Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/bgp_config_ifmap.h"
6 : #include "bgp/bgp_route.h"
7 :
8 : #include "bgp/bgp_peer.h"
9 : #include "bgp/bgp_server.h"
10 : #include "bgp/bgp_table.h"
11 : #include "bgp/extended-community/default_gateway.h"
12 : #include "bgp/extended-community/es_import.h"
13 : #include "bgp/extended-community/esi_label.h"
14 : #include "bgp/extended-community/etree.h"
15 : #include "bgp/extended-community/load_balance.h"
16 : #include "bgp/extended-community/mac_mobility.h"
17 : #include "bgp/extended-community/local_sequence_number.h"
18 : #include "bgp/extended-community/multicast_flags.h"
19 : #include "bgp/extended-community/router_mac.h"
20 : #include "bgp/extended-community/site_of_origin.h"
21 : #include "bgp/extended-community/source_as.h"
22 : #include "bgp/extended-community/sub_cluster.h"
23 : #include "bgp/extended-community/tag.h"
24 : #include "bgp/extended-community/vrf_route_import.h"
25 : #include "bgp/origin-vn/origin_vn.h"
26 : #include "bgp/routing-instance/routepath_replicator.h"
27 : #include "bgp/routing-instance/routing_instance.h"
28 : #include "bgp/security_group/security_group.h"
29 : #include "bgp/tunnel_encap/tunnel_encap.h"
30 : #include "bgp/large-community/tag.h"
31 :
32 : using std::string;
33 : using std::vector;
34 : using std::ostringstream;
35 :
36 3428070 : BgpRoute::BgpRoute() {
37 3427491 : }
38 :
39 3427900 : BgpRoute::~BgpRoute() {
40 3427900 : assert(GetPathList().empty());
41 3427658 : }
42 :
43 : //
44 : // Return the best path for this route.
45 : // Skip aliased paths.
46 : //
47 7274026 : const BgpPath *BgpRoute::BestPath() const {
48 7274026 : for (Route::PathList::const_iterator it = GetPathList().begin();
49 14543984 : it != GetPathList().end(); ++it) {
50 7270633 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
51 7270633 : if (path->GetFlags() & BgpPath::AliasedPath)
52 28 : continue;
53 7271413 : return path;
54 : }
55 835 : return NULL;
56 : }
57 :
58 : //
59 : // Insert given path and redo path selection.
60 : //
61 966423 : void BgpRoute::InsertPath(BgpPath *path) {
62 966423 : assert(!IsDeleted());
63 966414 : const Path *prev_front = front();
64 :
65 966366 : BgpTable *table = static_cast<BgpTable *>(get_table());
66 : // 'table' is not expected to be null, suspect it is checked here because of
67 : // unit tests.
68 966366 : if (table) {
69 : // Default Tunnel Encapsulation processing is done if configured for
70 : // the address family on the peer.
71 : // If routing policy is supported on the table(family)it is handled in
72 : // ProcessRoutingPolicy where other changes may be made to the
73 : // attributes. Also, when there are routing policy configuration changes
74 : // the attributes needs to be re-evaluated using the original attributes
75 : // and Default Tunnel Encapsulation also needs to be re-applied, this
76 : // will be handled seamlessly since ProcessRoutingPolicy will be called
77 : // in that case.
78 : // Note that currently routing policies are not supported on VPN address
79 : // families, however this is ensuring that it will be handed correctly
80 : // in future. Additionally, for labeled inet routes, routing policies
81 : // are supported so the Default Tunnel Encapsulation needs to be handled
82 : // in ProcessRoutingPolicy.
83 : // If the table(family) does not support routing policies the Default
84 : // Tunnel Encapsulation processing is handled here. The original and
85 : // modified attributes are saved and are not expected to be modified
86 : // further. Note that the configuration is not applied if the path
87 : // already has tunnel encapsulation specified.
88 :
89 965582 : if (table->IsRoutingPolicySupported()) {
90 450751 : if (!path->IsReplicated()) {
91 : // Add sub-cluster extended community to all routes
92 : // originated within a sub-cluster
93 64093 : uint32_t subcluster_id = SubClusterId();
94 64082 : if (subcluster_id) {
95 0 : path->AddExtCommunitySubCluster(subcluster_id);
96 : }
97 : }
98 450733 : RoutingInstance *rtinstance = table->routing_instance();
99 450735 : rtinstance->ProcessRoutingPolicy(this, path);
100 : } else {
101 514815 : IPeer *peer = path->GetPeer();
102 514883 : if (peer) {
103 : // Take snapshot of original attribute
104 262864 : BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
105 262875 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
106 : table->server()->extcomm_db(), table);
107 : BgpAttrPtr modified_attr =
108 262854 : table->server()->attr_db()->Locate(out_attr);
109 : // Update the path with new set of attributes
110 262875 : path->SetAttr(modified_attr, path->GetOriginalAttr());
111 262876 : }
112 : }
113 : }
114 966469 : insert(path);
115 :
116 966471 : Sort(&BgpTable::PathSelection, prev_front);
117 :
118 : // Update counters.
119 966433 : if (table)
120 965648 : table->UpdatePathCount(path, +1);
121 966514 : path->UpdatePeerRefCount(+1, table ? table->family() : Address::UNSPEC);
122 966532 : }
123 :
124 : //
125 : // Delete given path and redo path selection.
126 : //
127 965790 : void BgpRoute::DeletePath(BgpPath *path) {
128 965790 : const Path *prev_front = front();
129 :
130 965686 : remove(path);
131 966087 : Sort(&BgpTable::PathSelection, prev_front);
132 :
133 : // Update counters.
134 965697 : BgpTable *table = static_cast<BgpTable *>(get_table());
135 965678 : if (table)
136 964891 : table->UpdatePathCount(path, -1);
137 966312 : path->UpdatePeerRefCount(-1, table ? table->family() : Address::UNSPEC);
138 :
139 966215 : delete path;
140 966315 : }
141 :
142 : //
143 : // Find first path with given path source.
144 : // Skips secondary, aliased and resolved paths.
145 : //
146 1396 : const BgpPath *BgpRoute::FindPath(BgpPath::PathSource src) const {
147 1396 : for (Route::PathList::const_iterator it = GetPathList().begin();
148 2792 : it != GetPathList().end(); ++it) {
149 : // Skip secondary paths.
150 1396 : if (dynamic_cast<const BgpSecondaryPath *>(it.operator->())) {
151 0 : continue;
152 : }
153 :
154 1396 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
155 1396 : if (path->GetFlags() & BgpPath::AliasedPath) {
156 0 : continue;
157 : }
158 1396 : if (path->GetFlags() & BgpPath::ResolvedPath) {
159 0 : continue;
160 : }
161 1396 : if (path->GetSource() == src) {
162 1396 : return path;
163 : }
164 : }
165 0 : return NULL;
166 : }
167 :
168 : //
169 : // Find path added by BGP_XMPP peer.
170 : // Skips non BGP_XMPP, secondary, aliased and resolved paths.
171 : //
172 446217 : BgpPath *BgpRoute::FindPath(const IPeer *peer, bool include_secondary) {
173 446217 : for (Route::PathList::iterator it = GetPathList().begin();
174 1069171 : it != GetPathList().end(); ++it) {
175 282956 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
176 282956 : if (path->GetSource() != BgpPath::BGP_XMPP) {
177 787 : continue;
178 : }
179 282179 : if (path->GetFlags() & BgpPath::AliasedPath) {
180 0 : continue;
181 : }
182 282181 : if (path->GetFlags() & BgpPath::ResolvedPath) {
183 1307 : continue;
184 : }
185 561725 : if (!include_secondary &&
186 280862 : dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
187 821 : continue;
188 : }
189 280042 : if (path->GetPeer() == peer) {
190 194666 : return path;
191 : }
192 : }
193 251623 : return NULL;
194 : }
195 :
196 260 : const BgpPath *BgpRoute::FindPath(const IPeer *peer,
197 : bool include_secondary) const {
198 260 : return const_cast<BgpRoute *>(this)->FindPath(peer, include_secondary);
199 : }
200 :
201 : //
202 : // Find path with given nexthop address.
203 : // Skips non BGP_XMPP, aliased and resolved paths.
204 : //
205 140 : BgpPath *BgpRoute::FindPath(const IpAddress &nexthop) {
206 140 : for (Route::PathList::iterator it = GetPathList().begin();
207 576 : it != GetPathList().end(); ++it) {
208 216 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
209 216 : if (path->GetSource() != BgpPath::BGP_XMPP) {
210 0 : continue;
211 : }
212 216 : if (path->IsResolved() || path->IsAliased()) {
213 72 : continue;
214 : }
215 144 : if (path->GetAttr()->nexthop() == nexthop) {
216 68 : return path;
217 : }
218 : }
219 72 : return NULL;
220 : }
221 :
222 : //
223 : // Find path added by peer with given path id and path source.
224 : // Skips secondary, aliased and resolved paths.
225 : //
226 81418 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, const IPeer *peer,
227 : uint32_t path_id) {
228 81418 : for (Route::PathList::iterator it = GetPathList().begin();
229 170814 : it != GetPathList().end(); ++it) {
230 : // Skip secondary paths.
231 59743 : if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
232 94 : continue;
233 : }
234 :
235 59649 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
236 59649 : if (path->GetFlags() & BgpPath::AliasedPath) {
237 0 : continue;
238 : }
239 59649 : if (path->GetFlags() & BgpPath::ResolvedPath) {
240 151 : continue;
241 : }
242 115252 : if (path->GetPeer() == peer && path->GetPathId() == path_id &&
243 55754 : path->GetSource() == src) {
244 55754 : return path;
245 : }
246 : }
247 25664 : return NULL;
248 : }
249 :
250 : //
251 : // Find path added given source and path id - peer must be NULL.
252 : // Skips secondary paths and resolved paths.
253 : //
254 62515 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, uint32_t path_id) {
255 62515 : return FindPath(src, NULL, path_id);
256 : }
257 :
258 : //
259 : // Remove path added by peer with given path id and source.
260 : // Skips secondary paths.
261 : // Return true if the path is found and removed, false otherwise.
262 : //
263 64639 : bool BgpRoute::RemovePath(BgpPath::PathSource src, const IPeer *peer,
264 : uint32_t path_id) {
265 111204 : for (Route::PathList::iterator it = GetPathList().begin();
266 222408 : it != GetPathList().end(); it++) {
267 93533 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
268 :
269 : //
270 : // Skip secondary paths.
271 : //
272 93533 : if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
273 62 : continue;
274 : }
275 :
276 140441 : if (path->GetPeer() == peer && path->GetPathId() == path_id &&
277 46970 : path->GetSource() == src) {
278 46968 : DeletePath(path);
279 46968 : return true;
280 : }
281 : }
282 17671 : return false;
283 : }
284 :
285 : //
286 : // Remove path added given source and path id - peer must be NULL.
287 : // Skips secondary paths.
288 : // Return true if the path is found and removed, false otherwise.
289 : //
290 45287 : bool BgpRoute::RemovePath(BgpPath::PathSource src, uint32_t path_id) {
291 45287 : return RemovePath(src, NULL, path_id);
292 : }
293 :
294 : //
295 : // Remove path added by peer with given path id and source.
296 : // Skips secondary paths.
297 : // Return true if the path is found and removed, false otherwise.
298 : //
299 857 : bool BgpRoute::RemovePath(const IPeer *peer) {
300 857 : bool ret = false;
301 :
302 1714 : for (Route::PathList::iterator it = GetPathList().begin(), next = it;
303 3290 : it != GetPathList().end(); it = next) {
304 788 : next++;
305 788 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
306 :
307 : //
308 : // Skip secondary paths.
309 : //
310 788 : if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
311 0 : continue;
312 : }
313 :
314 788 : if (path->GetPeer() == peer) {
315 777 : DeletePath(path);
316 777 : ret = true;
317 : }
318 : }
319 857 : return ret;
320 : }
321 :
322 : //
323 : // Check if the route is usable.
324 : //
325 2429252 : bool BgpRoute::IsUsable() const {
326 2429252 : if (IsDeleted())
327 781520 : return false;
328 :
329 1647642 : const BgpPath *path = BestPath();
330 1647314 : if (!path || !path->IsFeasible())
331 7579 : return false;
332 :
333 1639704 : return true;
334 : }
335 :
336 : //
337 : // Check if the route is valid.
338 : //
339 83289 : bool BgpRoute::IsValid() const {
340 83289 : return IsUsable();
341 : }
342 :
343 : //
344 : // Check if there's a better path with the same forwarding information.
345 : //
346 : // Return true if we find such a path, false otherwise.
347 : //
348 : // The forwarding information we look at is just the next hop. We don't
349 : // consider the label since there's could be transient cases where we
350 : // have 2 paths with the same next hop and different labels. We don't
351 : // want to treat these as unique paths.
352 : //
353 26868 : bool BgpRoute::DuplicateForwardingPath(const BgpPath *in_path) const {
354 26868 : for (Route::PathList::const_iterator it = GetPathList().begin();
355 58152 : it != GetPathList().end(); ++it) {
356 29077 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
357 :
358 : // Bail if we reached the input path since the paths are sorted.
359 29077 : if (path == in_path)
360 26871 : return false;
361 :
362 : // Check the forwarding information.
363 3824 : if (path->GetAttr()->nexthop() == in_path->GetAttr()->nexthop())
364 1618 : return true;
365 : }
366 :
367 0 : return false;
368 : }
369 :
370 : //
371 : // Find the secondary path matching secondary replicated info.
372 : //
373 1466041 : BgpPath *BgpRoute::FindSecondaryPath(BgpRoute *src_rt,
374 : BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
375 1466041 : for (Route::PathList::iterator it = GetPathList().begin();
376 3488874 : it != GetPathList().end(); ++it) {
377 1226892 : BgpSecondaryPath *path = dynamic_cast<BgpSecondaryPath *>(
378 1226892 : it.operator->());
379 : // Skip resolved paths. They'll be taken care of by the path
380 : // resolver infrastructure.
381 2007307 : if (path && (src_rt->table()->IsVpnTable()) &&
382 780442 : (path->GetFlags() & BgpPath::ResolvedPath)) {
383 8 : continue;
384 : }
385 2239655 : if (path && path->src_rt() == src_rt &&
386 4415258 : path->GetPeer() == peer && path->GetPathId() == path_id &&
387 948486 : path->GetSource() == src) {
388 948768 : return path;
389 : }
390 : }
391 517489 : return NULL;
392 : }
393 :
394 : //
395 : // Remove the secondary path matching secondary replicated info.
396 : // Return true if the path is found and removed, false otherwise.
397 : //
398 578506 : bool BgpRoute::RemoveSecondaryPath(const BgpRoute *src_rt,
399 : BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
400 592436 : for (Route::PathList::iterator it = GetPathList().begin();
401 1184724 : it != GetPathList().end(); it++) {
402 : BgpSecondaryPath *path =
403 592330 : dynamic_cast<BgpSecondaryPath *>(it.operator->());
404 : // Skip resolved paths. They'll be taken care of by the path
405 : // resolver infrastructure.
406 960172 : if (path && (src_rt->table()->IsVpnTable()) &&
407 367856 : (path->GetFlags() & BgpPath::ResolvedPath)) {
408 0 : continue;
409 : }
410 1180148 : if (path && path->src_rt() == src_rt &&
411 2350954 : path->GetPeer() == peer && path->GetPathId() == path_id &&
412 578263 : path->GetSource() == src) {
413 578558 : DeletePath(path);
414 578988 : return true;
415 : }
416 : }
417 :
418 32 : return false;
419 : }
420 :
421 538101 : size_t BgpRoute::count() const {
422 538101 : return GetPathList().size();
423 : }
424 :
425 1230042 : BgpTable *BgpRoute::table() {
426 1230042 : return dynamic_cast<BgpTable *>(get_table_partition()->parent());
427 : }
428 :
429 1357874 : const BgpTable *BgpRoute::table() const {
430 1357874 : return dynamic_cast<BgpTable *>(get_table_partition()->parent());
431 : }
432 :
433 148 : void BgpRoute::FillRouteInfo(const BgpTable *table,
434 : ShowRouteBrief *show_route) const {
435 148 : show_route->set_prefix(ToString());
436 148 : vector<ShowRoutePathBrief> show_route_paths;
437 148 : for (Route::PathList::const_iterator it = GetPathList().begin();
438 780 : it != GetPathList().end(); ++it) {
439 242 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
440 242 : ShowRoutePathBrief srp;
441 242 : const IPeer *peer = path->GetPeer();
442 242 : if (peer) {
443 16 : srp.set_source(peer->ToString());
444 : }
445 :
446 242 : srp.set_protocol(path->GetSourceString());
447 :
448 242 : const BgpAttr *attr = path->GetAttr();
449 242 : srp.set_local_preference(attr->local_pref());
450 242 : srp.set_med(attr->med());
451 242 : srp.set_next_hop(attr->nexthop().to_string());
452 242 : srp.set_label(path->GetLabel());
453 242 : show_route_paths.push_back(srp);
454 242 : }
455 148 : show_route->set_paths(show_route_paths);
456 148 : }
457 :
458 0 : static void FillRoutePathClusterListInfo(const ClusterList *clist,
459 : ShowRoutePath *show_path) {
460 0 : const vector<uint32_t> &list = clist->cluster_list().cluster_list;
461 0 : vector<string> cluster_list = vector<string>();
462 0 : for (vector<uint32_t>::const_iterator it = list.begin(); it != list.end();
463 0 : ++it) {
464 0 : cluster_list.push_back(Ip4Address(*it).to_string());
465 : }
466 0 : show_path->set_cluster_list(cluster_list);
467 0 : }
468 :
469 192 : static void FillRoutePathCommunityInfo(const Community *comm,
470 : ShowRoutePath *show_path, vector<string> *communities) {
471 192 : comm->BuildStringList(communities);
472 192 : }
473 :
474 328 : static void FillRoutePathExtCommunityInfo(const BgpTable *table,
475 : const ExtCommunity *extcomm,
476 : ShowRoutePath *show_path, vector<string> *communities) {
477 328 : const RoutingInstance *ri = table->routing_instance();
478 328 : const RoutingInstanceMgr *ri_mgr = ri->manager();
479 328 : vector<string> tunnel_encap = vector<string>();
480 :
481 328 : const ExtCommunity::ExtCommunityList &v = extcomm->communities();
482 328 : for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
483 867 : it != v.end(); ++it) {
484 539 : if (ExtCommunity::is_route_target(*it)) {
485 107 : RouteTarget rt(*it);
486 107 : communities->push_back(rt.ToString());
487 432 : } else if (ExtCommunity::is_default_gateway(*it)) {
488 0 : DefaultGateway dgw(*it);
489 0 : communities->push_back(dgw.ToString());
490 432 : } else if (ExtCommunity::is_es_import(*it)) {
491 0 : EsImport es_import(*it);
492 0 : communities->push_back(es_import.ToString());
493 432 : } else if (ExtCommunity::is_esi_label(*it)) {
494 0 : EsiLabel esi_label(*it);
495 0 : communities->push_back(esi_label.ToString());
496 432 : } else if (ExtCommunity::is_mac_mobility(*it)) {
497 0 : MacMobility mm(*it);
498 0 : communities->push_back(mm.ToString());
499 0 : show_path->set_sequence_no(integerToString(mm.sequence_number()));
500 432 : } else if (ExtCommunity::is_local_sequence_number(*it)) {
501 0 : LocalSequenceNumber lsn(*it);
502 0 : communities->push_back(lsn.ToString());
503 432 : } else if (ExtCommunity::is_etree(*it)) {
504 2 : ETree etree(*it);
505 2 : communities->push_back(etree.ToString());
506 430 : } else if (ExtCommunity::is_router_mac(*it)) {
507 0 : RouterMac router_mac(*it);
508 0 : communities->push_back(router_mac.ToString());
509 430 : } else if (ExtCommunity::is_origin_vn(*it)) {
510 287 : OriginVn origin_vn(*it);
511 287 : communities->push_back(origin_vn.ToString());
512 287 : int vn_index = origin_vn.vn_index();
513 287 : show_path->set_origin_vn(
514 574 : ri_mgr->GetVirtualNetworkByVnIndex(vn_index));
515 143 : } else if (ExtCommunity::is_security_group(*it)) {
516 19 : SecurityGroup sg(*it);
517 19 : communities->push_back(sg.ToString());
518 124 : } else if (ExtCommunity::is_security_group4(*it)) {
519 0 : SecurityGroup4ByteAs sg(*it);
520 0 : communities->push_back(sg.ToString());
521 124 : } else if (ExtCommunity::is_site_of_origin(*it)) {
522 0 : SiteOfOrigin soo(*it);
523 0 : communities->push_back(soo.ToString());
524 124 : } else if (ExtCommunity::is_tunnel_encap(*it)) {
525 124 : TunnelEncap encap(*it);
526 124 : communities->push_back(encap.ToString());
527 124 : TunnelEncapType::Encap id = encap.tunnel_encap();
528 124 : tunnel_encap.push_back(TunnelEncapType::TunnelEncapToString(id));
529 0 : } else if (ExtCommunity::is_load_balance(*it)) {
530 0 : LoadBalance load_balance(*it);
531 0 : communities->push_back(load_balance.ToString());
532 :
533 0 : ShowLoadBalance show_load_balance;
534 0 : load_balance.ShowAttribute(&show_load_balance);
535 0 : show_path->set_load_balance(show_load_balance);
536 0 : } else if (ExtCommunity::is_tag(*it)) {
537 0 : Tag tag(*it);
538 0 : communities->push_back(tag.ToString());
539 0 : } else if (ExtCommunity::is_tag4(*it)) {
540 0 : Tag4ByteAs tag(*it);
541 0 : communities->push_back(tag.ToString());
542 0 : } else if (ExtCommunity::is_source_as(*it)) {
543 0 : SourceAs sas(*it);
544 0 : communities->push_back(sas.ToString());
545 0 : } else if (ExtCommunity::is_sub_cluster(*it)) {
546 0 : SubCluster sc(*it);
547 0 : communities->push_back(sc.ToString());
548 0 : } else if (ExtCommunity::is_vrf_route_import(*it)) {
549 0 : VrfRouteImport rt_import(*it);
550 0 : communities->push_back(rt_import.ToString());
551 0 : } else if (ExtCommunity::is_multicast_flags(*it)) {
552 0 : MulticastFlags mf(*it);
553 0 : communities->push_back(mf.ToString());
554 : } else {
555 : char temp[50];
556 0 : int len = snprintf(temp, sizeof(temp), "ext community: ");
557 0 : for (size_t i = 0; i < it->size(); i++) {
558 0 : len += snprintf(temp+len, sizeof(temp) - len, "%02x", (*it)[i]);
559 : }
560 0 : communities->push_back(string(temp));
561 : }
562 : }
563 328 : show_path->set_tunnel_encap(tunnel_encap);
564 328 : }
565 :
566 314 : static void FillRoutePathLargeCommunityInfo(const LargeCommunity *largecomm,
567 : ShowRoutePath *show_path, vector<string> *communities) {
568 :
569 314 : const LargeCommunity::LargeCommunityList &v = largecomm->communities();
570 314 : for (const auto &lc : v) {
571 0 : if (LargeCommunity::is_tag(lc)) {
572 0 : TagLC tag(lc);
573 0 : communities->push_back(tag.ToString());
574 : } else {
575 : char temp[50];
576 0 : int len = snprintf(temp, sizeof(temp), "large community: ");
577 0 : for (size_t i = 0; i < lc.size(); i++) {
578 0 : len += snprintf(temp + len, sizeof(temp) - len, "%02x",
579 0 : lc[i]);
580 : }
581 0 : communities->push_back(string(temp));
582 : }
583 : }
584 314 : }
585 :
586 8 : static void FillEdgeForwardingInfo(const EdgeForwarding *edge_forwarding,
587 : ShowRoutePath *show_path) {
588 8 : vector<ShowEdgeForwarding> show_ef_list;
589 : vector<EdgeForwardingSpec::Edge *> edge_list =
590 8 : edge_forwarding->edge_forwarding().edge_list;
591 8 : for (vector<EdgeForwardingSpec::Edge *>::const_iterator it =
592 8 : edge_list.begin(); it != edge_list.end(); ++it) {
593 0 : const EdgeForwardingSpec::Edge *edge = *it;
594 0 : ShowEdgeForwarding show_ef;
595 0 : ostringstream oss;
596 0 : oss << edge->GetInboundIp4Address() << ":" << edge->inbound_label;
597 0 : show_ef.set_in_address_label(oss.str());
598 0 : oss.str("");
599 0 : oss.clear();
600 0 : oss << edge->GetOutboundIp4Address() << ":" << edge->outbound_label;
601 0 : show_ef.set_out_address_label(oss.str());
602 0 : show_ef_list.push_back(show_ef);
603 0 : }
604 8 : show_path->set_edge_forwarding(show_ef_list);
605 8 : }
606 :
607 8 : static void FillEdgeDiscoveryInfo(const EdgeDiscovery *edge_discovery,
608 : ShowRoutePath *show_path) {
609 8 : vector<ShowEdgeDiscovery> show_ed_list;
610 : vector<EdgeDiscoverySpec::Edge *> edge_list =
611 8 : edge_discovery->edge_discovery().edge_list;
612 8 : int idx = 0;
613 8 : for (vector<EdgeDiscoverySpec::Edge *>::const_iterator it =
614 8 : edge_list.begin();
615 32 : it != edge_list.end(); ++it, ++idx) {
616 24 : const EdgeDiscoverySpec::Edge *edge = *it;
617 24 : ShowEdgeDiscovery show_ed;
618 24 : ostringstream oss;
619 : uint32_t first_label, last_label;
620 24 : oss << edge->GetIp4Address();
621 24 : show_ed.set_address(oss.str());
622 24 : oss.str("");
623 24 : oss.clear();
624 24 : edge->GetLabels(&first_label, &last_label);
625 24 : oss << first_label << "-" << last_label;
626 24 : show_ed.set_labels(oss.str());
627 24 : show_ed_list.push_back(show_ed);
628 24 : }
629 8 : show_path->set_edge_discovery(show_ed_list);
630 8 : }
631 :
632 192 : static void FillOriginVnPathInfo(const OriginVnPath *ovnpath,
633 : ShowRoutePath *show_path) {
634 192 : const OriginVnPath::OriginVnList &v = ovnpath->origin_vns();
635 192 : vector<string> origin_vn_path = vector<string>();
636 192 : for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
637 384 : it != v.end(); ++it) {
638 192 : OriginVn origin_vn(*it);
639 192 : origin_vn_path.push_back(origin_vn.ToString());
640 : }
641 192 : show_path->set_origin_vn_path(origin_vn_path);
642 192 : }
643 :
644 0 : static void FillPmsiTunnelInfo(const PmsiTunnel *pmsi_tunnel,
645 : const ExtCommunity *ext, ShowRoutePath *show_path) {
646 0 : ShowPmsiTunnel spt;
647 0 : spt.set_type(pmsi_tunnel->pmsi_tunnel().GetTunnelTypeString());
648 0 : spt.set_ar_type(pmsi_tunnel->pmsi_tunnel().GetTunnelArTypeString());
649 0 : spt.set_identifier(pmsi_tunnel->identifier().to_string());
650 0 : spt.set_label(pmsi_tunnel->GetLabel(ext));
651 0 : spt.set_flags(pmsi_tunnel->pmsi_tunnel().GetTunnelFlagsStrings());
652 0 : show_path->set_pmsi_tunnel(spt);
653 0 : }
654 :
655 6329 : void BgpRoute::FillRouteInfo(const BgpTable *table,
656 : ShowRoute *show_route, const string &source, const string &protocol) const {
657 6329 : const RoutingInstance *ri = table->routing_instance();
658 :
659 6329 : show_route->set_prefix(ToString());
660 6346 : show_route->set_last_modified(
661 12690 : integerToString(UTCUsecToPTime(last_change_at())));
662 :
663 6346 : vector<ShowRoutePath> show_route_paths;
664 6345 : for (Route::PathList::const_iterator it = GetPathList().begin();
665 25455 : it != GetPathList().end(); ++it) {
666 6397 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
667 6397 : ShowRoutePath srp;
668 6397 : const IPeer *peer = path->GetPeer();
669 :
670 : // Filter against peer source, if specified.
671 6396 : if (!source.empty() && (!peer || source != peer->ToString()))
672 599 : continue;
673 :
674 : // Filter against path protocol, if specified.
675 5797 : if (!protocol.empty() && protocol != path->GetSourceString())
676 195 : continue;
677 :
678 5602 : if (peer) {
679 5250 : srp.set_source(peer->ToString());
680 : }
681 :
682 5605 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
683 5605 : if (bgp_peer) {
684 5196 : srp.set_local_as(bgp_peer->local_as());
685 5195 : srp.set_peer_as(bgp_peer->peer_as());
686 5194 : srp.set_peer_router_id(bgp_peer->bgp_identifier_string());
687 : }
688 :
689 5605 : const BgpAttr *attr = path->GetAttr();
690 5609 : if (attr->edge_forwarding()) {
691 8 : FillEdgeForwardingInfo(attr->edge_forwarding(), &srp);
692 : }
693 5609 : if (attr->edge_discovery()) {
694 8 : FillEdgeDiscoveryInfo(attr->edge_discovery(), &srp);
695 : }
696 5609 : if (attr->sub_protocol().empty()) {
697 5597 : srp.set_protocol(path->GetSourceString());
698 : } else {
699 12 : const string sbp = attr->sub_protocol();
700 12 : srp.set_protocol(path->GetSourceString() + " (" + sbp + ")");
701 12 : }
702 5607 : srp.set_origin(attr->origin_string());
703 5605 : if (attr->as_path() != NULL)
704 5235 : srp.set_as_path(attr->as_path()->path().ToString());
705 369 : else if (attr->aspath_4byte() != NULL)
706 0 : srp.set_as_path(attr->aspath_4byte()->path().ToString());
707 5606 : if (attr->as4_path() != NULL)
708 6 : srp.set_as4_path(attr->as4_path()->path().ToString());
709 5606 : srp.set_local_preference(attr->local_pref());
710 5605 : srp.set_med(attr->med());
711 5604 : srp.set_next_hop(attr->nexthop().to_string());
712 5610 : srp.set_label(path->GetLabel());
713 5609 : srp.set_flags(path->GetFlagsStringList());
714 5610 : srp.set_last_modified(
715 11212 : integerToString(UTCUsecToPTime(path->time_stamp_usecs())));
716 5610 : if (path->IsReplicated()) {
717 : const BgpSecondaryPath *replicated;
718 101 : replicated = static_cast<const BgpSecondaryPath *>(path);
719 101 : srp.set_replicated(true);
720 101 : srp.set_primary_table(replicated->src_table()->name());
721 : } else {
722 5508 : srp.set_replicated(false);
723 : Address::Family vpn_family =
724 5507 : Address::VpnFamilyFromFamily(table->family());
725 : const RoutePathReplicator *replicator =
726 5505 : table->server()->replicator(vpn_family);
727 5504 : if (replicator) {
728 5420 : srp.set_secondary_tables(
729 10845 : replicator->GetReplicatedTableNameList(table, this, path));
730 : }
731 : }
732 5596 : if (attr->cluster_list()) {
733 0 : FillRoutePathClusterListInfo(attr->cluster_list(), &srp);
734 : }
735 5595 : vector<string> communities;
736 5595 : if (attr->community()) {
737 192 : FillRoutePathCommunityInfo(attr->community(), &srp, &communities);
738 : }
739 5595 : if (attr->ext_community()) {
740 328 : FillRoutePathExtCommunityInfo(table, attr->ext_community(), &srp,
741 : &communities);
742 : }
743 5595 : if (attr->large_community()) {
744 314 : FillRoutePathLargeCommunityInfo(attr->large_community(), &srp,
745 : &communities);
746 : }
747 5595 : if (!communities.empty()){
748 304 : srp.set_communities(communities);
749 : }
750 5594 : if (srp.get_origin_vn().empty() &&
751 5594 : !table->IsVpnTable() && path->IsVrfOriginated()) {
752 5286 : srp.set_origin_vn(ri->GetVirtualNetworkName());
753 : }
754 5591 : if (attr->origin_vn_path()) {
755 192 : FillOriginVnPathInfo(attr->origin_vn_path(), &srp);
756 : }
757 5592 : if (attr->pmsi_tunnel()) {
758 0 : const ExtCommunity *extcomm = attr->ext_community();
759 0 : if (extcomm) {
760 0 : FillPmsiTunnelInfo(attr->pmsi_tunnel(), extcomm, &srp);
761 : }
762 : }
763 5592 : if (attr->originator_id().to_ulong()) {
764 0 : srp.set_originator_id(attr->originator_id().to_string());
765 : }
766 :
767 5591 : show_route_paths.push_back(srp);
768 6379 : }
769 6326 : show_route->set_paths(show_route_paths);
770 6320 : }
771 :
772 51746 : void BgpRoute::NotifyOrDelete() {
773 51746 : if (!front()) {
774 48080 : Delete();
775 : } else {
776 3666 : Notify();
777 : }
778 51746 : }
779 :
780 64092 : uint32_t BgpRoute::SubClusterId() const {
781 64092 : BgpTable *table = static_cast<BgpTable *>(get_table());
782 64093 : const BgpConfigManager *config_manager_ = table->server()->config_manager();
783 64091 : if (!config_manager_) {
784 0 : return 0;
785 : }
786 : const BgpProtocolConfig *proto =
787 64091 : config_manager_->GetProtocolConfig(BgpConfigManager::kMasterInstance);
788 64082 : if (!proto) {
789 2623 : return 0;
790 : }
791 61459 : return proto->subcluster_id();
792 : }
|