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