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 3420462 : BgpRoute::BgpRoute() {
37 3420073 : }
38 :
39 3420404 : BgpRoute::~BgpRoute() {
40 3420404 : assert(GetPathList().empty());
41 3420187 : }
42 :
43 : //
44 : // Return the best path for this route.
45 : // Skip aliased paths.
46 : //
47 7325536 : const BgpPath *BgpRoute::BestPath() const {
48 7325536 : for (Route::PathList::const_iterator it = GetPathList().begin();
49 14647294 : it != GetPathList().end(); ++it) {
50 7322326 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
51 7322326 : if (path->GetFlags() & BgpPath::AliasedPath)
52 28 : continue;
53 7323124 : return path;
54 : }
55 781 : return NULL;
56 : }
57 :
58 : //
59 : // Insert given path and redo path selection.
60 : //
61 966675 : void BgpRoute::InsertPath(BgpPath *path) {
62 966675 : assert(!IsDeleted());
63 966677 : const Path *prev_front = front();
64 :
65 966618 : 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 966628 : 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 965844 : if (table->IsRoutingPolicySupported()) {
90 451093 : if (!path->IsReplicated()) {
91 : // Add sub-cluster extended community to all routes
92 : // originated within a sub-cluster
93 64060 : uint32_t subcluster_id = SubClusterId();
94 64049 : if (subcluster_id) {
95 0 : path->AddExtCommunitySubCluster(subcluster_id);
96 : }
97 : }
98 451082 : RoutingInstance *rtinstance = table->routing_instance();
99 451085 : rtinstance->ProcessRoutingPolicy(this, path);
100 : } else {
101 514729 : IPeer *peer = path->GetPeer();
102 514829 : if (peer) {
103 : // Take snapshot of original attribute
104 262669 : BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
105 262684 : peer->ProcessPathTunnelEncapsulation(path, out_attr,
106 : table->server()->extcomm_db(), table);
107 : BgpAttrPtr modified_attr =
108 262664 : table->server()->attr_db()->Locate(out_attr);
109 : // Update the path with new set of attributes
110 262685 : path->SetAttr(modified_attr, path->GetOriginalAttr());
111 262685 : }
112 : }
113 : }
114 966783 : insert(path);
115 :
116 966736 : Sort(&BgpTable::PathSelection, prev_front);
117 :
118 : // Update counters.
119 966691 : if (table)
120 965906 : table->UpdatePathCount(path, +1);
121 966817 : path->UpdatePeerRefCount(+1, table ? table->family() : Address::UNSPEC);
122 966808 : }
123 :
124 : //
125 : // Delete given path and redo path selection.
126 : //
127 965720 : void BgpRoute::DeletePath(BgpPath *path) {
128 965720 : const Path *prev_front = front();
129 :
130 965547 : remove(path);
131 966133 : Sort(&BgpTable::PathSelection, prev_front);
132 :
133 : // Update counters.
134 965674 : BgpTable *table = static_cast<BgpTable *>(get_table());
135 965646 : if (table)
136 964858 : table->UpdatePathCount(path, -1);
137 966407 : path->UpdatePeerRefCount(-1, table ? table->family() : Address::UNSPEC);
138 :
139 966223 : delete path;
140 966482 : }
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 446329 : BgpPath *BgpRoute::FindPath(const IPeer *peer, bool include_secondary) {
173 446329 : for (Route::PathList::iterator it = GetPathList().begin();
174 1070327 : it != GetPathList().end(); ++it) {
175 283478 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
176 283478 : if (path->GetSource() != BgpPath::BGP_XMPP) {
177 745 : continue;
178 : }
179 282763 : if (path->GetFlags() & BgpPath::AliasedPath) {
180 0 : continue;
181 : }
182 282763 : if (path->GetFlags() & BgpPath::ResolvedPath) {
183 1298 : continue;
184 : }
185 562916 : if (!include_secondary &&
186 281456 : dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
187 842 : continue;
188 : }
189 280618 : if (path->GetPeer() == peer) {
190 194763 : return path;
191 : }
192 : }
193 251677 : 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 136 : BgpPath *BgpRoute::FindPath(const IpAddress &nexthop) {
206 136 : for (Route::PathList::iterator it = GetPathList().begin();
207 574 : it != GetPathList().end(); ++it) {
208 213 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
209 213 : if (path->GetSource() != BgpPath::BGP_XMPP) {
210 0 : continue;
211 : }
212 213 : if (path->IsResolved() || path->IsAliased()) {
213 74 : continue;
214 : }
215 140 : if (path->GetAttr()->nexthop() == nexthop) {
216 62 : return path;
217 : }
218 : }
219 74 : 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 81495 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, const IPeer *peer,
227 : uint32_t path_id) {
228 81495 : for (Route::PathList::iterator it = GetPathList().begin();
229 170872 : it != GetPathList().end(); ++it) {
230 : // Skip secondary paths.
231 59773 : if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
232 79 : continue;
233 : }
234 :
235 59694 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
236 59694 : if (path->GetFlags() & BgpPath::AliasedPath) {
237 0 : continue;
238 : }
239 59694 : if (path->GetFlags() & BgpPath::ResolvedPath) {
240 151 : continue;
241 : }
242 115375 : if (path->GetPeer() == peer && path->GetPathId() == path_id &&
243 55832 : path->GetSource() == src) {
244 55832 : return path;
245 : }
246 : }
247 25663 : 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 62512 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, uint32_t path_id) {
255 62512 : 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 64750 : bool BgpRoute::RemovePath(BgpPath::PathSource src, const IPeer *peer,
264 : uint32_t path_id) {
265 111486 : for (Route::PathList::iterator it = GetPathList().begin();
266 222972 : it != GetPathList().end(); it++) {
267 93828 : BgpPath *path = static_cast<BgpPath *>(it.operator->());
268 :
269 : //
270 : // Skip secondary paths.
271 : //
272 93828 : if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
273 55 : continue;
274 : }
275 :
276 140867 : if (path->GetPeer() == peer && path->GetPathId() == path_id &&
277 47094 : path->GetSource() == src) {
278 47092 : DeletePath(path);
279 47092 : return true;
280 : }
281 : }
282 17658 : 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 45396 : bool BgpRoute::RemovePath(BgpPath::PathSource src, uint32_t path_id) {
291 45396 : 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 2445459 : bool BgpRoute::IsUsable() const {
326 2445459 : if (IsDeleted())
327 781711 : return false;
328 :
329 1663582 : const BgpPath *path = BestPath();
330 1663296 : if (!path || !path->IsFeasible())
331 7670 : return false;
332 :
333 1655580 : return true;
334 : }
335 :
336 : //
337 : // Check if the route is valid.
338 : //
339 83516 : bool BgpRoute::IsValid() const {
340 83516 : 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 26986 : bool BgpRoute::DuplicateForwardingPath(const BgpPath *in_path) const {
354 26986 : for (Route::PathList::const_iterator it = GetPathList().begin();
355 58314 : it != GetPathList().end(); ++it) {
356 29158 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
357 :
358 : // Bail if we reached the input path since the paths are sorted.
359 29158 : if (path == in_path)
360 26988 : return false;
361 :
362 : // Check the forwarding information.
363 3806 : if (path->GetAttr()->nexthop() == in_path->GetAttr()->nexthop())
364 1636 : return true;
365 : }
366 :
367 0 : return false;
368 : }
369 :
370 : //
371 : // Find the secondary path matching secondary replicated info.
372 : //
373 1460437 : BgpPath *BgpRoute::FindSecondaryPath(BgpRoute *src_rt,
374 : BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
375 1460437 : for (Route::PathList::iterator it = GetPathList().begin();
376 3477969 : it != GetPathList().end(); ++it) {
377 1221212 : BgpSecondaryPath *path = dynamic_cast<BgpSecondaryPath *>(
378 1221212 : it.operator->());
379 : // Skip resolved paths. They'll be taken care of by the path
380 : // resolver infrastructure.
381 1996089 : if (path && (src_rt->table()->IsVpnTable()) &&
382 774910 : (path->GetFlags() & BgpPath::ResolvedPath)) {
383 8 : continue;
384 : }
385 2229044 : if (path && path->src_rt() == src_rt &&
386 4393374 : path->GetPeer() == peer && path->GetPathId() == path_id &&
387 942694 : path->GetSource() == src) {
388 943199 : return path;
389 : }
390 : }
391 517718 : 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 578671 : bool BgpRoute::RemoveSecondaryPath(const BgpRoute *src_rt,
399 : BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
400 592868 : for (Route::PathList::iterator it = GetPathList().begin();
401 1185432 : it != GetPathList().end(); it++) {
402 : BgpSecondaryPath *path =
403 592692 : dynamic_cast<BgpSecondaryPath *>(it.operator->());
404 : // Skip resolved paths. They'll be taken care of by the path
405 : // resolver infrastructure.
406 961172 : if (path && (src_rt->table()->IsVpnTable()) &&
407 368507 : (path->GetFlags() & BgpPath::ResolvedPath)) {
408 0 : continue;
409 : }
410 1181196 : if (path && path->src_rt() == src_rt &&
411 2352548 : path->GetPeer() == peer && path->GetPathId() == path_id &&
412 578341 : path->GetSource() == src) {
413 578747 : DeletePath(path);
414 579336 : return true;
415 : }
416 : }
417 :
418 5 : return false;
419 : }
420 :
421 537962 : size_t BgpRoute::count() const {
422 537962 : return GetPathList().size();
423 : }
424 :
425 1224605 : BgpTable *BgpRoute::table() {
426 1224605 : return dynamic_cast<BgpTable *>(get_table_partition()->parent());
427 : }
428 :
429 1359120 : const BgpTable *BgpRoute::table() const {
430 1359120 : 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 324 : static void FillRoutePathExtCommunityInfo(const BgpTable *table,
475 : const ExtCommunity *extcomm,
476 : ShowRoutePath *show_path, vector<string> *communities) {
477 324 : const RoutingInstance *ri = table->routing_instance();
478 324 : const RoutingInstanceMgr *ri_mgr = ri->manager();
479 324 : vector<string> tunnel_encap = vector<string>();
480 :
481 324 : const ExtCommunity::ExtCommunityList &v = extcomm->communities();
482 324 : for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
483 853 : it != v.end(); ++it) {
484 529 : if (ExtCommunity::is_route_target(*it)) {
485 103 : RouteTarget rt(*it);
486 103 : communities->push_back(rt.ToString());
487 426 : } else if (ExtCommunity::is_default_gateway(*it)) {
488 0 : DefaultGateway dgw(*it);
489 0 : communities->push_back(dgw.ToString());
490 426 : } else if (ExtCommunity::is_es_import(*it)) {
491 0 : EsImport es_import(*it);
492 0 : communities->push_back(es_import.ToString());
493 426 : } else if (ExtCommunity::is_esi_label(*it)) {
494 0 : EsiLabel esi_label(*it);
495 0 : communities->push_back(esi_label.ToString());
496 426 : } 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 426 : } else if (ExtCommunity::is_local_sequence_number(*it)) {
501 0 : LocalSequenceNumber lsn(*it);
502 0 : communities->push_back(lsn.ToString());
503 426 : } else if (ExtCommunity::is_etree(*it)) {
504 2 : ETree etree(*it);
505 2 : communities->push_back(etree.ToString());
506 424 : } else if (ExtCommunity::is_router_mac(*it)) {
507 0 : RouterMac router_mac(*it);
508 0 : communities->push_back(router_mac.ToString());
509 424 : } else if (ExtCommunity::is_origin_vn(*it)) {
510 285 : OriginVn origin_vn(*it);
511 285 : communities->push_back(origin_vn.ToString());
512 285 : int vn_index = origin_vn.vn_index();
513 285 : show_path->set_origin_vn(
514 570 : ri_mgr->GetVirtualNetworkByVnIndex(vn_index));
515 139 : } else if (ExtCommunity::is_security_group(*it)) {
516 19 : SecurityGroup sg(*it);
517 19 : communities->push_back(sg.ToString());
518 120 : } else if (ExtCommunity::is_security_group4(*it)) {
519 0 : SecurityGroup4ByteAs sg(*it);
520 0 : communities->push_back(sg.ToString());
521 120 : } else if (ExtCommunity::is_site_of_origin(*it)) {
522 0 : SiteOfOrigin soo(*it);
523 0 : communities->push_back(soo.ToString());
524 120 : } else if (ExtCommunity::is_tunnel_encap(*it)) {
525 120 : TunnelEncap encap(*it);
526 120 : communities->push_back(encap.ToString());
527 120 : TunnelEncapType::Encap id = encap.tunnel_encap();
528 120 : 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 324 : show_path->set_tunnel_encap(tunnel_encap);
564 324 : }
565 :
566 310 : static void FillRoutePathLargeCommunityInfo(const LargeCommunity *largecomm,
567 : ShowRoutePath *show_path, vector<string> *communities) {
568 :
569 310 : const LargeCommunity::LargeCommunityList &v = largecomm->communities();
570 310 : 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 310 : }
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 6321 : void BgpRoute::FillRouteInfo(const BgpTable *table,
656 : ShowRoute *show_route, const string &source, const string &protocol) const {
657 6321 : const RoutingInstance *ri = table->routing_instance();
658 :
659 6321 : show_route->set_prefix(ToString());
660 6339 : show_route->set_last_modified(
661 12670 : integerToString(UTCUsecToPTime(last_change_at())));
662 :
663 6337 : vector<ShowRoutePath> show_route_paths;
664 6334 : for (Route::PathList::const_iterator it = GetPathList().begin();
665 25422 : it != GetPathList().end(); ++it) {
666 6388 : const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
667 6388 : ShowRoutePath srp;
668 6383 : const IPeer *peer = path->GetPeer();
669 :
670 : // Filter against peer source, if specified.
671 6383 : if (!source.empty() && (!peer || source != peer->ToString()))
672 596 : continue;
673 :
674 : // Filter against path protocol, if specified.
675 5787 : if (!protocol.empty() && protocol != path->GetSourceString())
676 195 : continue;
677 :
678 5591 : if (peer) {
679 5239 : srp.set_source(peer->ToString());
680 : }
681 :
682 5590 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
683 5590 : if (bgp_peer) {
684 5189 : srp.set_local_as(bgp_peer->local_as());
685 5188 : srp.set_peer_as(bgp_peer->peer_as());
686 5186 : srp.set_peer_router_id(bgp_peer->bgp_identifier_string());
687 : }
688 :
689 5589 : const BgpAttr *attr = path->GetAttr();
690 5601 : if (attr->edge_forwarding()) {
691 8 : FillEdgeForwardingInfo(attr->edge_forwarding(), &srp);
692 : }
693 5600 : if (attr->edge_discovery()) {
694 8 : FillEdgeDiscoveryInfo(attr->edge_discovery(), &srp);
695 : }
696 5600 : if (attr->sub_protocol().empty()) {
697 5588 : 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 5595 : srp.set_origin(attr->origin_string());
703 5592 : if (attr->as_path() != NULL)
704 5228 : srp.set_as_path(attr->as_path()->path().ToString());
705 365 : else if (attr->aspath_4byte() != NULL)
706 0 : srp.set_as_path(attr->aspath_4byte()->path().ToString());
707 5600 : if (attr->as4_path() != NULL)
708 5 : srp.set_as4_path(attr->as4_path()->path().ToString());
709 5600 : srp.set_local_preference(attr->local_pref());
710 5599 : srp.set_med(attr->med());
711 5598 : srp.set_next_hop(attr->nexthop().to_string());
712 5602 : srp.set_label(path->GetLabel());
713 5602 : srp.set_flags(path->GetFlagsStringList());
714 5603 : srp.set_last_modified(
715 11193 : integerToString(UTCUsecToPTime(path->time_stamp_usecs())));
716 5599 : if (path->IsReplicated()) {
717 : const BgpSecondaryPath *replicated;
718 99 : replicated = static_cast<const BgpSecondaryPath *>(path);
719 99 : srp.set_replicated(true);
720 99 : srp.set_primary_table(replicated->src_table()->name());
721 : } else {
722 5501 : srp.set_replicated(false);
723 : Address::Family vpn_family =
724 5500 : Address::VpnFamilyFromFamily(table->family());
725 : const RoutePathReplicator *replicator =
726 5499 : table->server()->replicator(vpn_family);
727 5498 : if (replicator) {
728 5416 : srp.set_secondary_tables(
729 10836 : replicator->GetReplicatedTableNameList(table, this, path));
730 : }
731 : }
732 5588 : if (attr->cluster_list()) {
733 0 : FillRoutePathClusterListInfo(attr->cluster_list(), &srp);
734 : }
735 5588 : vector<string> communities;
736 5588 : if (attr->community()) {
737 192 : FillRoutePathCommunityInfo(attr->community(), &srp, &communities);
738 : }
739 5588 : if (attr->ext_community()) {
740 324 : FillRoutePathExtCommunityInfo(table, attr->ext_community(), &srp,
741 : &communities);
742 : }
743 5588 : if (attr->large_community()) {
744 310 : FillRoutePathLargeCommunityInfo(attr->large_community(), &srp,
745 : &communities);
746 : }
747 5588 : if (!communities.empty()){
748 300 : srp.set_communities(communities);
749 : }
750 5588 : if (srp.get_origin_vn().empty() &&
751 5588 : !table->IsVpnTable() && path->IsVrfOriginated()) {
752 5285 : srp.set_origin_vn(ri->GetVirtualNetworkName());
753 : }
754 5586 : if (attr->origin_vn_path()) {
755 192 : FillOriginVnPathInfo(attr->origin_vn_path(), &srp);
756 : }
757 5587 : 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 5586 : if (attr->originator_id().to_ulong()) {
764 0 : srp.set_originator_id(attr->originator_id().to_string());
765 : }
766 :
767 5586 : show_route_paths.push_back(srp);
768 6368 : }
769 6320 : show_route->set_paths(show_route_paths);
770 6302 : }
771 :
772 51742 : void BgpRoute::NotifyOrDelete() {
773 51742 : if (!front()) {
774 48078 : Delete();
775 : } else {
776 3664 : Notify();
777 : }
778 51742 : }
779 :
780 64061 : uint32_t BgpRoute::SubClusterId() const {
781 64061 : BgpTable *table = static_cast<BgpTable *>(get_table());
782 64059 : const BgpConfigManager *config_manager_ = table->server()->config_manager();
783 64056 : if (!config_manager_) {
784 0 : return 0;
785 : }
786 : const BgpProtocolConfig *proto =
787 64056 : config_manager_->GetProtocolConfig(BgpConfigManager::kMasterInstance);
788 64048 : if (!proto) {
789 2663 : return 0;
790 : }
791 61385 : return proto->subcluster_id();
792 : }
|