1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "sockunion.h"
36 #include "workqueue.h"
41 #include "bgpd/bgpd.h"
42 #include "bgpd/bgp_table.h"
43 #include "bgpd/bgp_route.h"
44 #include "bgpd/bgp_attr.h"
45 #include "bgpd/bgp_debug.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_regex.h"
48 #include "bgpd/bgp_community.h"
49 #include "bgpd/bgp_ecommunity.h"
50 #include "bgpd/bgp_lcommunity.h"
51 #include "bgpd/bgp_clist.h"
52 #include "bgpd/bgp_packet.h"
53 #include "bgpd/bgp_filter.h"
54 #include "bgpd/bgp_fsm.h"
55 #include "bgpd/bgp_mplsvpn.h"
56 #include "bgpd/bgp_nexthop.h"
57 #include "bgpd/bgp_damp.h"
58 #include "bgpd/bgp_advertise.h"
59 #include "bgpd/bgp_zebra.h"
60 #include "bgpd/bgp_vty.h"
61 #include "bgpd/bgp_mpath.h"
62 #include "bgpd/bgp_nht.h"
63 #include "bgpd/bgp_updgrp.h"
64 #include "bgpd/bgp_label.h"
67 #include "bgpd/rfapi/rfapi_backend.h"
68 #include "bgpd/rfapi/vnc_import_bgp.h"
69 #include "bgpd/rfapi/vnc_export_bgp.h"
71 #include "bgpd/bgp_encap_types.h"
72 #include "bgpd/bgp_encap_tlv.h"
73 #include "bgpd/bgp_evpn.h"
74 #include "bgpd/bgp_evpn_vty.h"
77 /* Extern from bgp_dump.c */
78 extern const char *bgp_origin_str
[];
79 extern const char *bgp_origin_long_str
[];
81 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
82 safi_t safi
, struct prefix
*p
,
83 struct prefix_rd
*prd
)
86 struct bgp_node
*prn
= NULL
;
92 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
93 || (safi
== SAFI_EVPN
)) {
94 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
96 if (prn
->info
== NULL
)
97 prn
->info
= bgp_table_init(afi
, safi
);
103 rn
= bgp_node_get(table
, p
);
105 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
106 || (safi
== SAFI_EVPN
))
112 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
113 safi_t safi
, struct prefix
*p
,
114 struct prefix_rd
*prd
)
117 struct bgp_node
*prn
= NULL
;
122 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
123 || (safi
== SAFI_EVPN
)) {
124 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
128 if (prn
->info
== NULL
) {
129 bgp_unlock_node(prn
);
136 rn
= bgp_node_lookup(table
, p
);
141 /* Allocate bgp_info_extra */
142 static struct bgp_info_extra
*bgp_info_extra_new(void)
144 struct bgp_info_extra
*new;
145 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
146 new->label
= MPLS_INVALID_LABEL
;
150 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
152 if (extra
&& *extra
) {
153 if ((*extra
)->damp_info
)
154 bgp_damp_info_free((*extra
)->damp_info
, 0);
156 (*extra
)->damp_info
= NULL
;
158 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
164 /* Get bgp_info extra information for the given bgp_info, lazy allocated
167 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
170 ri
->extra
= bgp_info_extra_new();
174 /* Allocate new bgp info structure. */
175 struct bgp_info
*bgp_info_new(void)
177 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
180 /* Free bgp route information. */
181 static void bgp_info_free(struct bgp_info
*binfo
)
184 bgp_attr_unintern(&binfo
->attr
);
186 bgp_unlink_nexthop(binfo
);
187 bgp_info_extra_free(&binfo
->extra
);
188 bgp_info_mpath_free(&binfo
->mpath
);
190 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
192 XFREE(MTYPE_BGP_ROUTE
, binfo
);
195 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
201 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
203 assert(binfo
&& binfo
->lock
> 0);
206 if (binfo
->lock
== 0) {
208 zlog_debug ("%s: unlocked and freeing", __func__
);
209 zlog_backtrace (LOG_DEBUG
);
211 bgp_info_free(binfo
);
216 if (binfo
->lock
== 1)
218 zlog_debug ("%s: unlocked to 1", __func__
);
219 zlog_backtrace (LOG_DEBUG
);
226 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
228 struct bgp_info
*top
;
240 peer_lock(ri
->peer
); /* bgp_info peer reference */
243 /* Do the actual removal of info from RIB, for use by bgp_process
244 completion callback *only* */
245 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
248 ri
->next
->prev
= ri
->prev
;
250 ri
->prev
->next
= ri
->next
;
254 bgp_info_mpath_dequeue(ri
);
259 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
261 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
262 /* set of previous already took care of pcount */
263 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
266 /* undo the effects of a previous call to bgp_info_delete; typically
267 called when a route is deleted and then quickly re-added before the
268 deletion has been processed */
269 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
271 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
272 /* unset of previous already took care of pcount */
273 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
276 /* Adjust pcount as required */
277 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
279 struct bgp_table
*table
;
281 assert(rn
&& bgp_node_table(rn
));
282 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
284 table
= bgp_node_table(rn
);
286 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
289 if (!BGP_INFO_COUNTABLE(ri
)
290 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
292 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
294 /* slight hack, but more robust against errors. */
295 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
296 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
299 "%s: Asked to decrement 0 prefix count for peer %s",
300 __func__
, ri
->peer
->host
);
301 zlog_backtrace(LOG_WARNING
);
302 zlog_warn("%s: Please report to Quagga bugzilla",
305 } else if (BGP_INFO_COUNTABLE(ri
)
306 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
307 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
308 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
312 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
314 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
317 /* Set/unset bgp_info flags, adjusting any other state as needed.
318 * This is here primarily to keep prefix-count in check.
320 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, u_int32_t flag
)
322 SET_FLAG(ri
->flags
, flag
);
324 /* early bath if we know it's not a flag that changes countability state
326 if (!CHECK_FLAG(flag
,
327 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
330 bgp_pcount_adjust(rn
, ri
);
333 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
336 UNSET_FLAG(ri
->flags
, flag
);
338 /* early bath if we know it's not a flag that changes countability state
340 if (!CHECK_FLAG(flag
,
341 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
344 bgp_pcount_adjust(rn
, ri
);
347 /* Get MED value. If MED value is missing and "bgp bestpath
348 missing-as-worst" is specified, treat it as the worst value. */
349 static u_int32_t
bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
351 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
354 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
361 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
363 if (ri
->addpath_rx_id
)
364 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
367 sprintf(buf
, "path %s", ri
->peer
->host
);
370 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
372 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
373 struct bgp_info
*exist
, int *paths_eq
,
374 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
375 char *pfx_buf
, afi_t afi
, safi_t safi
)
377 struct attr
*newattr
, *existattr
;
378 bgp_peer_sort_t new_sort
;
379 bgp_peer_sort_t exist_sort
;
381 u_int32_t exist_pref
;
384 u_int32_t new_weight
;
385 u_int32_t exist_weight
;
386 uint32_t newm
, existm
;
387 struct in_addr new_id
;
388 struct in_addr exist_id
;
391 int internal_as_route
;
394 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
395 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
396 u_int32_t new_mm_seq
;
397 u_int32_t exist_mm_seq
;
404 zlog_debug("%s: new is NULL", pfx_buf
);
409 bgp_info_path_with_addpath_rx_str(new, new_buf
);
413 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
419 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
420 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
421 pfx_buf
, new_buf
, new->flags
, exist_buf
,
426 existattr
= exist
->attr
;
428 /* For EVPN routes, we cannot just go by local vs remote, we have to
429 * look at the MAC mobility sequence number, if present.
431 if (safi
== SAFI_EVPN
) {
432 /* This is an error condition described in RFC 7432 Section
434 * states that in this scenario "the PE MUST alert the operator"
436 * does not state what other action to take. In order to provide
438 * consistency in this scenario we are going to prefer the path
442 if (newattr
->sticky
!= existattr
->sticky
) {
444 prefix2str(&new->net
->p
, pfx_buf
,
446 * PREFIX2STR_BUFFER
);
447 bgp_info_path_with_addpath_rx_str(new, new_buf
);
448 bgp_info_path_with_addpath_rx_str(exist
,
452 if (newattr
->sticky
&& !existattr
->sticky
) {
454 "%s: %s wins over %s due to sticky MAC flag",
455 pfx_buf
, new_buf
, exist_buf
);
459 if (!newattr
->sticky
&& existattr
->sticky
) {
461 "%s: %s loses to %s due to sticky MAC flag",
462 pfx_buf
, new_buf
, exist_buf
);
467 new_mm_seq
= mac_mobility_seqnum(newattr
);
468 exist_mm_seq
= mac_mobility_seqnum(existattr
);
470 if (new_mm_seq
> exist_mm_seq
) {
473 "%s: %s wins over %s due to MM seq %u > %u",
474 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
479 if (new_mm_seq
< exist_mm_seq
) {
482 "%s: %s loses to %s due to MM seq %u < %u",
483 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
489 /* 1. Weight check. */
490 new_weight
= exist_weight
= 0;
492 new_weight
= newattr
->weight
;
493 exist_weight
= existattr
->weight
;
495 if (new_weight
> exist_weight
) {
497 zlog_debug("%s: %s wins over %s due to weight %d > %d",
498 pfx_buf
, new_buf
, exist_buf
, new_weight
,
503 if (new_weight
< exist_weight
) {
505 zlog_debug("%s: %s loses to %s due to weight %d < %d",
506 pfx_buf
, new_buf
, exist_buf
, new_weight
,
511 /* 2. Local preference check. */
512 new_pref
= exist_pref
= bgp
->default_local_pref
;
514 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
515 new_pref
= newattr
->local_pref
;
516 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
517 exist_pref
= existattr
->local_pref
;
519 if (new_pref
> exist_pref
) {
522 "%s: %s wins over %s due to localpref %d > %d",
523 pfx_buf
, new_buf
, exist_buf
, new_pref
,
528 if (new_pref
< exist_pref
) {
531 "%s: %s loses to %s due to localpref %d < %d",
532 pfx_buf
, new_buf
, exist_buf
, new_pref
,
537 /* 3. Local route check. We prefer:
539 * - BGP_ROUTE_AGGREGATE
540 * - BGP_ROUTE_REDISTRIBUTE
542 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
545 "%s: %s wins over %s due to preferred BGP_ROUTE type",
546 pfx_buf
, new_buf
, exist_buf
);
550 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
553 "%s: %s loses to %s due to preferred BGP_ROUTE type",
554 pfx_buf
, new_buf
, exist_buf
);
558 /* 4. AS path length check. */
559 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
560 int exist_hops
= aspath_count_hops(existattr
->aspath
);
561 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
563 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
566 aspath_hops
= aspath_count_hops(newattr
->aspath
);
567 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
569 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
572 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
573 pfx_buf
, new_buf
, exist_buf
,
575 (exist_hops
+ exist_confeds
));
579 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
582 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
583 pfx_buf
, new_buf
, exist_buf
,
585 (exist_hops
+ exist_confeds
));
589 int newhops
= aspath_count_hops(newattr
->aspath
);
591 if (newhops
< exist_hops
) {
594 "%s: %s wins over %s due to aspath hopcount %d < %d",
595 pfx_buf
, new_buf
, exist_buf
,
596 newhops
, exist_hops
);
600 if (newhops
> exist_hops
) {
603 "%s: %s loses to %s due to aspath hopcount %d > %d",
604 pfx_buf
, new_buf
, exist_buf
,
605 newhops
, exist_hops
);
611 /* 5. Origin check. */
612 if (newattr
->origin
< existattr
->origin
) {
614 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
615 pfx_buf
, new_buf
, exist_buf
,
616 bgp_origin_long_str
[newattr
->origin
],
617 bgp_origin_long_str
[existattr
->origin
]);
621 if (newattr
->origin
> existattr
->origin
) {
623 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
624 pfx_buf
, new_buf
, exist_buf
,
625 bgp_origin_long_str
[newattr
->origin
],
626 bgp_origin_long_str
[existattr
->origin
]);
631 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
632 && aspath_count_hops(existattr
->aspath
) == 0);
633 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
634 && aspath_count_confeds(existattr
->aspath
) > 0
635 && aspath_count_hops(newattr
->aspath
) == 0
636 && aspath_count_hops(existattr
->aspath
) == 0);
638 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
639 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
640 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
641 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
642 || internal_as_route
) {
643 new_med
= bgp_med_value(new->attr
, bgp
);
644 exist_med
= bgp_med_value(exist
->attr
, bgp
);
646 if (new_med
< exist_med
) {
649 "%s: %s wins over %s due to MED %d < %d",
650 pfx_buf
, new_buf
, exist_buf
, new_med
,
655 if (new_med
> exist_med
) {
658 "%s: %s loses to %s due to MED %d > %d",
659 pfx_buf
, new_buf
, exist_buf
, new_med
,
665 /* 7. Peer type check. */
666 new_sort
= new->peer
->sort
;
667 exist_sort
= exist
->peer
->sort
;
669 if (new_sort
== BGP_PEER_EBGP
670 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
673 "%s: %s wins over %s due to eBGP peer > iBGP peer",
674 pfx_buf
, new_buf
, exist_buf
);
678 if (exist_sort
== BGP_PEER_EBGP
679 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
682 "%s: %s loses to %s due to iBGP peer < eBGP peer",
683 pfx_buf
, new_buf
, exist_buf
);
687 /* 8. IGP metric check. */
691 newm
= new->extra
->igpmetric
;
693 existm
= exist
->extra
->igpmetric
;
698 "%s: %s wins over %s due to IGP metric %d < %d",
699 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
706 "%s: %s loses to %s due to IGP metric %d > %d",
707 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
711 /* 9. Same IGP metric. Compare the cluster list length as
712 representative of IGP hops metric. Rewrite the metric value
713 pair (newm, existm) with the cluster list length. Prefer the
714 path with smaller cluster list length. */
715 if (newm
== existm
) {
716 if (peer_sort(new->peer
) == BGP_PEER_IBGP
717 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
718 && (mpath_cfg
== NULL
720 mpath_cfg
->ibgp_flags
,
721 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
722 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
723 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
728 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
729 pfx_buf
, new_buf
, exist_buf
,
737 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
738 pfx_buf
, new_buf
, exist_buf
,
745 /* 10. confed-external vs. confed-internal */
746 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
747 if (new_sort
== BGP_PEER_CONFED
748 && exist_sort
== BGP_PEER_IBGP
) {
751 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
752 pfx_buf
, new_buf
, exist_buf
);
756 if (exist_sort
== BGP_PEER_CONFED
757 && new_sort
== BGP_PEER_IBGP
) {
760 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
761 pfx_buf
, new_buf
, exist_buf
);
766 /* 11. Maximum path check. */
767 if (newm
== existm
) {
768 /* If one path has a label but the other does not, do not treat
769 * them as equals for multipath
771 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
))
773 && bgp_is_valid_label(&exist
->extra
->label
))) {
776 "%s: %s and %s cannot be multipath, one has a label while the other does not",
777 pfx_buf
, new_buf
, exist_buf
);
778 } else if (bgp_flag_check(bgp
,
779 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
782 * For the two paths, all comparison steps till IGP
784 * have succeeded - including AS_PATH hop count. Since
786 * bestpath as-path multipath-relax' knob is on, we
788 * an exact match of AS_PATH. Thus, mark the paths are
790 * That will trigger both these paths to get into the
798 "%s: %s and %s are equal via multipath-relax",
799 pfx_buf
, new_buf
, exist_buf
);
800 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
801 if (aspath_cmp(new->attr
->aspath
,
802 exist
->attr
->aspath
)) {
807 "%s: %s and %s are equal via matching aspaths",
808 pfx_buf
, new_buf
, exist_buf
);
810 } else if (new->peer
->as
== exist
->peer
->as
) {
815 "%s: %s and %s are equal via same remote-as",
816 pfx_buf
, new_buf
, exist_buf
);
820 * TODO: If unequal cost ibgp multipath is enabled we can
821 * mark the paths as equal here instead of returning
826 "%s: %s wins over %s after IGP metric comparison",
827 pfx_buf
, new_buf
, exist_buf
);
830 "%s: %s loses to %s after IGP metric comparison",
831 pfx_buf
, new_buf
, exist_buf
);
836 /* 12. If both paths are external, prefer the path that was received
837 first (the oldest one). This step minimizes route-flap, since a
838 newer path won't displace an older one, even if it was the
839 preferred route based on the additional decision criteria below. */
840 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
841 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
842 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
845 "%s: %s wins over %s due to oldest external",
846 pfx_buf
, new_buf
, exist_buf
);
850 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
853 "%s: %s loses to %s due to oldest external",
854 pfx_buf
, new_buf
, exist_buf
);
859 /* 13. Router-ID comparision. */
860 /* If one of the paths is "stale", the corresponding peer router-id will
861 * be 0 and would always win over the other path. If originator id is
862 * used for the comparision, it will decide which path is better.
864 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
865 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
867 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
868 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
869 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
871 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
873 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
876 "%s: %s wins over %s due to Router-ID comparison",
877 pfx_buf
, new_buf
, exist_buf
);
881 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
884 "%s: %s loses to %s due to Router-ID comparison",
885 pfx_buf
, new_buf
, exist_buf
);
889 /* 14. Cluster length comparision. */
890 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
891 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
893 if (new_cluster
< exist_cluster
) {
896 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
897 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
902 if (new_cluster
> exist_cluster
) {
905 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
906 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
911 /* 15. Neighbor address comparision. */
912 /* Do this only if neither path is "stale" as stale paths do not have
913 * valid peer information (as the connection may or may not be up).
915 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
918 "%s: %s wins over %s due to latter path being STALE",
919 pfx_buf
, new_buf
, exist_buf
);
923 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
926 "%s: %s loses to %s due to former path being STALE",
927 pfx_buf
, new_buf
, exist_buf
);
931 /* locally configured routes to advertise do not have su_remote */
932 if (new->peer
->su_remote
== NULL
)
934 if (exist
->peer
->su_remote
== NULL
)
937 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
942 "%s: %s loses to %s due to Neighor IP comparison",
943 pfx_buf
, new_buf
, exist_buf
);
950 "%s: %s wins over %s due to Neighor IP comparison",
951 pfx_buf
, new_buf
, exist_buf
);
956 zlog_debug("%s: %s wins over %s due to nothing left to compare",
957 pfx_buf
, new_buf
, exist_buf
);
962 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
963 * is preferred, or 0 if they are the same (usually will only occur if
964 * multipath is enabled
965 * This version is compatible with */
966 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
967 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
972 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
986 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
987 struct attr
*attr
, afi_t afi
,
990 struct bgp_filter
*filter
;
992 filter
= &peer
->filter
[afi
][safi
];
994 #define FILTER_EXIST_WARN(F, f, filter) \
995 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
996 zlog_warn("%s: Could not find configured input %s-list %s!", \
997 peer->host, #f, F##_IN_NAME(filter));
999 if (DISTRIBUTE_IN_NAME(filter
)) {
1000 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1002 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1006 if (PREFIX_LIST_IN_NAME(filter
)) {
1007 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1009 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1013 if (FILTER_LIST_IN_NAME(filter
)) {
1014 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1016 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1021 return FILTER_PERMIT
;
1022 #undef FILTER_EXIST_WARN
1025 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1026 struct attr
*attr
, afi_t afi
,
1029 struct bgp_filter
*filter
;
1031 filter
= &peer
->filter
[afi
][safi
];
1033 #define FILTER_EXIST_WARN(F, f, filter) \
1034 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1035 zlog_warn("%s: Could not find configured output %s-list %s!", \
1036 peer->host, #f, F##_OUT_NAME(filter));
1038 if (DISTRIBUTE_OUT_NAME(filter
)) {
1039 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1041 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1045 if (PREFIX_LIST_OUT_NAME(filter
)) {
1046 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1048 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1053 if (FILTER_LIST_OUT_NAME(filter
)) {
1054 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1056 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1061 return FILTER_PERMIT
;
1062 #undef FILTER_EXIST_WARN
1065 /* If community attribute includes no_export then return 1. */
1066 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1068 if (attr
->community
) {
1069 /* NO_ADVERTISE check. */
1070 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1073 /* NO_EXPORT check. */
1074 if (peer
->sort
== BGP_PEER_EBGP
1075 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1078 /* NO_EXPORT_SUBCONFED check. */
1079 if (peer
->sort
== BGP_PEER_EBGP
1080 || peer
->sort
== BGP_PEER_CONFED
)
1081 if (community_include(attr
->community
,
1082 COMMUNITY_NO_EXPORT_SUBCONFED
))
1088 /* Route reflection loop check. */
1089 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1091 struct in_addr cluster_id
;
1093 if (attr
->cluster
) {
1094 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1095 cluster_id
= peer
->bgp
->cluster_id
;
1097 cluster_id
= peer
->bgp
->router_id
;
1099 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1105 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1106 struct attr
*attr
, afi_t afi
, safi_t safi
,
1107 const char *rmap_name
)
1109 struct bgp_filter
*filter
;
1110 struct bgp_info info
;
1111 route_map_result_t ret
;
1112 struct route_map
*rmap
= NULL
;
1114 filter
= &peer
->filter
[afi
][safi
];
1116 /* Apply default weight value. */
1117 if (peer
->weight
[afi
][safi
])
1118 attr
->weight
= peer
->weight
[afi
][safi
];
1121 rmap
= route_map_lookup_by_name(rmap_name
);
1126 if (ROUTE_MAP_IN_NAME(filter
)) {
1127 rmap
= ROUTE_MAP_IN(filter
);
1134 /* Route map apply. */
1136 /* Duplicate current value to new strucutre for modification. */
1140 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1142 /* Apply BGP route map to the attribute. */
1143 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1145 peer
->rmap_type
= 0;
1147 if (ret
== RMAP_DENYMATCH
) {
1148 /* Free newly generated AS path and community by
1150 bgp_attr_flush(attr
);
1157 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1158 struct attr
*attr
, afi_t afi
, safi_t safi
,
1159 const char *rmap_name
)
1161 struct bgp_filter
*filter
;
1162 struct bgp_info info
;
1163 route_map_result_t ret
;
1164 struct route_map
*rmap
= NULL
;
1166 filter
= &peer
->filter
[afi
][safi
];
1168 /* Apply default weight value. */
1169 if (peer
->weight
[afi
][safi
])
1170 attr
->weight
= peer
->weight
[afi
][safi
];
1173 rmap
= route_map_lookup_by_name(rmap_name
);
1178 if (ROUTE_MAP_OUT_NAME(filter
)) {
1179 rmap
= ROUTE_MAP_OUT(filter
);
1186 /* Route map apply. */
1188 /* Duplicate current value to new strucutre for modification. */
1192 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1194 /* Apply BGP route map to the attribute. */
1195 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1197 peer
->rmap_type
= 0;
1199 if (ret
== RMAP_DENYMATCH
)
1200 /* caller has multiple error paths with bgp_attr_flush()
1207 /* If this is an EBGP peer with remove-private-AS */
1208 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1209 struct peer
*peer
, struct attr
*attr
)
1211 if (peer
->sort
== BGP_PEER_EBGP
1212 && (peer_af_flag_check(peer
, afi
, safi
,
1213 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1214 || peer_af_flag_check(peer
, afi
, safi
,
1215 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1216 || peer_af_flag_check(peer
, afi
, safi
,
1217 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1218 || peer_af_flag_check(peer
, afi
, safi
,
1219 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1220 // Take action on the entire aspath
1221 if (peer_af_flag_check(peer
, afi
, safi
,
1222 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1223 || peer_af_flag_check(peer
, afi
, safi
,
1224 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1225 if (peer_af_flag_check(
1227 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1228 attr
->aspath
= aspath_replace_private_asns(
1229 attr
->aspath
, bgp
->as
);
1231 // The entire aspath consists of private ASNs so create
1233 else if (aspath_private_as_check(attr
->aspath
))
1234 attr
->aspath
= aspath_empty_get();
1236 // There are some public and some private ASNs, remove
1239 attr
->aspath
= aspath_remove_private_asns(
1243 // 'all' was not specified so the entire aspath must be private
1245 // for us to do anything
1246 else if (aspath_private_as_check(attr
->aspath
)) {
1247 if (peer_af_flag_check(
1249 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1250 attr
->aspath
= aspath_replace_private_asns(
1251 attr
->aspath
, bgp
->as
);
1253 attr
->aspath
= aspath_empty_get();
1258 /* If this is an EBGP peer with as-override */
1259 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1260 struct peer
*peer
, struct attr
*attr
)
1262 if (peer
->sort
== BGP_PEER_EBGP
1263 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1264 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1265 attr
->aspath
= aspath_replace_specific_asn(
1266 attr
->aspath
, peer
->as
, bgp
->as
);
1270 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1272 if (family
== AF_INET
)
1273 attr
->nexthop
.s_addr
= 0;
1274 if (family
== AF_INET6
)
1275 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1278 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1279 struct update_subgroup
*subgrp
, struct prefix
*p
,
1282 struct bgp_filter
*filter
;
1285 struct peer
*onlypeer
;
1287 struct attr
*riattr
;
1288 struct peer_af
*paf
;
1289 char buf
[PREFIX_STRLEN
];
1295 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1297 if (DISABLE_BGP_ANNOUNCE
)
1300 afi
= SUBGRP_AFI(subgrp
);
1301 safi
= SUBGRP_SAFI(subgrp
);
1302 peer
= SUBGRP_PEER(subgrp
);
1304 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1305 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1308 filter
= &peer
->filter
[afi
][safi
];
1309 bgp
= SUBGRP_INST(subgrp
);
1310 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1313 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1314 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1315 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1318 * direct and direct_ext type routes originate internally even
1319 * though they can have peer pointers that reference other
1322 prefix2str(p
, buf
, PREFIX_STRLEN
);
1323 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1329 /* With addpath we may be asked to TX all kinds of paths so make sure
1331 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1332 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1333 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1337 /* If this is not the bestpath then check to see if there is an enabled
1339 * feature that requires us to advertise it */
1340 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1341 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1346 /* Aggregate-address suppress check. */
1347 if (ri
->extra
&& ri
->extra
->suppress
)
1348 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1352 /* If it's labeled safi, make sure the route has a valid label. */
1353 if (safi
== SAFI_LABELED_UNICAST
) {
1354 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1355 if (!bgp_is_valid_label(&label
)) {
1356 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1357 zlog_debug("u%" PRIu64
":s%" PRIu64
1358 " %s/%d is filtered - no label (%p)",
1359 subgrp
->update_group
->id
, subgrp
->id
,
1360 inet_ntop(p
->family
, &p
->u
.prefix
,
1361 buf
, SU_ADDRSTRLEN
),
1362 p
->prefixlen
, &label
);
1367 /* Do not send back route to sender. */
1368 if (onlypeer
&& from
== onlypeer
) {
1372 /* Do not send the default route in the BGP table if the neighbor is
1373 * configured for default-originate */
1374 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1375 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1376 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1378 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1382 /* Transparency check. */
1383 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1384 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1389 /* If community is not disabled check the no-export and local. */
1390 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1391 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1393 "subgrpannouncecheck: community filter check fail");
1397 /* If the attribute has originator-id and it is same as remote
1399 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1400 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1401 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1403 "%s [Update:SEND] %s originator-id is same as "
1406 prefix2str(p
, buf
, sizeof(buf
)));
1410 /* ORF prefix-list filter check */
1411 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1412 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1413 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1414 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1415 if (peer
->orf_plist
[afi
][safi
]) {
1416 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1418 if (bgp_debug_update(NULL
, p
,
1419 subgrp
->update_group
, 0))
1421 "%s [Update:SEND] %s is filtered via ORF",
1429 /* Output filter check. */
1430 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1431 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1432 zlog_debug("%s [Update:SEND] %s is filtered",
1433 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1437 #ifdef BGP_SEND_ASPATH_CHECK
1438 /* AS path loop check. */
1439 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1440 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1442 "%s [Update:SEND] suppress announcement to peer AS %u "
1443 "that is part of AS path.",
1444 onlypeer
->host
, onlypeer
->as
);
1447 #endif /* BGP_SEND_ASPATH_CHECK */
1449 /* If we're a CONFED we need to loop check the CONFED ID too */
1450 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1451 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1452 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1454 "%s [Update:SEND] suppress announcement to peer AS %u"
1456 peer
->host
, bgp
->confed_id
);
1461 /* Route-Reflect check. */
1462 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1467 /* IBGP reflection check. */
1468 if (reflect
&& !samepeer_safe
) {
1469 /* A route from a Client peer. */
1470 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1471 PEER_FLAG_REFLECTOR_CLIENT
)) {
1472 /* Reflect to all the Non-Client peers and also to the
1473 Client peers other than the originator. Originator
1475 is already done. So there is noting to do. */
1476 /* no bgp client-to-client reflection check. */
1477 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1478 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1479 PEER_FLAG_REFLECTOR_CLIENT
))
1482 /* A route from a Non-client peer. Reflect to all other
1484 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1485 PEER_FLAG_REFLECTOR_CLIENT
))
1490 /* For modify attribute, copy it to temporary structure. */
1491 bgp_attr_dup(attr
, riattr
);
1493 /* If local-preference is not set. */
1494 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1495 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1496 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1497 attr
->local_pref
= bgp
->default_local_pref
;
1500 /* If originator-id is not set and the route is to be reflected,
1501 set the originator id */
1503 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1504 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1505 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1508 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1510 if (peer
->sort
== BGP_PEER_EBGP
1511 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1512 if (from
!= bgp
->peer_self
&& !transparent
1513 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1514 PEER_FLAG_MED_UNCHANGED
))
1516 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1519 /* Since the nexthop attribute can vary per peer, it is not explicitly
1521 * in announce check, only certain flags and length (or number of
1523 * -- for IPv6/MP_REACH) are set here in order to guide the update
1525 * code in setting the nexthop(s) on a per peer basis in
1527 * Typically, the source nexthop in the attribute is preserved but in
1529 * scenarios where we know it will always be overwritten, we reset the
1530 * nexthop to "0" in an attempt to achieve better Update packing. An
1531 * example of this is when a prefix from each of 2 IBGP peers needs to
1533 * announced to an EBGP peer (and they have the same attributes barring
1537 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1539 #define NEXTHOP_IS_V6 \
1540 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1541 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1542 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1543 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1545 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1547 * the peer (group) is configured to receive link-local nexthop
1549 * and it is available in the prefix OR we're not reflecting the route
1551 * the peer (group) to whom we're going to announce is on a shared
1553 * and this is either a self-originated route or the peer is EBGP.
1555 if (NEXTHOP_IS_V6
) {
1556 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1557 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1558 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1559 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1560 || (!reflect
&& peer
->shared_network
1561 && (from
== bgp
->peer_self
1562 || peer
->sort
== BGP_PEER_EBGP
))) {
1563 attr
->mp_nexthop_len
=
1564 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1567 /* Clear off link-local nexthop in source, whenever it is not
1569 * ensure more prefixes share the same attribute for
1572 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1573 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1574 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1577 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1578 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1580 /* Route map & unsuppress-map apply. */
1581 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1582 struct bgp_info info
;
1583 struct bgp_info_extra dummy_info_extra
;
1584 struct attr dummy_attr
;
1590 memcpy(&dummy_info_extra
, ri
->extra
,
1591 sizeof(struct bgp_info_extra
));
1592 info
.extra
= &dummy_info_extra
;
1595 /* don't confuse inbound and outbound setting */
1596 RESET_FLAG(attr
->rmap_change_flags
);
1599 * The route reflector is not allowed to modify the attributes
1600 * of the reflected IBGP routes unless explicitly allowed.
1602 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1603 && !bgp_flag_check(bgp
,
1604 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1605 bgp_attr_dup(&dummy_attr
, attr
);
1606 info
.attr
= &dummy_attr
;
1609 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1611 if (ri
->extra
&& ri
->extra
->suppress
)
1612 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1615 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1618 peer
->rmap_type
= 0;
1620 if (ret
== RMAP_DENYMATCH
) {
1621 bgp_attr_flush(attr
);
1626 /* After route-map has been applied, we check to see if the nexthop to
1627 * be carried in the attribute (that is used for the announcement) can
1628 * be cleared off or not. We do this in all cases where we would be
1629 * setting the nexthop to "ourselves". For IPv6, we only need to
1631 * the global nexthop here; the link-local nexthop would have been
1633 * already, and if not, it is required by the update formation code.
1634 * Also see earlier comments in this function.
1637 * If route-map has performed some operation on the nexthop or the peer
1638 * configuration says to pass it unchanged, we cannot reset the nexthop
1639 * here, so only attempt to do it if these aren't true. Note that the
1640 * route-map handler itself might have cleared the nexthop, if for
1642 * it is configured as 'peer-address'.
1644 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1645 riattr
->rmap_change_flags
)
1647 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1648 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1649 /* We can reset the nexthop, if setting (or forcing) it to
1651 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1652 PEER_FLAG_NEXTHOP_SELF
)
1653 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1654 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1656 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1657 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1658 subgroup_announce_reset_nhop(
1659 (peer_cap_enhe(peer
, afi
, safi
)
1663 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1664 /* Can also reset the nexthop if announcing to EBGP, but
1666 * no peer in the subgroup is on a shared subnet.
1667 * Note: 3rd party nexthop currently implemented for
1670 SUBGRP_FOREACH_PEER(subgrp
, paf
)
1672 if (bgp_multiaccess_check_v4(riattr
->nexthop
,
1677 subgroup_announce_reset_nhop(
1678 (peer_cap_enhe(peer
, afi
, safi
)
1683 /* If IPv6/MP and nexthop does not have any override and happens
1685 * be a link-local address, reset it so that we don't pass along
1687 * source's link-local IPv6 address to recipients who may not be
1689 * the same interface.
1691 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1692 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1693 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1700 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1701 struct bgp_maxpaths_cfg
*mpath_cfg
,
1702 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1704 struct bgp_info
*new_select
;
1705 struct bgp_info
*old_select
;
1706 struct bgp_info
*ri
;
1707 struct bgp_info
*ri1
;
1708 struct bgp_info
*ri2
;
1709 struct bgp_info
*nextri
= NULL
;
1710 int paths_eq
, do_mpath
, debug
;
1711 struct list mp_list
;
1712 char pfx_buf
[PREFIX2STR_BUFFER
];
1713 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1715 bgp_mp_list_init(&mp_list
);
1717 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1719 debug
= bgp_debug_bestpath(&rn
->p
);
1722 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1724 /* bgp deterministic-med */
1726 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1728 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1729 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1730 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1732 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1733 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1735 if (BGP_INFO_HOLDDOWN(ri1
))
1737 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1738 if (ri1
->peer
->status
!= Established
)
1743 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1744 if (CHECK_FLAG(ri2
->flags
,
1745 BGP_INFO_DMED_CHECK
))
1747 if (BGP_INFO_HOLDDOWN(ri2
))
1750 && ri2
->peer
!= bgp
->peer_self
1753 PEER_STATUS_NSF_WAIT
))
1754 if (ri2
->peer
->status
1758 if (aspath_cmp_left(ri1
->attr
->aspath
,
1760 || aspath_cmp_left_confed(
1762 ri2
->attr
->aspath
)) {
1763 if (bgp_info_cmp(bgp
, ri2
,
1769 bgp_info_unset_flag(
1771 BGP_INFO_DMED_SELECTED
);
1777 BGP_INFO_DMED_CHECK
);
1781 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1782 bgp_info_set_flag(rn
, new_select
,
1783 BGP_INFO_DMED_SELECTED
);
1786 bgp_info_path_with_addpath_rx_str(new_select
,
1788 zlog_debug("%s: %s is the bestpath from AS %d",
1790 aspath_get_first_as(
1791 new_select
->attr
->aspath
));
1796 /* Check old selected route and new selected route. */
1799 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1801 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1804 if (BGP_INFO_HOLDDOWN(ri
)) {
1805 /* reap REMOVED routes, if needs be
1806 * selected route must stay for a while longer though
1808 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1809 && (ri
!= old_select
))
1810 bgp_info_reap(rn
, ri
);
1815 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1816 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1817 if (ri
->peer
->status
!= Established
)
1820 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1821 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1822 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1826 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1828 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1829 debug
, pfx_buf
, afi
, safi
)) {
1834 /* Now that we know which path is the bestpath see if any of the other
1836 * qualify as multipaths
1840 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1842 sprintf(path_buf
, "NONE");
1844 "%s: After path selection, newbest is %s oldbest was %s",
1846 old_select
? old_select
->peer
->host
: "NONE");
1849 if (do_mpath
&& new_select
) {
1850 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1854 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1856 if (ri
== new_select
) {
1859 "%s: %s is the bestpath, add to the multipath list",
1861 bgp_mp_list_add(&mp_list
, ri
);
1865 if (BGP_INFO_HOLDDOWN(ri
))
1868 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1869 && !CHECK_FLAG(ri
->peer
->sflags
,
1870 PEER_STATUS_NSF_WAIT
))
1871 if (ri
->peer
->status
!= Established
)
1874 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1877 "%s: %s has the same nexthop as the bestpath, skip it",
1882 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1883 debug
, pfx_buf
, afi
, safi
);
1888 "%s: %s is equivalent to the bestpath, add to the multipath list",
1890 bgp_mp_list_add(&mp_list
, ri
);
1895 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1896 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1897 bgp_mp_list_clear(&mp_list
);
1899 result
->old
= old_select
;
1900 result
->new = new_select
;
1906 * A new route/change in bestpath of an existing route. Evaluate the path
1907 * for advertisement to the subgroup.
1909 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1910 struct bgp_info
*selected
,
1911 struct bgp_node
*rn
,
1912 u_int32_t addpath_tx_id
)
1915 struct peer
*onlypeer
;
1921 afi
= SUBGRP_AFI(subgrp
);
1922 safi
= SUBGRP_SAFI(subgrp
);
1923 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1926 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1927 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1928 PEER_STATUS_ORF_WAIT_REFRESH
))
1931 memset(&attr
, 0, sizeof(struct attr
));
1932 /* It's initialized in bgp_announce_check() */
1934 /* Announcement to the subgroup. If the route is filtered withdraw it.
1937 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1938 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1940 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1941 selected
->addpath_tx_id
);
1944 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1946 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1953 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1954 * This is called at the end of route processing.
1956 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1958 struct bgp_info
*ri
;
1960 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1961 if (BGP_INFO_HOLDDOWN(ri
))
1963 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1964 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
1969 * Has the route changed from the RIB's perspective? This is invoked only
1970 * if the route selection returns the same best route as earlier - to
1971 * determine if we need to update zebra or not.
1973 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
1975 struct bgp_info
*mpinfo
;
1977 /* If this is multipath, check all selected paths for any nexthop change
1979 * attribute change. Some attribute changes (e.g., community) aren't of
1980 * relevance to the RIB, but we'll update zebra to ensure we handle the
1981 * case of BGP nexthop change. This is the behavior when the best path
1983 * an attribute change anyway.
1985 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
1986 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
1989 /* If this is multipath, check all selected paths for any nexthop change
1991 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
1992 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
1993 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
1994 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
1998 /* Nothing has changed from the RIB's perspective. */
2002 struct bgp_process_queue
{
2004 struct bgp_node
*rn
;
2009 static wq_item_status
bgp_process_main(struct work_queue
*wq
, void *data
)
2011 struct bgp_process_queue
*pq
= data
;
2012 struct bgp
*bgp
= pq
->bgp
;
2013 struct bgp_node
*rn
= pq
->rn
;
2014 afi_t afi
= pq
->afi
;
2015 safi_t safi
= pq
->safi
;
2016 struct prefix
*p
= &rn
->p
;
2017 struct bgp_info
*new_select
;
2018 struct bgp_info
*old_select
;
2019 struct bgp_info_pair old_and_new
;
2021 /* Is it end of initial update? (after startup) */
2023 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2024 sizeof(bgp
->update_delay_zebra_resume_time
));
2026 bgp
->main_zebra_update_hold
= 0;
2027 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
2028 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
2029 if (bgp_fibupd_safi(safi
))
2030 bgp_zebra_announce_table(bgp
, afi
,
2033 bgp
->main_peers_update_hold
= 0;
2035 bgp_start_routeadv(bgp
);
2039 /* Best path selection. */
2040 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2042 old_select
= old_and_new
.old
;
2043 new_select
= old_and_new
.new;
2045 /* Do we need to allocate or free labels?
2046 * Right now, since we only deal with per-prefix labels, it is not
2048 * to do this upon changes to best path except of the label index
2051 if (safi
== SAFI_UNICAST
) {
2054 || bgp_label_index_differs(new_select
, old_select
)
2055 || new_select
->sub_type
!= old_select
->sub_type
) {
2056 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2057 && new_select
->attr
->flag
2059 BGP_ATTR_PREFIX_SID
)
2060 && new_select
->attr
->label_index
2061 != BGP_INVALID_LABEL_INDEX
) {
2064 BGP_NODE_REGISTERED_FOR_LABEL
))
2065 bgp_unregister_for_label(rn
);
2066 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2068 bgp_set_valid_label(&rn
->local_label
);
2070 bgp_register_for_label(rn
, new_select
);
2072 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
2073 bgp_unregister_for_label(rn
);
2076 /* If best route remains the same and this is not due to user-initiated
2077 * clear, see exactly what needs to be done.
2080 if (old_select
&& old_select
== new_select
2081 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2082 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2083 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2084 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2086 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2087 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2089 if (bgp_fibupd_safi(safi
)
2090 && !bgp_option_check(BGP_OPT_NO_FIB
)
2091 && new_select
->type
== ZEBRA_ROUTE_BGP
2092 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2093 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2096 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2097 bgp_zebra_clear_route_change_flags(rn
);
2099 /* If there is a change of interest to peers, reannounce the
2101 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2102 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2103 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2105 /* unicast routes must also be annouced to
2106 * labeled-unicast update-groups */
2107 if (safi
== SAFI_UNICAST
)
2108 group_announce_route(bgp
, afi
,
2109 SAFI_LABELED_UNICAST
, rn
,
2112 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2113 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2116 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2120 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2122 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2124 /* bestpath has changed; bump version */
2125 if (old_select
|| new_select
) {
2126 bgp_bump_version(rn
);
2128 if (!bgp
->t_rmap_def_originate_eval
) {
2132 update_group_refresh_default_originate_route_map
,
2133 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2134 &bgp
->t_rmap_def_originate_eval
);
2139 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2141 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2142 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2143 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2147 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2148 if (old_select
!= new_select
) {
2150 vnc_import_bgp_exterior_del_route(bgp
, p
,
2152 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2155 vnc_import_bgp_exterior_add_route(bgp
, p
,
2157 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2163 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2165 /* unicast routes must also be annouced to labeled-unicast update-groups
2167 if (safi
== SAFI_UNICAST
)
2168 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2172 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2173 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2174 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2175 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2176 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2177 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2179 /* Withdraw the route from the kernel. */
2180 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2181 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2182 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2183 bgp_zebra_withdraw(p
, old_select
, safi
);
2187 /* Clear any route change flags. */
2188 bgp_zebra_clear_route_change_flags(rn
);
2190 /* Reap old select bgp_info, if it has been removed */
2191 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2192 bgp_info_reap(rn
, old_select
);
2194 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2198 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2200 struct bgp_process_queue
*pq
= data
;
2201 struct bgp_table
*table
;
2203 bgp_unlock(pq
->bgp
);
2205 table
= bgp_node_table(pq
->rn
);
2206 bgp_unlock_node(pq
->rn
);
2207 bgp_table_unlock(table
);
2209 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pq
);
2212 void bgp_process_queue_init(void)
2214 if (!bm
->process_main_queue
) {
2215 bm
->process_main_queue
=
2216 work_queue_new(bm
->master
, "process_main_queue");
2218 if (!bm
->process_main_queue
) {
2219 zlog_err("%s: Failed to allocate work queue", __func__
);
2224 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_main
;
2225 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2226 bm
->process_main_queue
->spec
.max_retries
= 0;
2227 bm
->process_main_queue
->spec
.hold
= 50;
2228 /* Use a higher yield value of 50ms for main queue processing */
2229 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2232 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2234 struct bgp_process_queue
*pqnode
;
2236 /* already scheduled for processing? */
2237 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2240 if (bm
->process_main_queue
== NULL
)
2243 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2244 sizeof(struct bgp_process_queue
));
2248 /* all unlocked in bgp_processq_del */
2249 bgp_table_lock(bgp_node_table(rn
));
2250 pqnode
->rn
= bgp_lock_node(rn
);
2251 pqnode
->bgp
= bgp_lock(bgp
);
2253 pqnode
->safi
= safi
;
2254 work_queue_add(bm
->process_main_queue
, pqnode
);
2255 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2259 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2261 struct bgp_process_queue
*pqnode
;
2263 if (bm
->process_main_queue
== NULL
)
2266 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2267 sizeof(struct bgp_process_queue
));
2274 work_queue_add(bm
->process_main_queue
, pqnode
);
2277 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2281 peer
= THREAD_ARG(thread
);
2282 peer
->t_pmax_restart
= NULL
;
2284 if (bgp_debug_neighbor_events(peer
))
2286 "%s Maximum-prefix restart timer expired, restore peering",
2289 peer_clear(peer
, NULL
);
2294 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2298 iana_safi_t pkt_safi
;
2300 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2303 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2304 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2305 PEER_STATUS_PREFIX_LIMIT
)
2310 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2312 afi_safi_print(afi
, safi
), peer
->host
,
2313 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2314 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2316 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2317 PEER_FLAG_MAX_PREFIX_WARNING
))
2320 /* Convert AFI, SAFI to values for packet. */
2321 pkt_afi
= afi_int2iana(afi
);
2322 pkt_safi
= safi_int2iana(safi
);
2326 ndata
[0] = (pkt_afi
>> 8);
2328 ndata
[2] = pkt_safi
;
2329 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2330 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2331 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2332 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2334 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2335 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2336 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2340 /* Dynamic peers will just close their connection. */
2341 if (peer_dynamic_neighbor(peer
))
2344 /* restart timer start */
2345 if (peer
->pmax_restart
[afi
][safi
]) {
2346 peer
->v_pmax_restart
=
2347 peer
->pmax_restart
[afi
][safi
] * 60;
2349 if (bgp_debug_neighbor_events(peer
))
2351 "%s Maximum-prefix restart timer started for %d secs",
2352 peer
->host
, peer
->v_pmax_restart
);
2354 BGP_TIMER_ON(peer
->t_pmax_restart
,
2355 bgp_maximum_prefix_restart_timer
,
2356 peer
->v_pmax_restart
);
2361 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2362 PEER_STATUS_PREFIX_LIMIT
);
2364 if (peer
->pcount
[afi
][safi
]
2365 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2366 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2367 PEER_STATUS_PREFIX_THRESHOLD
)
2372 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2373 afi_safi_print(afi
, safi
), peer
->host
,
2374 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2375 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2376 PEER_STATUS_PREFIX_THRESHOLD
);
2378 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2379 PEER_STATUS_PREFIX_THRESHOLD
);
2383 /* Unconditionally remove the route from the RIB, without taking
2384 * damping into consideration (eg, because the session went down)
2386 static void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
,
2387 struct peer
*peer
, afi_t afi
, safi_t safi
)
2389 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2391 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2392 bgp_info_delete(rn
, ri
); /* keep historical info */
2394 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2397 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2398 struct peer
*peer
, afi_t afi
, safi_t safi
,
2399 struct prefix_rd
*prd
)
2401 int status
= BGP_DAMP_NONE
;
2403 /* apply dampening, if result is suppressed, we'll be retaining
2404 * the bgp_info in the RIB for historical reference.
2406 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2407 && peer
->sort
== BGP_PEER_EBGP
)
2408 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2409 == BGP_DAMP_SUPPRESSED
) {
2410 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2416 if (safi
== SAFI_MPLS_VPN
) {
2417 struct bgp_node
*prn
= NULL
;
2418 struct bgp_table
*table
= NULL
;
2420 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2421 (struct prefix
*)prd
);
2423 table
= (struct bgp_table
*)(prn
->info
);
2425 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2426 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2428 bgp_unlock_node(prn
);
2430 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2431 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2433 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2434 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2440 /* If this is an EVPN route, process for un-import. */
2441 if (safi
== SAFI_EVPN
)
2442 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2444 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2447 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2448 struct peer
*peer
, struct attr
*attr
,
2449 struct bgp_node
*rn
)
2451 struct bgp_info
*new;
2453 /* Make new BGP info. */
2454 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2456 new->instance
= instance
;
2457 new->sub_type
= sub_type
;
2460 new->uptime
= bgp_clock();
2462 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2466 static void overlay_index_update(struct attr
*attr
,
2467 struct eth_segment_id
*eth_s_id
,
2468 union gw_addr
*gw_ip
)
2473 if (eth_s_id
== NULL
) {
2474 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2475 sizeof(struct eth_segment_id
));
2477 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2478 sizeof(struct eth_segment_id
));
2480 if (gw_ip
== NULL
) {
2481 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2483 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2484 sizeof(union gw_addr
));
2488 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2489 struct eth_segment_id
*eth_s_id
,
2490 union gw_addr
*gw_ip
)
2492 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2493 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2496 if (afi
!= AFI_L2VPN
)
2499 memset(&temp
, 0, 16);
2500 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2501 info_gw_ip
= (union gw_addr
*)&temp
;
2502 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2505 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2506 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2509 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2511 info_gw_ip_remote
= gw_ip
;
2512 if (eth_s_id
== NULL
)
2513 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2515 info_eth_s_id_remote
= eth_s_id
;
2516 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2518 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2519 sizeof(struct eth_segment_id
));
2522 /* Check if received nexthop is valid or not. */
2523 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2528 /* Only validated for unicast and multicast currently. */
2529 /* Also valid for EVPN where the nexthop is an IP address. */
2530 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2533 /* If NEXT_HOP is present, validate it. */
2534 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2535 if (attr
->nexthop
.s_addr
== 0
2536 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2537 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2541 /* If MP_NEXTHOP is present, validate it. */
2542 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2543 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2544 * it is not an IPv6 link-local address.
2546 if (attr
->mp_nexthop_len
) {
2547 switch (attr
->mp_nexthop_len
) {
2548 case BGP_ATTR_NHLEN_IPV4
:
2549 case BGP_ATTR_NHLEN_VPNV4
:
2550 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2551 || IPV4_CLASS_DE(ntohl(
2552 attr
->mp_nexthop_global_in
.s_addr
))
2553 || bgp_nexthop_self(bgp
,
2554 attr
->mp_nexthop_global_in
));
2557 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2558 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2559 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2560 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2561 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2562 || IN6_IS_ADDR_MULTICAST(
2563 &attr
->mp_nexthop_global
));
2575 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2576 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2577 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2578 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2581 int aspath_loop_count
= 0;
2582 struct bgp_node
*rn
;
2584 struct attr new_attr
;
2585 struct attr
*attr_new
;
2586 struct bgp_info
*ri
;
2587 struct bgp_info
*new;
2589 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2592 int do_loop_check
= 1;
2593 int has_valid_label
= 0;
2595 int vnc_implicit_withdraw
= 0;
2599 memset(&new_attr
, 0, sizeof(struct attr
));
2600 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2601 new_attr
.label
= MPLS_INVALID_LABEL
;
2604 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2605 has_valid_label
= bgp_is_valid_label(label
);
2607 if (has_valid_label
)
2608 sprintf(label_buf
, "label %u", label_pton(label
));
2610 /* When peer's soft reconfiguration enabled. Record input packet in
2613 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2614 && peer
!= bgp
->peer_self
)
2615 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2617 /* Check previously received route. */
2618 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2619 if (ri
->peer
== peer
&& ri
->type
== type
2620 && ri
->sub_type
== sub_type
2621 && ri
->addpath_rx_id
== addpath_id
)
2624 /* AS path local-as loop check. */
2625 if (peer
->change_local_as
) {
2626 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2627 aspath_loop_count
= 1;
2629 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2630 > aspath_loop_count
) {
2631 reason
= "as-path contains our own AS;";
2636 /* If the peer is configured for "allowas-in origin" and the last ASN in
2638 * as-path is our ASN then we do not need to call aspath_loop_check
2640 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2641 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2644 /* AS path loop check. */
2645 if (do_loop_check
) {
2646 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2647 > peer
->allowas_in
[afi
][safi
]
2648 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2649 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2650 > peer
->allowas_in
[afi
][safi
])) {
2651 reason
= "as-path contains our own AS;";
2656 /* Route reflector originator ID check. */
2657 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2658 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2659 reason
= "originator is us;";
2663 /* Route reflector cluster ID check. */
2664 if (bgp_cluster_filter(peer
, attr
)) {
2665 reason
= "reflected from the same cluster;";
2669 /* Apply incoming filter. */
2670 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2675 bgp_attr_dup(&new_attr
, attr
);
2677 /* Apply incoming route-map.
2678 * NB: new_attr may now contain newly allocated values from route-map
2680 * commands, so we need bgp_attr_flush in the error paths, until we
2682 * the attr (which takes over the memory references) */
2683 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2685 reason
= "route-map;";
2686 bgp_attr_flush(&new_attr
);
2690 /* next hop check. */
2691 if (bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2692 reason
= "martian or self next-hop;";
2693 bgp_attr_flush(&new_attr
);
2697 attr_new
= bgp_attr_intern(&new_attr
);
2699 /* If the update is implicit withdraw. */
2701 ri
->uptime
= bgp_clock();
2702 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2704 /* Same attribute comes in. */
2705 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2706 && attrhash_cmp(ri
->attr
, attr_new
)
2707 && (!has_valid_label
2708 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2711 && (overlay_index_equal(
2712 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2713 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2714 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2715 BGP_CONFIG_DAMPENING
)
2716 && peer
->sort
== BGP_PEER_EBGP
2717 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2718 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2719 bgp_debug_rdpfxpath2str(
2720 afi
, safi
, prd
, p
, label
,
2721 addpath_id
? 1 : 0, addpath_id
,
2722 pfx_buf
, sizeof(pfx_buf
));
2723 zlog_debug("%s rcvd %s", peer
->host
,
2727 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2728 != BGP_DAMP_SUPPRESSED
) {
2729 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2731 bgp_process(bgp
, rn
, afi
, safi
);
2733 } else /* Duplicate - odd */
2735 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2736 if (!peer
->rcvd_attr_printed
) {
2738 "%s rcvd UPDATE w/ attr: %s",
2740 peer
->rcvd_attr_str
);
2741 peer
->rcvd_attr_printed
= 1;
2744 bgp_debug_rdpfxpath2str(
2745 afi
, safi
, prd
, p
, label
,
2746 addpath_id
? 1 : 0, addpath_id
,
2747 pfx_buf
, sizeof(pfx_buf
));
2749 "%s rcvd %s...duplicate ignored",
2750 peer
->host
, pfx_buf
);
2753 /* graceful restart STALE flag unset. */
2754 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2755 bgp_info_unset_flag(rn
, ri
,
2757 bgp_process(bgp
, rn
, afi
, safi
);
2761 bgp_unlock_node(rn
);
2762 bgp_attr_unintern(&attr_new
);
2767 /* Withdraw/Announce before we fully processed the withdraw */
2768 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2769 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2770 bgp_debug_rdpfxpath2str(
2771 afi
, safi
, prd
, p
, label
,
2772 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2775 "%s rcvd %s, flapped quicker than processing",
2776 peer
->host
, pfx_buf
);
2779 bgp_info_restore(rn
, ri
);
2782 /* Received Logging. */
2783 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2784 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2785 addpath_id
? 1 : 0, addpath_id
,
2786 pfx_buf
, sizeof(pfx_buf
));
2787 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2790 /* graceful restart STALE flag unset. */
2791 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2792 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2794 /* The attribute is changed. */
2795 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2797 /* implicit withdraw, decrement aggregate and pcount here.
2798 * only if update is accepted, they'll increment below.
2800 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2802 /* Update bgp route dampening information. */
2803 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2804 && peer
->sort
== BGP_PEER_EBGP
) {
2805 /* This is implicit withdraw so we should update
2808 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2809 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2812 if (safi
== SAFI_MPLS_VPN
) {
2813 struct bgp_node
*prn
= NULL
;
2814 struct bgp_table
*table
= NULL
;
2816 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2817 (struct prefix
*)prd
);
2819 table
= (struct bgp_table
*)(prn
->info
);
2821 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2822 bgp
, prd
, table
, p
, ri
);
2824 bgp_unlock_node(prn
);
2826 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2827 && (safi
== SAFI_UNICAST
)) {
2828 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2830 * Implicit withdraw case.
2832 ++vnc_implicit_withdraw
;
2833 vnc_import_bgp_del_route(bgp
, p
, ri
);
2834 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2839 /* Special handling for EVPN update of an existing route. If the
2840 * extended community attribute has changed, we need to
2842 * the route using its existing extended community. It will be
2843 * subsequently processed for import with the new extended
2846 if (safi
== SAFI_EVPN
&& !same_attr
) {
2848 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2850 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2853 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2854 attr_new
->ecommunity
);
2856 if (bgp_debug_update(peer
, p
, NULL
, 1))
2858 "Change in EXT-COMM, existing %s new %s",
2860 ri
->attr
->ecommunity
),
2862 attr_new
->ecommunity
));
2863 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2869 /* Update to new attribute. */
2870 bgp_attr_unintern(&ri
->attr
);
2871 ri
->attr
= attr_new
;
2873 /* Update MPLS label */
2874 if (has_valid_label
) {
2875 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2877 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2881 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2882 && (safi
== SAFI_UNICAST
)) {
2883 if (vnc_implicit_withdraw
) {
2885 * Add back the route with its new attributes
2887 * The route is still selected, until the route
2889 * queued by bgp_process actually runs. We have
2891 * update to the VNC side immediately to avoid
2893 * configuration changes (e.g., route-map
2895 * trigger re-importation of the entire RIB.
2897 vnc_import_bgp_add_route(bgp
, p
, ri
);
2898 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
2902 /* Update Overlay Index */
2903 if (afi
== AFI_L2VPN
) {
2904 overlay_index_update(
2905 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2906 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
2909 /* Update bgp route dampening information. */
2910 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2911 && peer
->sort
== BGP_PEER_EBGP
) {
2912 /* Now we do normal update dampening. */
2913 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
2914 if (ret
== BGP_DAMP_SUPPRESSED
) {
2915 bgp_unlock_node(rn
);
2920 /* Nexthop reachability check - for unicast and
2921 * labeled-unicast.. */
2922 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2923 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
2924 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
2925 && !CHECK_FLAG(peer
->flags
,
2926 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
2928 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
2933 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
2935 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2937 if (BGP_DEBUG(nht
, NHT
)) {
2938 char buf1
[INET6_ADDRSTRLEN
];
2940 (const void *)&attr_new
2942 buf1
, INET6_ADDRSTRLEN
);
2943 zlog_debug("%s(%s): NH unresolved",
2944 __FUNCTION__
, buf1
);
2946 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
2949 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2952 if (safi
== SAFI_MPLS_VPN
) {
2953 struct bgp_node
*prn
= NULL
;
2954 struct bgp_table
*table
= NULL
;
2956 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2957 (struct prefix
*)prd
);
2959 table
= (struct bgp_table
*)(prn
->info
);
2961 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
2962 bgp
, prd
, table
, p
, ri
);
2964 bgp_unlock_node(prn
);
2968 /* If this is an EVPN route and some attribute has changed,
2970 * route for import. If the extended community has changed, we
2972 * have done the un-import earlier and the import would result
2974 * route getting injected into appropriate L2 VNIs. If it is
2976 * some other attribute change, the import will result in
2978 * the attributes for the route in the VNI(s).
2980 if (safi
== SAFI_EVPN
&& !same_attr
)
2981 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
2983 /* Process change. */
2984 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
2986 bgp_process(bgp
, rn
, afi
, safi
);
2987 bgp_unlock_node(rn
);
2990 if (SAFI_MPLS_VPN
== safi
) {
2991 mpls_label_t label_decoded
= decode_label(label
);
2993 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2994 type
, sub_type
, &label_decoded
);
2996 if (SAFI_ENCAP
== safi
) {
2997 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2998 type
, sub_type
, NULL
);
3003 } // End of implicit withdraw
3005 /* Received Logging. */
3006 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3007 if (!peer
->rcvd_attr_printed
) {
3008 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3009 peer
->rcvd_attr_str
);
3010 peer
->rcvd_attr_printed
= 1;
3013 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3014 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3016 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3019 /* Make new BGP info. */
3020 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3022 /* Update MPLS label */
3023 if (has_valid_label
) {
3024 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3026 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3029 /* Update Overlay Index */
3030 if (afi
== AFI_L2VPN
) {
3031 overlay_index_update(new->attr
,
3032 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3033 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3035 /* Nexthop reachability check. */
3036 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3037 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3038 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3039 && !CHECK_FLAG(peer
->flags
,
3040 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3041 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3046 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
))
3047 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3049 if (BGP_DEBUG(nht
, NHT
)) {
3050 char buf1
[INET6_ADDRSTRLEN
];
3052 (const void *)&attr_new
->nexthop
,
3053 buf1
, INET6_ADDRSTRLEN
);
3054 zlog_debug("%s(%s): NH unresolved",
3055 __FUNCTION__
, buf1
);
3057 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3060 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3063 new->addpath_rx_id
= addpath_id
;
3065 /* Increment prefix */
3066 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3068 /* Register new BGP information. */
3069 bgp_info_add(rn
, new);
3071 /* route_node_get lock */
3072 bgp_unlock_node(rn
);
3075 if (safi
== SAFI_MPLS_VPN
) {
3076 struct bgp_node
*prn
= NULL
;
3077 struct bgp_table
*table
= NULL
;
3079 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3081 table
= (struct bgp_table
*)(prn
->info
);
3083 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3084 bgp
, prd
, table
, p
, new);
3086 bgp_unlock_node(prn
);
3090 /* If maximum prefix count is configured and current prefix
3092 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3095 /* If this is an EVPN route, process for import. */
3096 if (safi
== SAFI_EVPN
)
3097 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3099 /* Process change. */
3100 bgp_process(bgp
, rn
, afi
, safi
);
3103 if (SAFI_MPLS_VPN
== safi
) {
3104 mpls_label_t label_decoded
= decode_label(label
);
3106 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3107 sub_type
, &label_decoded
);
3109 if (SAFI_ENCAP
== safi
) {
3110 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3117 /* This BGP update is filtered. Log the reason then update BGP
3120 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3121 if (!peer
->rcvd_attr_printed
) {
3122 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3123 peer
->rcvd_attr_str
);
3124 peer
->rcvd_attr_printed
= 1;
3127 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3128 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3130 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3131 peer
->host
, pfx_buf
, reason
);
3135 /* If this is an EVPN route, un-import it as it is now filtered.
3137 if (safi
== SAFI_EVPN
)
3138 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3140 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3143 bgp_unlock_node(rn
);
3147 * Filtered update is treated as an implicit withdrawal (see
3149 * a few lines above)
3151 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3152 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3160 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3161 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3162 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3163 struct bgp_route_evpn
*evpn
)
3166 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3167 struct bgp_node
*rn
;
3168 struct bgp_info
*ri
;
3171 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3172 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3180 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3182 /* If peer is soft reconfiguration enabled. Record input packet for
3183 * further calculation.
3185 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3186 * routes that are filtered. This tanks out Quagga RS pretty badly due
3188 * the iteration over all RS clients.
3189 * Since we need to remove the entry from adj_in anyway, do that first
3191 * if there was no entry, we don't need to do anything more.
3193 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3194 && peer
!= bgp
->peer_self
)
3195 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3196 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3197 bgp_debug_rdpfxpath2str(
3198 afi
, safi
, prd
, p
, label
,
3199 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3202 "%s withdrawing route %s not in adj-in",
3203 peer
->host
, pfx_buf
);
3205 bgp_unlock_node(rn
);
3209 /* Lookup withdrawn route. */
3210 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3211 if (ri
->peer
== peer
&& ri
->type
== type
3212 && ri
->sub_type
== sub_type
3213 && ri
->addpath_rx_id
== addpath_id
)
3217 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3218 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3219 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3221 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3225 /* Withdraw specified route from routing table. */
3226 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3227 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3228 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3229 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3230 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3232 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3235 /* Unlock bgp_node_get() lock. */
3236 bgp_unlock_node(rn
);
3241 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3244 struct update_subgroup
*subgrp
;
3245 subgrp
= peer_subgroup(peer
, afi
, safi
);
3246 subgroup_default_originate(subgrp
, withdraw
);
3251 * bgp_stop_announce_route_timer
3253 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3255 if (!paf
->t_announce_route
)
3258 THREAD_TIMER_OFF(paf
->t_announce_route
);
3262 * bgp_announce_route_timer_expired
3264 * Callback that is invoked when the route announcement timer for a
3267 static int bgp_announce_route_timer_expired(struct thread
*t
)
3269 struct peer_af
*paf
;
3272 paf
= THREAD_ARG(t
);
3275 if (peer
->status
!= Established
)
3278 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3281 peer_af_announce_route(paf
, 1);
3286 * bgp_announce_route
3288 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3290 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3292 struct peer_af
*paf
;
3293 struct update_subgroup
*subgrp
;
3295 paf
= peer_af_find(peer
, afi
, safi
);
3298 subgrp
= PAF_SUBGRP(paf
);
3301 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3302 * or a refresh has already been triggered.
3304 if (!subgrp
|| paf
->t_announce_route
)
3308 * Start a timer to stagger/delay the announce. This serves
3309 * two purposes - announcement can potentially be combined for
3310 * multiple peers and the announcement doesn't happen in the
3313 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3314 (subgrp
->peer_count
== 1)
3315 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3316 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3317 &paf
->t_announce_route
);
3321 * Announce routes from all AF tables to a peer.
3323 * This should ONLY be called when there is a need to refresh the
3324 * routes to the peer based on a policy change for this peer alone
3325 * or a route refresh request received from the peer.
3326 * The operation will result in splitting the peer from its existing
3327 * subgroups and putting it in new subgroups.
3329 void bgp_announce_route_all(struct peer
*peer
)
3334 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3335 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3336 bgp_announce_route(peer
, afi
, safi
);
3339 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3340 struct bgp_table
*table
,
3341 struct prefix_rd
*prd
)
3344 struct bgp_node
*rn
;
3345 struct bgp_adj_in
*ain
;
3348 table
= peer
->bgp
->rib
[afi
][safi
];
3350 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3351 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3352 if (ain
->peer
== peer
) {
3353 struct bgp_info
*ri
= rn
->info
;
3354 mpls_label_t label
=
3355 (ri
&& ri
->extra
) ? ri
->extra
->label
3356 : MPLS_INVALID_LABEL
;
3359 peer
, &rn
->p
, ain
->addpath_rx_id
,
3360 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3361 BGP_ROUTE_NORMAL
, prd
, &label
, 1, NULL
);
3364 bgp_unlock_node(rn
);
3371 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3373 struct bgp_node
*rn
;
3374 struct bgp_table
*table
;
3376 if (peer
->status
!= Established
)
3379 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3380 && (safi
!= SAFI_EVPN
))
3381 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3383 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3384 rn
= bgp_route_next(rn
))
3385 if ((table
= rn
->info
) != NULL
) {
3386 struct prefix_rd prd
;
3387 prd
.family
= AF_UNSPEC
;
3389 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3391 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3397 struct bgp_clear_node_queue
{
3398 struct bgp_node
*rn
;
3401 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3403 struct bgp_clear_node_queue
*cnq
= data
;
3404 struct bgp_node
*rn
= cnq
->rn
;
3405 struct peer
*peer
= wq
->spec
.data
;
3406 struct bgp_info
*ri
;
3407 afi_t afi
= bgp_node_table(rn
)->afi
;
3408 safi_t safi
= bgp_node_table(rn
)->safi
;
3412 /* It is possible that we have multiple paths for a prefix from a peer
3413 * if that peer is using AddPath.
3415 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3416 if (ri
->peer
== peer
) {
3417 /* graceful restart STALE flag set. */
3418 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3419 && peer
->nsf
[afi
][safi
]
3420 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3421 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3422 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3424 /* If this is an EVPN route, process for
3426 if (safi
== SAFI_EVPN
)
3427 bgp_evpn_unimport_route(peer
->bgp
, afi
,
3430 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3436 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3438 struct bgp_clear_node_queue
*cnq
= data
;
3439 struct bgp_node
*rn
= cnq
->rn
;
3440 struct bgp_table
*table
= bgp_node_table(rn
);
3442 bgp_unlock_node(rn
);
3443 bgp_table_unlock(table
);
3444 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3447 static void bgp_clear_node_complete(struct work_queue
*wq
)
3449 struct peer
*peer
= wq
->spec
.data
;
3451 /* Tickle FSM to start moving again */
3452 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3454 peer_unlock(peer
); /* bgp_clear_route */
3457 static void bgp_clear_node_queue_init(struct peer
*peer
)
3459 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3461 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3462 #undef CLEAR_QUEUE_NAME_LEN
3464 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3466 zlog_err("%s: Failed to allocate work queue", __func__
);
3469 peer
->clear_node_queue
->spec
.hold
= 10;
3470 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3471 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3472 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3473 peer
->clear_node_queue
->spec
.max_retries
= 0;
3475 /* we only 'lock' this peer reference when the queue is actually active
3477 peer
->clear_node_queue
->spec
.data
= peer
;
3480 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3481 struct bgp_table
*table
)
3483 struct bgp_node
*rn
;
3484 int force
= bm
->process_main_queue
? 0 : 1;
3487 table
= peer
->bgp
->rib
[afi
][safi
];
3489 /* If still no table => afi/safi isn't configured at all or smth. */
3493 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3494 struct bgp_info
*ri
, *next
;
3495 struct bgp_adj_in
*ain
;
3496 struct bgp_adj_in
*ain_next
;
3498 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3499 * queued for every clearing peer, regardless of whether it is
3500 * relevant to the peer at hand.
3502 * Overview: There are 3 different indices which need to be
3503 * scrubbed, potentially, when a peer is removed:
3505 * 1 peer's routes visible via the RIB (ie accepted routes)
3506 * 2 peer's routes visible by the (optional) peer's adj-in index
3507 * 3 other routes visible by the peer's adj-out index
3509 * 3 there is no hurry in scrubbing, once the struct peer is
3510 * removed from bgp->peer, we could just GC such deleted peer's
3511 * adj-outs at our leisure.
3513 * 1 and 2 must be 'scrubbed' in some way, at least made
3514 * invisible via RIB index before peer session is allowed to be
3515 * brought back up. So one needs to know when such a 'search' is
3520 * - there'd be a single global queue or a single RIB walker
3521 * - rather than tracking which route_nodes still need to be
3522 * examined on a peer basis, we'd track which peers still
3525 * Given that our per-peer prefix-counts now should be reliable,
3526 * this may actually be achievable. It doesn't seem to be a huge
3527 * problem at this time,
3529 * It is possible that we have multiple paths for a prefix from
3531 * if that peer is using AddPath.
3535 ain_next
= ain
->next
;
3537 if (ain
->peer
== peer
) {
3538 bgp_adj_in_remove(rn
, ain
);
3539 bgp_unlock_node(rn
);
3545 for (ri
= rn
->info
; ri
; ri
= next
) {
3547 if (ri
->peer
!= peer
)
3551 bgp_info_reap(rn
, ri
);
3553 struct bgp_clear_node_queue
*cnq
;
3555 /* both unlocked in bgp_clear_node_queue_del */
3556 bgp_table_lock(bgp_node_table(rn
));
3559 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3560 sizeof(struct bgp_clear_node_queue
));
3562 work_queue_add(peer
->clear_node_queue
, cnq
);
3570 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3572 struct bgp_node
*rn
;
3573 struct bgp_table
*table
;
3575 if (peer
->clear_node_queue
== NULL
)
3576 bgp_clear_node_queue_init(peer
);
3578 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3579 * Idle until it receives a Clearing_Completed event. This protects
3580 * against peers which flap faster than we can we clear, which could
3583 * a) race with routes from the new session being installed before
3584 * clear_route_node visits the node (to delete the route of that
3586 * b) resource exhaustion, clear_route_node likely leads to an entry
3587 * on the process_main queue. Fast-flapping could cause that queue
3591 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3592 * the unlock will happen upon work-queue completion; other wise, the
3593 * unlock happens at the end of this function.
3595 if (!peer
->clear_node_queue
->thread
)
3598 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3599 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3601 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3602 rn
= bgp_route_next(rn
))
3603 if ((table
= rn
->info
) != NULL
)
3604 bgp_clear_route_table(peer
, afi
, safi
, table
);
3606 /* unlock if no nodes got added to the clear-node-queue. */
3607 if (!peer
->clear_node_queue
->thread
)
3611 void bgp_clear_route_all(struct peer
*peer
)
3616 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3617 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3618 bgp_clear_route(peer
, afi
, safi
);
3621 rfapiProcessPeerDown(peer
);
3625 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3627 struct bgp_table
*table
;
3628 struct bgp_node
*rn
;
3629 struct bgp_adj_in
*ain
;
3630 struct bgp_adj_in
*ain_next
;
3632 table
= peer
->bgp
->rib
[afi
][safi
];
3634 /* It is possible that we have multiple paths for a prefix from a peer
3635 * if that peer is using AddPath.
3637 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3641 ain_next
= ain
->next
;
3643 if (ain
->peer
== peer
) {
3644 bgp_adj_in_remove(rn
, ain
);
3645 bgp_unlock_node(rn
);
3653 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3655 struct bgp_node
*rn
;
3656 struct bgp_info
*ri
;
3657 struct bgp_table
*table
;
3659 if (safi
== SAFI_MPLS_VPN
) {
3660 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3661 rn
= bgp_route_next(rn
)) {
3662 struct bgp_node
*rm
;
3663 struct bgp_info
*ri
;
3665 /* look for neighbor in tables */
3666 if ((table
= rn
->info
) != NULL
) {
3667 for (rm
= bgp_table_top(table
); rm
;
3668 rm
= bgp_route_next(rm
))
3669 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
3670 if (ri
->peer
== peer
) {
3684 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3685 rn
= bgp_route_next(rn
))
3686 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3687 if (ri
->peer
== peer
) {
3688 if (CHECK_FLAG(ri
->flags
,
3690 bgp_rib_remove(rn
, ri
, peer
,
3697 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3699 struct bgp_node
*rn
;
3700 struct bgp_info
*ri
;
3701 struct bgp_info
*next
;
3703 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3704 for (ri
= rn
->info
; ri
; ri
= next
) {
3706 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3707 && ri
->type
== ZEBRA_ROUTE_BGP
3708 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3709 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3710 if (bgp_fibupd_safi(safi
))
3711 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3712 bgp_info_reap(rn
, ri
);
3717 /* Delete all kernel routes. */
3718 void bgp_cleanup_routes(struct bgp
*bgp
)
3721 struct bgp_node
*rn
;
3723 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3724 if (afi
== AFI_L2VPN
)
3726 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3728 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3730 if (afi
!= AFI_L2VPN
) {
3732 safi
= SAFI_MPLS_VPN
;
3733 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3734 rn
= bgp_route_next(rn
)) {
3737 (struct bgp_table
*)(rn
->info
),
3739 bgp_table_finish((struct bgp_table
**)&(
3742 bgp_unlock_node(rn
);
3746 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3747 rn
= bgp_route_next(rn
)) {
3750 (struct bgp_table
*)(rn
->info
),
3752 bgp_table_finish((struct bgp_table
**)&(
3755 bgp_unlock_node(rn
);
3760 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3761 rn
= bgp_route_next(rn
)) {
3763 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3765 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3767 bgp_unlock_node(rn
);
3772 void bgp_reset(void)
3775 bgp_zclient_reset();
3776 access_list_reset();
3777 prefix_list_reset();
3780 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3782 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3783 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3784 PEER_CAP_ADDPATH_AF_TX_RCV
));
3787 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3789 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3790 struct bgp_nlri
*packet
)
3799 int addpath_encoded
;
3800 u_int32_t addpath_id
;
3802 /* Check peer status. */
3803 if (peer
->status
!= Established
)
3807 lim
= pnt
+ packet
->length
;
3809 safi
= packet
->safi
;
3811 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3813 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3814 syntactic validity. If the field is syntactically incorrect,
3815 then the Error Subcode is set to Invalid Network Field. */
3816 for (; pnt
< lim
; pnt
+= psize
) {
3817 /* Clear prefix structure. */
3818 memset(&p
, 0, sizeof(struct prefix
));
3820 if (addpath_encoded
) {
3822 /* When packet overflow occurs return immediately. */
3823 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3826 addpath_id
= ntohl(*((uint32_t *)pnt
));
3827 pnt
+= BGP_ADDPATH_ID_LEN
;
3830 /* Fetch prefix length. */
3831 p
.prefixlen
= *pnt
++;
3832 /* afi/safi validity already verified by caller,
3833 * bgp_update_receive */
3834 p
.family
= afi2family(afi
);
3836 /* Prefix length check. */
3837 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3839 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3840 peer
->host
, p
.prefixlen
, packet
->afi
);
3844 /* Packet size overflow check. */
3845 psize
= PSIZE(p
.prefixlen
);
3847 /* When packet overflow occur return immediately. */
3848 if (pnt
+ psize
> lim
) {
3850 "%s [Error] Update packet error (prefix length %d overflows packet)",
3851 peer
->host
, p
.prefixlen
);
3855 /* Defensive coding, double-check the psize fits in a struct
3857 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3859 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3860 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3864 /* Fetch prefix from NLRI packet. */
3865 memcpy(&p
.u
.prefix
, pnt
, psize
);
3867 /* Check address. */
3868 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3869 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3870 /* From RFC4271 Section 6.3:
3872 * If a prefix in the NLRI field is semantically
3874 * (e.g., an unexpected multicast IP address),
3876 * be logged locally, and the prefix SHOULD be
3880 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3881 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3886 /* Check address. */
3887 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3888 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3892 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3894 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3899 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
3903 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
3905 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3912 /* Normal process. */
3914 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
3915 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
3916 NULL
, NULL
, 0, NULL
);
3918 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
3919 safi
, ZEBRA_ROUTE_BGP
,
3920 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
3922 /* Address family configuration mismatch or maximum-prefix count
3928 /* Packet length consistency check. */
3931 "%s [Error] Update packet error (prefix length mismatch with total length)",
3939 static struct bgp_static
*bgp_static_new(void)
3941 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
3944 static void bgp_static_free(struct bgp_static
*bgp_static
)
3946 if (bgp_static
->rmap
.name
)
3947 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
3948 if (bgp_static
->eth_s_id
)
3949 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
3950 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
3953 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
3954 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
3956 struct bgp_node
*rn
;
3957 struct bgp_info
*ri
;
3958 struct bgp_info
*new;
3959 struct bgp_info info
;
3961 struct attr
*attr_new
;
3964 int vnc_implicit_withdraw
= 0;
3971 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
3973 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
3975 attr
.nexthop
= bgp_static
->igpnexthop
;
3976 attr
.med
= bgp_static
->igpmetric
;
3977 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
3979 if (bgp_static
->atomic
)
3980 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
3982 /* Store label index, if required. */
3983 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3984 attr
.label_index
= bgp_static
->label_index
;
3985 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3988 /* Apply route-map. */
3989 if (bgp_static
->rmap
.name
) {
3990 struct attr attr_tmp
= attr
;
3991 info
.peer
= bgp
->peer_self
;
3992 info
.attr
= &attr_tmp
;
3994 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
3996 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
3998 bgp
->peer_self
->rmap_type
= 0;
4000 if (ret
== RMAP_DENYMATCH
) {
4001 /* Free uninterned attribute. */
4002 bgp_attr_flush(&attr_tmp
);
4004 /* Unintern original. */
4005 aspath_unintern(&attr
.aspath
);
4006 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4009 attr_new
= bgp_attr_intern(&attr_tmp
);
4011 attr_new
= bgp_attr_intern(&attr
);
4013 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4014 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4015 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4019 if (attrhash_cmp(ri
->attr
, attr_new
)
4020 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4021 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4022 bgp_unlock_node(rn
);
4023 bgp_attr_unintern(&attr_new
);
4024 aspath_unintern(&attr
.aspath
);
4027 /* The attribute is changed. */
4028 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4030 /* Rewrite BGP route information. */
4031 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4032 bgp_info_restore(rn
, ri
);
4034 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4036 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4037 && (safi
== SAFI_UNICAST
)) {
4038 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4040 * Implicit withdraw case.
4041 * We have to do this before ri is
4044 ++vnc_implicit_withdraw
;
4045 vnc_import_bgp_del_route(bgp
, p
, ri
);
4046 vnc_import_bgp_exterior_del_route(
4051 bgp_attr_unintern(&ri
->attr
);
4052 ri
->attr
= attr_new
;
4053 ri
->uptime
= bgp_clock();
4055 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4056 && (safi
== SAFI_UNICAST
)) {
4057 if (vnc_implicit_withdraw
) {
4058 vnc_import_bgp_add_route(bgp
, p
, ri
);
4059 vnc_import_bgp_exterior_add_route(
4065 /* Nexthop reachability check. */
4066 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4067 && (safi
== SAFI_UNICAST
4068 || safi
== SAFI_LABELED_UNICAST
)) {
4069 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4071 bgp_info_set_flag(rn
, ri
,
4074 if (BGP_DEBUG(nht
, NHT
)) {
4075 char buf1
[INET6_ADDRSTRLEN
];
4076 inet_ntop(p
->family
,
4080 "%s(%s): Route not in table, not advertising",
4081 __FUNCTION__
, buf1
);
4083 bgp_info_unset_flag(rn
, ri
,
4087 /* Delete the NHT structure if any, if we're
4089 * enabling/disabling import check. We
4090 * deregister the route
4091 * from NHT to avoid overloading NHT and the
4092 * process interaction
4094 bgp_unlink_nexthop(ri
);
4095 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4097 /* Process change. */
4098 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4099 bgp_process(bgp
, rn
, afi
, safi
);
4100 bgp_unlock_node(rn
);
4101 aspath_unintern(&attr
.aspath
);
4106 /* Make new BGP info. */
4107 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4109 /* Nexthop reachability check. */
4110 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4111 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4112 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4113 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4115 if (BGP_DEBUG(nht
, NHT
)) {
4116 char buf1
[INET6_ADDRSTRLEN
];
4117 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4120 "%s(%s): Route not in table, not advertising",
4121 __FUNCTION__
, buf1
);
4123 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4126 /* Delete the NHT structure if any, if we're toggling between
4127 * enabling/disabling import check. We deregister the route
4128 * from NHT to avoid overloading NHT and the process interaction
4130 bgp_unlink_nexthop(new);
4132 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4135 /* Aggregate address increment. */
4136 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4138 /* Register new BGP information. */
4139 bgp_info_add(rn
, new);
4141 /* route_node_get lock */
4142 bgp_unlock_node(rn
);
4144 /* Process change. */
4145 bgp_process(bgp
, rn
, afi
, safi
);
4147 /* Unintern original. */
4148 aspath_unintern(&attr
.aspath
);
4151 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4154 struct bgp_node
*rn
;
4155 struct bgp_info
*ri
;
4157 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4159 /* Check selected route and self inserted route. */
4160 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4161 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4162 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4165 /* Withdraw static BGP route from routing table. */
4167 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4168 bgp_unlink_nexthop(ri
);
4169 bgp_info_delete(rn
, ri
);
4170 bgp_process(bgp
, rn
, afi
, safi
);
4173 /* Unlock bgp_node_lookup. */
4174 bgp_unlock_node(rn
);
4178 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4180 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4181 afi_t afi
, safi_t safi
,
4182 struct prefix_rd
*prd
)
4184 struct bgp_node
*rn
;
4185 struct bgp_info
*ri
;
4187 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4189 /* Check selected route and self inserted route. */
4190 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4191 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4192 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4195 /* Withdraw static BGP route from routing table. */
4198 rfapiProcessWithdraw(
4199 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4200 1); /* Kill, since it is an administrative change */
4202 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4203 bgp_info_delete(rn
, ri
);
4204 bgp_process(bgp
, rn
, afi
, safi
);
4207 /* Unlock bgp_node_lookup. */
4208 bgp_unlock_node(rn
);
4211 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4212 struct bgp_static
*bgp_static
, afi_t afi
,
4215 struct bgp_node
*rn
;
4216 struct bgp_info
*new;
4217 struct attr
*attr_new
;
4218 struct attr attr
= {0};
4219 struct bgp_info
*ri
;
4221 mpls_label_t label
= 0;
4227 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4230 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4232 attr
.nexthop
= bgp_static
->igpnexthop
;
4233 attr
.med
= bgp_static
->igpmetric
;
4234 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4236 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4237 || (safi
== SAFI_ENCAP
)) {
4238 if (afi
== AFI_IP
) {
4239 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4240 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4243 if (afi
== AFI_L2VPN
) {
4244 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4246 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4247 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4248 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4249 sizeof(struct in6_addr
));
4250 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4251 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4252 struct bgp_encap_type_vxlan bet
;
4253 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4254 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4255 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4257 if (bgp_static
->router_mac
) {
4258 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4261 /* Apply route-map. */
4262 if (bgp_static
->rmap
.name
) {
4263 struct attr attr_tmp
= attr
;
4264 struct bgp_info info
;
4267 info
.peer
= bgp
->peer_self
;
4268 info
.attr
= &attr_tmp
;
4270 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4272 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4274 bgp
->peer_self
->rmap_type
= 0;
4276 if (ret
== RMAP_DENYMATCH
) {
4277 /* Free uninterned attribute. */
4278 bgp_attr_flush(&attr_tmp
);
4280 /* Unintern original. */
4281 aspath_unintern(&attr
.aspath
);
4282 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4287 attr_new
= bgp_attr_intern(&attr_tmp
);
4289 attr_new
= bgp_attr_intern(&attr
);
4292 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4293 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4294 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4299 memset(&add
, 0, sizeof(union gw_addr
));
4300 if (attrhash_cmp(ri
->attr
, attr_new
)
4301 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4302 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4303 bgp_unlock_node(rn
);
4304 bgp_attr_unintern(&attr_new
);
4305 aspath_unintern(&attr
.aspath
);
4308 /* The attribute is changed. */
4309 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4311 /* Rewrite BGP route information. */
4312 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4313 bgp_info_restore(rn
, ri
);
4315 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4316 bgp_attr_unintern(&ri
->attr
);
4317 ri
->attr
= attr_new
;
4318 ri
->uptime
= bgp_clock();
4321 label
= decode_label(&ri
->extra
->label
);
4324 /* Process change. */
4325 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4326 bgp_process(bgp
, rn
, afi
, safi
);
4328 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4329 ri
->attr
, afi
, safi
, ri
->type
,
4330 ri
->sub_type
, &label
);
4332 bgp_unlock_node(rn
);
4333 aspath_unintern(&attr
.aspath
);
4339 /* Make new BGP info. */
4340 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4342 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4343 new->extra
= bgp_info_extra_new();
4344 new->extra
->label
= bgp_static
->label
;
4346 label
= decode_label(&bgp_static
->label
);
4349 /* Aggregate address increment. */
4350 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4352 /* Register new BGP information. */
4353 bgp_info_add(rn
, new);
4354 /* route_node_get lock */
4355 bgp_unlock_node(rn
);
4357 /* Process change. */
4358 bgp_process(bgp
, rn
, afi
, safi
);
4361 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4362 safi
, new->type
, new->sub_type
, &label
);
4365 /* Unintern original. */
4366 aspath_unintern(&attr
.aspath
);
4369 /* Configure static BGP network. When user don't run zebra, static
4370 route should be installed as valid. */
4371 static int bgp_static_set(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4372 safi_t safi
, const char *rmap
, int backdoor
,
4373 u_int32_t label_index
)
4375 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4378 struct bgp_static
*bgp_static
;
4379 struct bgp_node
*rn
;
4380 u_char need_update
= 0;
4382 /* Convert IP prefix string to struct prefix. */
4383 ret
= str2prefix(ip_str
, &p
);
4385 vty_out(vty
, "%% Malformed prefix\n");
4386 return CMD_WARNING_CONFIG_FAILED
;
4388 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4389 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4390 return CMD_WARNING_CONFIG_FAILED
;
4395 /* Set BGP static route configuration. */
4396 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4399 /* Configuration change. */
4400 bgp_static
= rn
->info
;
4402 /* Label index cannot be changed. */
4403 if (bgp_static
->label_index
!= label_index
) {
4404 vty_out(vty
, "%% Label index cannot be changed\n");
4405 return CMD_WARNING_CONFIG_FAILED
;
4408 /* Check previous routes are installed into BGP. */
4409 if (bgp_static
->valid
&& bgp_static
->backdoor
!= backdoor
)
4412 bgp_static
->backdoor
= backdoor
;
4415 if (bgp_static
->rmap
.name
)
4416 XFREE(MTYPE_ROUTE_MAP_NAME
,
4417 bgp_static
->rmap
.name
);
4418 bgp_static
->rmap
.name
=
4419 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4420 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4422 if (bgp_static
->rmap
.name
)
4423 XFREE(MTYPE_ROUTE_MAP_NAME
,
4424 bgp_static
->rmap
.name
);
4425 bgp_static
->rmap
.name
= NULL
;
4426 bgp_static
->rmap
.map
= NULL
;
4427 bgp_static
->valid
= 0;
4429 bgp_unlock_node(rn
);
4431 /* New configuration. */
4432 bgp_static
= bgp_static_new();
4433 bgp_static
->backdoor
= backdoor
;
4434 bgp_static
->valid
= 0;
4435 bgp_static
->igpmetric
= 0;
4436 bgp_static
->igpnexthop
.s_addr
= 0;
4437 bgp_static
->label_index
= label_index
;
4440 if (bgp_static
->rmap
.name
)
4441 XFREE(MTYPE_ROUTE_MAP_NAME
,
4442 bgp_static
->rmap
.name
);
4443 bgp_static
->rmap
.name
=
4444 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4445 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4447 rn
->info
= bgp_static
;
4450 bgp_static
->valid
= 1;
4452 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4454 if (!bgp_static
->backdoor
)
4455 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4460 /* Configure static BGP network. */
4461 static int bgp_static_unset(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4464 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4467 struct bgp_static
*bgp_static
;
4468 struct bgp_node
*rn
;
4470 /* Convert IP prefix string to struct prefix. */
4471 ret
= str2prefix(ip_str
, &p
);
4473 vty_out(vty
, "%% Malformed prefix\n");
4474 return CMD_WARNING_CONFIG_FAILED
;
4476 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4477 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4478 return CMD_WARNING_CONFIG_FAILED
;
4483 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4486 "%% Can't find specified static route configuration.\n");
4487 return CMD_WARNING_CONFIG_FAILED
;
4490 bgp_static
= rn
->info
;
4492 /* Update BGP RIB. */
4493 if (!bgp_static
->backdoor
)
4494 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4496 /* Clear configuration. */
4497 bgp_static_free(bgp_static
);
4499 bgp_unlock_node(rn
);
4500 bgp_unlock_node(rn
);
4505 void bgp_static_add(struct bgp
*bgp
)
4509 struct bgp_node
*rn
;
4510 struct bgp_node
*rm
;
4511 struct bgp_table
*table
;
4512 struct bgp_static
*bgp_static
;
4514 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4515 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4516 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4517 rn
= bgp_route_next(rn
))
4518 if (rn
->info
!= NULL
) {
4519 if ((safi
== SAFI_MPLS_VPN
)
4520 || (safi
== SAFI_ENCAP
)
4521 || (safi
== SAFI_EVPN
)) {
4524 for (rm
= bgp_table_top(table
);
4526 rm
= bgp_route_next(rm
)) {
4527 bgp_static
= rm
->info
;
4528 bgp_static_update_safi(
4534 bgp_static_update(bgp
, &rn
->p
,
4541 /* Called from bgp_delete(). Delete all static routes from the BGP
4543 void bgp_static_delete(struct bgp
*bgp
)
4547 struct bgp_node
*rn
;
4548 struct bgp_node
*rm
;
4549 struct bgp_table
*table
;
4550 struct bgp_static
*bgp_static
;
4552 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4553 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4554 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4555 rn
= bgp_route_next(rn
))
4556 if (rn
->info
!= NULL
) {
4557 if ((safi
== SAFI_MPLS_VPN
)
4558 || (safi
== SAFI_ENCAP
)
4559 || (safi
== SAFI_EVPN
)) {
4562 for (rm
= bgp_table_top(table
);
4564 rm
= bgp_route_next(rm
)) {
4565 bgp_static
= rm
->info
;
4566 bgp_static_withdraw_safi(
4575 bgp_unlock_node(rn
);
4578 bgp_static
= rn
->info
;
4579 bgp_static_withdraw(bgp
, &rn
->p
,
4581 bgp_static_free(bgp_static
);
4583 bgp_unlock_node(rn
);
4588 void bgp_static_redo_import_check(struct bgp
*bgp
)
4592 struct bgp_node
*rn
;
4593 struct bgp_node
*rm
;
4594 struct bgp_table
*table
;
4595 struct bgp_static
*bgp_static
;
4597 /* Use this flag to force reprocessing of the route */
4598 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4599 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4600 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4601 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4602 rn
= bgp_route_next(rn
))
4603 if (rn
->info
!= NULL
) {
4604 if ((safi
== SAFI_MPLS_VPN
)
4605 || (safi
== SAFI_ENCAP
)
4606 || (safi
== SAFI_EVPN
)) {
4609 for (rm
= bgp_table_top(table
);
4611 rm
= bgp_route_next(rm
)) {
4612 bgp_static
= rm
->info
;
4613 bgp_static_update_safi(
4619 bgp_static
= rn
->info
;
4620 bgp_static_update(bgp
, &rn
->p
,
4625 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4628 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4631 struct bgp_table
*table
;
4632 struct bgp_node
*rn
;
4633 struct bgp_info
*ri
;
4635 table
= bgp
->rib
[afi
][safi
];
4636 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4637 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4638 if (ri
->peer
== bgp
->peer_self
4639 && ((ri
->type
== ZEBRA_ROUTE_BGP
4640 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4641 || (ri
->type
!= ZEBRA_ROUTE_BGP
4643 == BGP_ROUTE_REDISTRIBUTE
))) {
4644 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4646 bgp_unlink_nexthop(ri
);
4647 bgp_info_delete(rn
, ri
);
4648 bgp_process(bgp
, rn
, afi
, safi
);
4655 * Purge all networks and redistributed routes from routing table.
4656 * Invoked upon the instance going down.
4658 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4663 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4664 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4665 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4670 * Currently this is used to set static routes for VPN and ENCAP.
4671 * I think it can probably be factored with bgp_static_set.
4673 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4674 const char *ip_str
, const char *rd_str
,
4675 const char *label_str
, const char *rmap_str
,
4676 int evpn_type
, const char *esi
, const char *gwip
,
4677 const char *ethtag
, const char *routermac
)
4679 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4682 struct prefix_rd prd
;
4683 struct bgp_node
*prn
;
4684 struct bgp_node
*rn
;
4685 struct bgp_table
*table
;
4686 struct bgp_static
*bgp_static
;
4687 mpls_label_t label
= MPLS_INVALID_LABEL
;
4688 struct prefix gw_ip
;
4690 /* validate ip prefix */
4691 ret
= str2prefix(ip_str
, &p
);
4693 vty_out(vty
, "%% Malformed prefix\n");
4694 return CMD_WARNING_CONFIG_FAILED
;
4697 if ((afi
== AFI_L2VPN
)
4698 && (bgp_build_evpn_prefix(evpn_type
,
4699 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4700 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4701 return CMD_WARNING_CONFIG_FAILED
;
4704 ret
= str2prefix_rd(rd_str
, &prd
);
4706 vty_out(vty
, "%% Malformed rd\n");
4707 return CMD_WARNING_CONFIG_FAILED
;
4711 unsigned long label_val
;
4712 label_val
= strtoul(label_str
, NULL
, 10);
4713 encode_label(label_val
, &label
);
4716 if (safi
== SAFI_EVPN
) {
4717 if (esi
&& str2esi(esi
, NULL
) == 0) {
4718 vty_out(vty
, "%% Malformed ESI\n");
4719 return CMD_WARNING_CONFIG_FAILED
;
4721 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4722 vty_out(vty
, "%% Malformed Router MAC\n");
4723 return CMD_WARNING_CONFIG_FAILED
;
4726 memset(&gw_ip
, 0, sizeof(struct prefix
));
4727 ret
= str2prefix(gwip
, &gw_ip
);
4729 vty_out(vty
, "%% Malformed GatewayIp\n");
4730 return CMD_WARNING_CONFIG_FAILED
;
4732 if ((gw_ip
.family
== AF_INET
4733 && IS_EVPN_PREFIX_IPADDR_V6(
4734 (struct prefix_evpn
*)&p
))
4735 || (gw_ip
.family
== AF_INET6
4736 && IS_EVPN_PREFIX_IPADDR_V4(
4737 (struct prefix_evpn
*)&p
))) {
4739 "%% GatewayIp family differs with IP prefix\n");
4740 return CMD_WARNING_CONFIG_FAILED
;
4744 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4745 if (prn
->info
== NULL
)
4746 prn
->info
= bgp_table_init(afi
, safi
);
4748 bgp_unlock_node(prn
);
4751 rn
= bgp_node_get(table
, &p
);
4754 vty_out(vty
, "%% Same network configuration exists\n");
4755 bgp_unlock_node(rn
);
4757 /* New configuration. */
4758 bgp_static
= bgp_static_new();
4759 bgp_static
->backdoor
= 0;
4760 bgp_static
->valid
= 0;
4761 bgp_static
->igpmetric
= 0;
4762 bgp_static
->igpnexthop
.s_addr
= 0;
4763 bgp_static
->label
= label
;
4764 bgp_static
->prd
= prd
;
4767 if (bgp_static
->rmap
.name
)
4768 XFREE(MTYPE_ROUTE_MAP_NAME
,
4769 bgp_static
->rmap
.name
);
4770 bgp_static
->rmap
.name
=
4771 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4772 bgp_static
->rmap
.map
=
4773 route_map_lookup_by_name(rmap_str
);
4776 if (safi
== SAFI_EVPN
) {
4778 bgp_static
->eth_s_id
=
4780 sizeof(struct eth_segment_id
));
4781 str2esi(esi
, bgp_static
->eth_s_id
);
4784 bgp_static
->router_mac
=
4785 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
4786 prefix_str2mac(routermac
,
4787 bgp_static
->router_mac
);
4790 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4792 rn
->info
= bgp_static
;
4794 bgp_static
->valid
= 1;
4795 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4801 /* Configure static BGP network. */
4802 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4803 const char *ip_str
, const char *rd_str
,
4804 const char *label_str
, int evpn_type
, const char *esi
,
4805 const char *gwip
, const char *ethtag
)
4807 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4810 struct prefix_rd prd
;
4811 struct bgp_node
*prn
;
4812 struct bgp_node
*rn
;
4813 struct bgp_table
*table
;
4814 struct bgp_static
*bgp_static
;
4815 mpls_label_t label
= MPLS_INVALID_LABEL
;
4817 /* Convert IP prefix string to struct prefix. */
4818 ret
= str2prefix(ip_str
, &p
);
4820 vty_out(vty
, "%% Malformed prefix\n");
4821 return CMD_WARNING_CONFIG_FAILED
;
4824 if ((afi
== AFI_L2VPN
)
4825 && (bgp_build_evpn_prefix(evpn_type
,
4826 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4827 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4828 return CMD_WARNING_CONFIG_FAILED
;
4830 ret
= str2prefix_rd(rd_str
, &prd
);
4832 vty_out(vty
, "%% Malformed rd\n");
4833 return CMD_WARNING_CONFIG_FAILED
;
4837 unsigned long label_val
;
4838 label_val
= strtoul(label_str
, NULL
, 10);
4839 encode_label(label_val
, &label
);
4842 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4843 if (prn
->info
== NULL
)
4844 prn
->info
= bgp_table_init(afi
, safi
);
4846 bgp_unlock_node(prn
);
4849 rn
= bgp_node_lookup(table
, &p
);
4852 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4854 bgp_static
= rn
->info
;
4855 bgp_static_free(bgp_static
);
4857 bgp_unlock_node(rn
);
4858 bgp_unlock_node(rn
);
4860 vty_out(vty
, "%% Can't find the route\n");
4865 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4866 const char *rmap_name
)
4868 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4869 struct bgp_rmap
*rmap
;
4871 rmap
= &bgp
->table_map
[afi
][safi
];
4874 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4875 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4876 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4879 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4884 if (bgp_fibupd_safi(safi
))
4885 bgp_zebra_announce_table(bgp
, afi
, safi
);
4890 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
4891 const char *rmap_name
)
4893 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4894 struct bgp_rmap
*rmap
;
4896 rmap
= &bgp
->table_map
[afi
][safi
];
4898 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4902 if (bgp_fibupd_safi(safi
))
4903 bgp_zebra_announce_table(bgp
, afi
, safi
);
4908 int bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4909 safi_t safi
, int *write
)
4911 if (bgp
->table_map
[afi
][safi
].name
) {
4912 bgp_config_write_family_header(vty
, afi
, safi
, write
);
4913 vty_out(vty
, " table-map %s\n",
4914 bgp
->table_map
[afi
][safi
].name
);
4920 DEFUN (bgp_table_map
,
4923 "BGP table to RIB route download filter\n"
4924 "Name of the route map\n")
4927 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4928 argv
[idx_word
]->arg
);
4930 DEFUN (no_bgp_table_map
,
4931 no_bgp_table_map_cmd
,
4932 "no table-map WORD",
4934 "BGP table to RIB route download filter\n"
4935 "Name of the route map\n")
4938 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4939 argv
[idx_word
]->arg
);
4944 "network A.B.C.D/M",
4945 "Specify a network to announce via BGP\n"
4948 int idx_ipv4_prefixlen
= 1;
4949 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4950 bgp_node_safi(vty
), NULL
, 0,
4951 BGP_INVALID_LABEL_INDEX
);
4954 DEFUN (bgp_network_route_map
,
4955 bgp_network_route_map_cmd
,
4956 "network A.B.C.D/M route-map WORD",
4957 "Specify a network to announce via BGP\n"
4959 "Route-map to modify the attributes\n"
4960 "Name of the route map\n")
4962 int idx_ipv4_prefixlen
= 1;
4964 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4965 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
4966 BGP_INVALID_LABEL_INDEX
);
4969 DEFUN (bgp_network_backdoor
,
4970 bgp_network_backdoor_cmd
,
4971 "network A.B.C.D/M backdoor",
4972 "Specify a network to announce via BGP\n"
4974 "Specify a BGP backdoor route\n")
4976 int idx_ipv4_prefixlen
= 1;
4977 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4978 SAFI_UNICAST
, NULL
, 1, BGP_INVALID_LABEL_INDEX
);
4981 DEFUN (bgp_network_mask
,
4982 bgp_network_mask_cmd
,
4983 "network A.B.C.D mask A.B.C.D",
4984 "Specify a network to announce via BGP\n"
4992 char prefix_str
[BUFSIZ
];
4994 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
4997 vty_out(vty
, "%% Inconsistent address and mask\n");
4998 return CMD_WARNING_CONFIG_FAILED
;
5001 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5002 0, BGP_INVALID_LABEL_INDEX
);
5005 DEFUN (bgp_network_mask_route_map
,
5006 bgp_network_mask_route_map_cmd
,
5007 "network A.B.C.D mask A.B.C.D route-map WORD",
5008 "Specify a network to announce via BGP\n"
5012 "Route-map to modify the attributes\n"
5013 "Name of the route map\n")
5019 char prefix_str
[BUFSIZ
];
5021 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5024 vty_out(vty
, "%% Inconsistent address and mask\n");
5025 return CMD_WARNING_CONFIG_FAILED
;
5028 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5029 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5032 DEFUN (bgp_network_mask_backdoor
,
5033 bgp_network_mask_backdoor_cmd
,
5034 "network A.B.C.D mask A.B.C.D backdoor",
5035 "Specify a network to announce via BGP\n"
5039 "Specify a BGP backdoor route\n")
5044 char prefix_str
[BUFSIZ
];
5046 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5049 vty_out(vty
, "%% Inconsistent address and mask\n");
5050 return CMD_WARNING_CONFIG_FAILED
;
5053 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5054 BGP_INVALID_LABEL_INDEX
);
5057 DEFUN (bgp_network_mask_natural
,
5058 bgp_network_mask_natural_cmd
,
5060 "Specify a network to announce via BGP\n"
5065 char prefix_str
[BUFSIZ
];
5067 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5069 vty_out(vty
, "%% Inconsistent address and mask\n");
5070 return CMD_WARNING_CONFIG_FAILED
;
5073 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5074 0, BGP_INVALID_LABEL_INDEX
);
5077 DEFUN (bgp_network_mask_natural_route_map
,
5078 bgp_network_mask_natural_route_map_cmd
,
5079 "network A.B.C.D route-map WORD",
5080 "Specify a network to announce via BGP\n"
5082 "Route-map to modify the attributes\n"
5083 "Name of the route map\n")
5088 char prefix_str
[BUFSIZ
];
5090 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5092 vty_out(vty
, "%% Inconsistent address and mask\n");
5093 return CMD_WARNING_CONFIG_FAILED
;
5096 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5097 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5100 DEFUN (bgp_network_mask_natural_backdoor
,
5101 bgp_network_mask_natural_backdoor_cmd
,
5102 "network A.B.C.D backdoor",
5103 "Specify a network to announce via BGP\n"
5105 "Specify a BGP backdoor route\n")
5109 char prefix_str
[BUFSIZ
];
5111 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5113 vty_out(vty
, "%% Inconsistent address and mask\n");
5114 return CMD_WARNING_CONFIG_FAILED
;
5117 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5118 BGP_INVALID_LABEL_INDEX
);
5121 DEFUN (bgp_network_label_index
,
5122 bgp_network_label_index_cmd
,
5123 "network A.B.C.D/M label-index (0-1048560)",
5124 "Specify a network to announce via BGP\n"
5125 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5126 "Label index to associate with the prefix\n"
5127 "Label index value\n")
5129 u_int32_t label_index
;
5131 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5132 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5133 NULL
, 0, label_index
);
5136 DEFUN (bgp_network_label_index_route_map
,
5137 bgp_network_label_index_route_map_cmd
,
5138 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
5139 "Specify a network to announce via BGP\n"
5141 "Label index to associate with the prefix\n"
5142 "Label index value\n"
5143 "Route-map to modify the attributes\n"
5144 "Name of the route map\n")
5146 u_int32_t label_index
;
5148 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5149 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5150 argv
[5]->arg
, 0, label_index
);
5153 DEFUN (no_bgp_network
,
5155 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
5157 "Specify a network to announce via BGP\n"
5159 "Specify a BGP backdoor route\n"
5160 "Route-map to modify the attributes\n"
5161 "Name of the route map\n")
5163 int idx_ipv4_prefixlen
= 2;
5164 return bgp_static_unset(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5165 bgp_node_safi(vty
));
5168 DEFUN (no_bgp_network_mask
,
5169 no_bgp_network_mask_cmd
,
5170 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
5172 "Specify a network to announce via BGP\n"
5176 "Specify a BGP backdoor route\n"
5177 "Route-map to modify the attributes\n"
5178 "Name of the route map\n")
5183 char prefix_str
[BUFSIZ
];
5185 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5188 vty_out(vty
, "%% Inconsistent address and mask\n");
5189 return CMD_WARNING_CONFIG_FAILED
;
5192 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5195 DEFUN (no_bgp_network_mask_natural
,
5196 no_bgp_network_mask_natural_cmd
,
5197 "no network A.B.C.D [<backdoor|route-map WORD>]",
5199 "Specify a network to announce via BGP\n"
5201 "Specify a BGP backdoor route\n"
5202 "Route-map to modify the attributes\n"
5203 "Name of the route map\n")
5207 char prefix_str
[BUFSIZ
];
5209 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5211 vty_out(vty
, "%% Inconsistent address and mask\n");
5212 return CMD_WARNING_CONFIG_FAILED
;
5215 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5218 ALIAS(no_bgp_network
, no_bgp_network_label_index_cmd
,
5219 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
5220 "Specify a network to announce via BGP\n"
5221 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5222 "Label index to associate with the prefix\n"
5223 "Label index value\n")
5225 ALIAS(no_bgp_network
, no_bgp_network_label_index_route_map_cmd
,
5226 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
5227 "Specify a network to announce via BGP\n"
5229 "Label index to associate with the prefix\n"
5230 "Label index value\n"
5231 "Route-map to modify the attributes\n"
5232 "Name of the route map\n")
5234 DEFUN (ipv6_bgp_network
,
5235 ipv6_bgp_network_cmd
,
5236 "network X:X::X:X/M",
5237 "Specify a network to announce via BGP\n"
5240 int idx_ipv6_prefixlen
= 1;
5241 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5242 bgp_node_safi(vty
), NULL
, 0,
5243 BGP_INVALID_LABEL_INDEX
);
5246 DEFUN (ipv6_bgp_network_route_map
,
5247 ipv6_bgp_network_route_map_cmd
,
5248 "network X:X::X:X/M route-map WORD",
5249 "Specify a network to announce via BGP\n"
5251 "Route-map to modify the attributes\n"
5252 "Name of the route map\n")
5254 int idx_ipv6_prefixlen
= 1;
5256 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5257 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5258 BGP_INVALID_LABEL_INDEX
);
5261 DEFUN (ipv6_bgp_network_label_index
,
5262 ipv6_bgp_network_label_index_cmd
,
5263 "network X:X::X:X/M label-index (0-1048560)",
5264 "Specify a network to announce via BGP\n"
5265 "IPv6 prefix <network>/<length>\n"
5266 "Label index to associate with the prefix\n"
5267 "Label index value\n")
5269 u_int32_t label_index
;
5271 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5272 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5273 NULL
, 0, label_index
);
5276 DEFUN (ipv6_bgp_network_label_index_route_map
,
5277 ipv6_bgp_network_label_index_route_map_cmd
,
5278 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
5279 "Specify a network to announce via BGP\n"
5281 "Label index to associate with the prefix\n"
5282 "Label index value\n"
5283 "Route-map to modify the attributes\n"
5284 "Name of the route map\n")
5286 u_int32_t label_index
;
5288 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5289 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5290 argv
[5]->arg
, 0, label_index
);
5293 DEFUN (no_ipv6_bgp_network
,
5294 no_ipv6_bgp_network_cmd
,
5295 "no network X:X::X:X/M [route-map WORD]",
5297 "Specify a network to announce via BGP\n"
5299 "Route-map to modify the attributes\n"
5300 "Name of the route map\n")
5302 int idx_ipv6_prefixlen
= 2;
5303 return bgp_static_unset(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5304 bgp_node_safi(vty
));
5307 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_cmd
,
5308 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
5309 "Specify a network to announce via BGP\n"
5310 "IPv6 prefix <network>/<length>\n"
5311 "Label index to associate with the prefix\n"
5312 "Label index value\n")
5314 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_route_map_cmd
,
5315 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
5316 "Specify a network to announce via BGP\n"
5318 "Label index to associate with the prefix\n"
5319 "Label index value\n"
5320 "Route-map to modify the attributes\n"
5321 "Name of the route map\n")
5323 /* Aggreagete address:
5325 advertise-map Set condition to advertise attribute
5326 as-set Generate AS set path information
5327 attribute-map Set attributes of aggregate
5328 route-map Set parameters of aggregate
5329 summary-only Filter more specific routes from updates
5330 suppress-map Conditionally filter more specific routes from updates
5333 struct bgp_aggregate
{
5334 /* Summary-only flag. */
5335 u_char summary_only
;
5337 /* AS set generation. */
5340 /* Route-map for aggregated route. */
5341 struct route_map
*map
;
5343 /* Suppress-count. */
5344 unsigned long count
;
5346 /* SAFI configuration. */
5350 static struct bgp_aggregate
*bgp_aggregate_new(void)
5352 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5355 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5357 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5360 /* Update an aggregate as routes are added/removed from the BGP table */
5361 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5362 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5363 struct bgp_info
*del
,
5364 struct bgp_aggregate
*aggregate
)
5366 struct bgp_table
*table
;
5367 struct bgp_node
*top
;
5368 struct bgp_node
*rn
;
5370 struct aspath
*aspath
= NULL
;
5371 struct aspath
*asmerge
= NULL
;
5372 struct community
*community
= NULL
;
5373 struct community
*commerge
= NULL
;
5374 #if defined(AGGREGATE_NEXTHOP_CHECK)
5375 struct in_addr nexthop
;
5378 struct bgp_info
*ri
;
5379 struct bgp_info
*new;
5381 unsigned long match
= 0;
5382 u_char atomic_aggregate
= 0;
5384 /* Record adding route's nexthop and med. */
5386 #if defined(AGGREGATE_NEXTHOP_CHECK)
5387 nexthop
= rinew
->attr
->nexthop
;
5388 med
= rinew
->attr
->med
;
5392 /* ORIGIN attribute: If at least one route among routes that are
5393 aggregated has ORIGIN with the value INCOMPLETE, then the
5394 aggregated route must have the ORIGIN attribute with the value
5395 INCOMPLETE. Otherwise, if at least one route among routes that
5396 are aggregated has ORIGIN with the value EGP, then the aggregated
5397 route must have the origin attribute with the value EGP. In all
5398 other case the value of the ORIGIN attribute of the aggregated
5399 route is INTERNAL. */
5400 origin
= BGP_ORIGIN_IGP
;
5402 table
= bgp
->rib
[afi
][safi
];
5404 top
= bgp_node_get(table
, p
);
5405 for (rn
= bgp_node_get(table
, p
); rn
;
5406 rn
= bgp_route_next_until(rn
, top
))
5407 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5410 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5411 if (BGP_INFO_HOLDDOWN(ri
))
5414 if (del
&& ri
== del
)
5417 if (!rinew
&& first
) {
5418 #if defined(AGGREGATE_NEXTHOP_CHECK)
5419 nexthop
= ri
->attr
->nexthop
;
5420 med
= ri
->attr
->med
;
5425 #ifdef AGGREGATE_NEXTHOP_CHECK
5426 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5428 || ri
->attr
->med
!= med
) {
5430 aspath_free(aspath
);
5432 community_free(community
);
5433 bgp_unlock_node(rn
);
5434 bgp_unlock_node(top
);
5437 #endif /* AGGREGATE_NEXTHOP_CHECK */
5440 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5441 atomic_aggregate
= 1;
5443 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5444 if (aggregate
->summary_only
) {
5445 (bgp_info_extra_get(ri
))
5449 BGP_INFO_ATTR_CHANGED
);
5455 if (origin
< ri
->attr
->origin
)
5456 origin
= ri
->attr
->origin
;
5458 if (aggregate
->as_set
) {
5460 asmerge
= aspath_aggregate(
5463 aspath_free(aspath
);
5466 aspath
= aspath_dup(
5469 if (ri
->attr
->community
) {
5471 commerge
= community_merge(
5473 ri
->attr
->community
);
5474 community
= community_uniq_sort(
5479 community
= community_dup(
5480 ri
->attr
->community
);
5486 bgp_process(bgp
, rn
, afi
, safi
);
5488 bgp_unlock_node(top
);
5493 if (aggregate
->summary_only
)
5494 (bgp_info_extra_get(rinew
))->suppress
++;
5496 if (origin
< rinew
->attr
->origin
)
5497 origin
= rinew
->attr
->origin
;
5499 if (aggregate
->as_set
) {
5501 asmerge
= aspath_aggregate(aspath
,
5502 rinew
->attr
->aspath
);
5503 aspath_free(aspath
);
5506 aspath
= aspath_dup(rinew
->attr
->aspath
);
5508 if (rinew
->attr
->community
) {
5510 commerge
= community_merge(
5512 rinew
->attr
->community
);
5514 community_uniq_sort(commerge
);
5515 community_free(commerge
);
5517 community
= community_dup(
5518 rinew
->attr
->community
);
5523 if (aggregate
->count
> 0) {
5524 rn
= bgp_node_get(table
, p
);
5526 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5527 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5528 community
, aggregate
->as_set
,
5531 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5533 bgp_info_add(rn
, new);
5534 bgp_unlock_node(rn
);
5535 bgp_process(bgp
, rn
, afi
, safi
);
5538 aspath_free(aspath
);
5540 community_free(community
);
5544 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5545 struct bgp_aggregate
*);
5547 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5548 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5550 struct bgp_node
*child
;
5551 struct bgp_node
*rn
;
5552 struct bgp_aggregate
*aggregate
;
5553 struct bgp_table
*table
;
5555 /* MPLS-VPN aggregation is not yet supported. */
5556 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5557 || (safi
== SAFI_EVPN
))
5560 table
= bgp
->aggregate
[afi
][safi
];
5562 /* No aggregates configured. */
5563 if (bgp_table_top_nolock(table
) == NULL
)
5566 if (p
->prefixlen
== 0)
5569 if (BGP_INFO_HOLDDOWN(ri
))
5572 child
= bgp_node_get(table
, p
);
5574 /* Aggregate address configuration check. */
5575 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5576 if ((aggregate
= rn
->info
) != NULL
5577 && rn
->p
.prefixlen
< p
->prefixlen
) {
5578 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5579 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5582 bgp_unlock_node(child
);
5585 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5586 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5588 struct bgp_node
*child
;
5589 struct bgp_node
*rn
;
5590 struct bgp_aggregate
*aggregate
;
5591 struct bgp_table
*table
;
5593 /* MPLS-VPN aggregation is not yet supported. */
5594 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5595 || (safi
== SAFI_EVPN
))
5598 table
= bgp
->aggregate
[afi
][safi
];
5600 /* No aggregates configured. */
5601 if (bgp_table_top_nolock(table
) == NULL
)
5604 if (p
->prefixlen
== 0)
5607 child
= bgp_node_get(table
, p
);
5609 /* Aggregate address configuration check. */
5610 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5611 if ((aggregate
= rn
->info
) != NULL
5612 && rn
->p
.prefixlen
< p
->prefixlen
) {
5613 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5614 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5617 bgp_unlock_node(child
);
5620 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5621 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5622 safi_t safi
, struct bgp_aggregate
*aggregate
)
5624 struct bgp_table
*table
;
5625 struct bgp_node
*top
;
5626 struct bgp_node
*rn
;
5627 struct bgp_info
*new;
5628 struct bgp_info
*ri
;
5629 unsigned long match
;
5630 u_char origin
= BGP_ORIGIN_IGP
;
5631 struct aspath
*aspath
= NULL
;
5632 struct aspath
*asmerge
= NULL
;
5633 struct community
*community
= NULL
;
5634 struct community
*commerge
= NULL
;
5635 u_char atomic_aggregate
= 0;
5637 table
= bgp
->rib
[afi
][safi
];
5640 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5642 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5645 /* If routes exists below this node, generate aggregate routes. */
5646 top
= bgp_node_get(table
, p
);
5647 for (rn
= bgp_node_get(table
, p
); rn
;
5648 rn
= bgp_route_next_until(rn
, top
))
5649 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5652 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5653 if (BGP_INFO_HOLDDOWN(ri
))
5657 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5658 atomic_aggregate
= 1;
5660 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5661 /* summary-only aggregate route suppress
5663 route announcement. */
5664 if (aggregate
->summary_only
) {
5665 (bgp_info_extra_get(ri
))
5669 BGP_INFO_ATTR_CHANGED
);
5673 /* If at least one route among routes
5674 * that are aggregated has
5675 * ORIGIN with the value INCOMPLETE,
5676 * then the aggregated route
5677 * MUST have the ORIGIN attribute with
5678 * the value INCOMPLETE.
5679 * Otherwise, if at least one route
5680 * among routes that are
5681 * aggregated has ORIGIN with the value
5682 * EGP, then the aggregated
5683 * route MUST have the ORIGIN attribute
5684 * with the value EGP.
5686 if (origin
< ri
->attr
->origin
)
5687 origin
= ri
->attr
->origin
;
5689 /* as-set aggregate route generate
5691 community aggregation. */
5692 if (aggregate
->as_set
) {
5694 asmerge
= aspath_aggregate(
5697 aspath_free(aspath
);
5700 aspath
= aspath_dup(
5703 if (ri
->attr
->community
) {
5705 commerge
= community_merge(
5707 ri
->attr
->community
);
5708 community
= community_uniq_sort(
5713 community
= community_dup(
5714 ri
->attr
->community
);
5721 /* If this node is suppressed, process the change. */
5723 bgp_process(bgp
, rn
, afi
, safi
);
5725 bgp_unlock_node(top
);
5727 /* Add aggregate route to BGP table. */
5728 if (aggregate
->count
) {
5729 rn
= bgp_node_get(table
, p
);
5731 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5732 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5733 community
, aggregate
->as_set
,
5736 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5738 bgp_info_add(rn
, new);
5739 bgp_unlock_node(rn
);
5741 /* Process change. */
5742 bgp_process(bgp
, rn
, afi
, safi
);
5745 aspath_free(aspath
);
5747 community_free(community
);
5751 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5752 safi_t safi
, struct bgp_aggregate
*aggregate
)
5754 struct bgp_table
*table
;
5755 struct bgp_node
*top
;
5756 struct bgp_node
*rn
;
5757 struct bgp_info
*ri
;
5758 unsigned long match
;
5760 table
= bgp
->rib
[afi
][safi
];
5762 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5764 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5767 /* If routes exists below this node, generate aggregate routes. */
5768 top
= bgp_node_get(table
, p
);
5769 for (rn
= bgp_node_get(table
, p
); rn
;
5770 rn
= bgp_route_next_until(rn
, top
))
5771 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5774 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5775 if (BGP_INFO_HOLDDOWN(ri
))
5778 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5779 if (aggregate
->summary_only
5781 ri
->extra
->suppress
--;
5783 if (ri
->extra
->suppress
== 0) {
5786 BGP_INFO_ATTR_CHANGED
);
5794 /* If this node was suppressed, process the change. */
5796 bgp_process(bgp
, rn
, afi
, safi
);
5798 bgp_unlock_node(top
);
5800 /* Delete aggregate route from BGP table. */
5801 rn
= bgp_node_get(table
, p
);
5803 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5804 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5805 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5808 /* Withdraw static BGP route from routing table. */
5810 bgp_info_delete(rn
, ri
);
5811 bgp_process(bgp
, rn
, afi
, safi
);
5814 /* Unlock bgp_node_lookup. */
5815 bgp_unlock_node(rn
);
5818 /* Aggregate route attribute. */
5819 #define AGGREGATE_SUMMARY_ONLY 1
5820 #define AGGREGATE_AS_SET 1
5822 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5823 afi_t afi
, safi_t safi
)
5825 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5828 struct bgp_node
*rn
;
5829 struct bgp_aggregate
*aggregate
;
5831 /* Convert string to prefix structure. */
5832 ret
= str2prefix(prefix_str
, &p
);
5834 vty_out(vty
, "Malformed prefix\n");
5835 return CMD_WARNING_CONFIG_FAILED
;
5839 /* Old configuration check. */
5840 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5843 "%% There is no aggregate-address configuration.\n");
5844 return CMD_WARNING_CONFIG_FAILED
;
5847 aggregate
= rn
->info
;
5848 if (aggregate
->safi
== SAFI_UNICAST
)
5849 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5850 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5851 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5853 if (aggregate
->safi
== SAFI_MULTICAST
)
5854 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5856 /* Unlock aggregate address configuration. */
5858 bgp_aggregate_free(aggregate
);
5859 bgp_unlock_node(rn
);
5860 bgp_unlock_node(rn
);
5865 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5866 safi_t safi
, u_char summary_only
, u_char as_set
)
5868 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5871 struct bgp_node
*rn
;
5872 struct bgp_aggregate
*aggregate
;
5874 /* Convert string to prefix structure. */
5875 ret
= str2prefix(prefix_str
, &p
);
5877 vty_out(vty
, "Malformed prefix\n");
5878 return CMD_WARNING_CONFIG_FAILED
;
5882 /* Old configuration check. */
5883 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5886 vty_out(vty
, "There is already same aggregate network.\n");
5887 /* try to remove the old entry */
5888 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5890 vty_out(vty
, "Error deleting aggregate.\n");
5891 bgp_unlock_node(rn
);
5892 return CMD_WARNING_CONFIG_FAILED
;
5896 /* Make aggregate address structure. */
5897 aggregate
= bgp_aggregate_new();
5898 aggregate
->summary_only
= summary_only
;
5899 aggregate
->as_set
= as_set
;
5900 aggregate
->safi
= safi
;
5901 rn
->info
= aggregate
;
5903 /* Aggregate address insert into BGP routing table. */
5904 if (safi
== SAFI_UNICAST
)
5905 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5906 if (safi
== SAFI_LABELED_UNICAST
)
5907 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5909 if (safi
== SAFI_MULTICAST
)
5910 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5915 DEFUN (aggregate_address
,
5916 aggregate_address_cmd
,
5917 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5918 "Configure BGP aggregate entries\n"
5919 "Aggregate prefix\n"
5920 "Generate AS set path information\n"
5921 "Filter more specific routes from updates\n"
5922 "Filter more specific routes from updates\n"
5923 "Generate AS set path information\n")
5926 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5927 char *prefix
= argv
[idx
]->arg
;
5929 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5931 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5932 ? AGGREGATE_SUMMARY_ONLY
5935 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5936 summary_only
, as_set
);
5939 DEFUN (aggregate_address_mask
,
5940 aggregate_address_mask_cmd
,
5941 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5942 "Configure BGP aggregate entries\n"
5943 "Aggregate address\n"
5945 "Generate AS set path information\n"
5946 "Filter more specific routes from updates\n"
5947 "Filter more specific routes from updates\n"
5948 "Generate AS set path information\n")
5951 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5952 char *prefix
= argv
[idx
]->arg
;
5953 char *mask
= argv
[idx
+ 1]->arg
;
5955 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5957 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5958 ? AGGREGATE_SUMMARY_ONLY
5961 char prefix_str
[BUFSIZ
];
5962 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5965 vty_out(vty
, "%% Inconsistent address and mask\n");
5966 return CMD_WARNING_CONFIG_FAILED
;
5969 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5970 summary_only
, as_set
);
5973 DEFUN (no_aggregate_address
,
5974 no_aggregate_address_cmd
,
5975 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5977 "Configure BGP aggregate entries\n"
5978 "Aggregate prefix\n"
5979 "Generate AS set path information\n"
5980 "Filter more specific routes from updates\n"
5981 "Filter more specific routes from updates\n"
5982 "Generate AS set path information\n")
5985 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5986 char *prefix
= argv
[idx
]->arg
;
5987 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5990 DEFUN (no_aggregate_address_mask
,
5991 no_aggregate_address_mask_cmd
,
5992 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5994 "Configure BGP aggregate entries\n"
5995 "Aggregate address\n"
5997 "Generate AS set path information\n"
5998 "Filter more specific routes from updates\n"
5999 "Filter more specific routes from updates\n"
6000 "Generate AS set path information\n")
6003 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6004 char *prefix
= argv
[idx
]->arg
;
6005 char *mask
= argv
[idx
+ 1]->arg
;
6007 char prefix_str
[BUFSIZ
];
6008 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6011 vty_out(vty
, "%% Inconsistent address and mask\n");
6012 return CMD_WARNING_CONFIG_FAILED
;
6015 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6018 DEFUN (ipv6_aggregate_address
,
6019 ipv6_aggregate_address_cmd
,
6020 "aggregate-address X:X::X:X/M [summary-only]",
6021 "Configure BGP aggregate entries\n"
6022 "Aggregate prefix\n"
6023 "Filter more specific routes from updates\n")
6026 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6027 char *prefix
= argv
[idx
]->arg
;
6028 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6029 ? AGGREGATE_SUMMARY_ONLY
6031 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6035 DEFUN (no_ipv6_aggregate_address
,
6036 no_ipv6_aggregate_address_cmd
,
6037 "no aggregate-address X:X::X:X/M [summary-only]",
6039 "Configure BGP aggregate entries\n"
6040 "Aggregate prefix\n"
6041 "Filter more specific routes from updates\n")
6044 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6045 char *prefix
= argv
[idx
]->arg
;
6046 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6049 /* Redistribute route treatment. */
6050 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6051 const struct in_addr
*nexthop
,
6052 const struct in6_addr
*nexthop6
, unsigned int ifindex
,
6053 u_int32_t metric
, u_char type
, u_short instance
,
6056 struct bgp_info
*new;
6057 struct bgp_info
*bi
;
6058 struct bgp_info info
;
6059 struct bgp_node
*bn
;
6061 struct attr
*new_attr
;
6064 struct bgp_redist
*red
;
6066 /* Make default attribute. */
6067 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6069 attr
.nexthop
= *nexthop
;
6070 attr
.nh_ifindex
= ifindex
;
6073 attr
.mp_nexthop_global
= *nexthop6
;
6074 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6078 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6081 afi
= family2afi(p
->family
);
6083 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6085 struct attr attr_new
;
6087 /* Copy attribute for modification. */
6088 bgp_attr_dup(&attr_new
, &attr
);
6090 if (red
->redist_metric_flag
)
6091 attr_new
.med
= red
->redist_metric
;
6093 /* Apply route-map. */
6094 if (red
->rmap
.name
) {
6095 info
.peer
= bgp
->peer_self
;
6096 info
.attr
= &attr_new
;
6098 SET_FLAG(bgp
->peer_self
->rmap_type
,
6099 PEER_RMAP_TYPE_REDISTRIBUTE
);
6101 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6104 bgp
->peer_self
->rmap_type
= 0;
6106 if (ret
== RMAP_DENYMATCH
) {
6107 /* Free uninterned attribute. */
6108 bgp_attr_flush(&attr_new
);
6110 /* Unintern original. */
6111 aspath_unintern(&attr
.aspath
);
6112 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6117 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6118 SAFI_UNICAST
, p
, NULL
);
6120 new_attr
= bgp_attr_intern(&attr_new
);
6122 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6123 if (bi
->peer
== bgp
->peer_self
6124 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6128 /* Ensure the (source route) type is updated. */
6130 if (attrhash_cmp(bi
->attr
, new_attr
)
6131 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6132 bgp_attr_unintern(&new_attr
);
6133 aspath_unintern(&attr
.aspath
);
6134 bgp_unlock_node(bn
);
6137 /* The attribute is changed. */
6138 bgp_info_set_flag(bn
, bi
,
6139 BGP_INFO_ATTR_CHANGED
);
6141 /* Rewrite BGP route information. */
6142 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6143 bgp_info_restore(bn
, bi
);
6145 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6147 bgp_attr_unintern(&bi
->attr
);
6148 bi
->attr
= new_attr
;
6149 bi
->uptime
= bgp_clock();
6151 /* Process change. */
6152 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6154 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6155 bgp_unlock_node(bn
);
6156 aspath_unintern(&attr
.aspath
);
6161 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6162 bgp
->peer_self
, new_attr
, bn
);
6163 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6165 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6166 bgp_info_add(bn
, new);
6167 bgp_unlock_node(bn
);
6168 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6171 /* Unintern original. */
6172 aspath_unintern(&attr
.aspath
);
6175 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6179 struct bgp_node
*rn
;
6180 struct bgp_info
*ri
;
6181 struct bgp_redist
*red
;
6183 afi
= family2afi(p
->family
);
6185 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6187 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6188 SAFI_UNICAST
, p
, NULL
);
6190 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6191 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6195 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6196 bgp_info_delete(rn
, ri
);
6197 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6199 bgp_unlock_node(rn
);
6203 /* Withdraw specified route type's route. */
6204 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6207 struct bgp_node
*rn
;
6208 struct bgp_info
*ri
;
6209 struct bgp_table
*table
;
6211 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6213 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6214 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6215 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6216 && ri
->instance
== instance
)
6220 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6222 bgp_info_delete(rn
, ri
);
6223 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6228 /* Static function to display route. */
6229 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
)
6232 u_int32_t destination
;
6235 if (p
->family
== AF_INET
) {
6236 len
= vty_out(vty
, "%s",
6237 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
));
6238 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6240 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6241 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6242 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6243 || p
->u
.prefix4
.s_addr
== 0) {
6244 /* When mask is natural, mask is not displayed. */
6246 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6247 } else if (p
->family
== AF_ETHERNET
) {
6248 prefix2str(p
, buf
, PREFIX_STRLEN
);
6249 len
= vty_out(vty
, "%s", buf
);
6250 } else if (p
->family
== AF_EVPN
) {
6251 #if defined(HAVE_CUMULUS)
6252 len
= vty_out(vty
, "%s",
6253 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6256 prefix2str(p
, buf
, PREFIX_STRLEN
);
6257 len
= vty_out(vty
, "%s", buf
);
6260 len
= vty_out(vty
, "%s/%d",
6261 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6266 vty_out(vty
, "\n%*s", 20, " ");
6268 vty_out(vty
, "%*s", len
, " ");
6271 enum bgp_display_type
{
6275 /* Print the short form route status for a bgp_info */
6276 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6277 json_object
*json_path
)
6281 /* Route status display. */
6282 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6283 json_object_boolean_true_add(json_path
, "removed");
6285 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6286 json_object_boolean_true_add(json_path
, "stale");
6288 if (binfo
->extra
&& binfo
->extra
->suppress
)
6289 json_object_boolean_true_add(json_path
, "suppressed");
6291 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6292 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6293 json_object_boolean_true_add(json_path
, "valid");
6296 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6297 json_object_boolean_true_add(json_path
, "history");
6299 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6300 json_object_boolean_true_add(json_path
, "damped");
6302 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6303 json_object_boolean_true_add(json_path
, "bestpath");
6305 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6306 json_object_boolean_true_add(json_path
, "multipath");
6308 /* Internal route. */
6309 if ((binfo
->peer
->as
)
6310 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6311 json_object_string_add(json_path
, "pathFrom",
6314 json_object_string_add(json_path
, "pathFrom",
6320 /* Route status display. */
6321 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6323 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6325 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6327 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6328 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6334 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6336 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6338 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6340 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6345 /* Internal route. */
6346 if (binfo
->peer
&& (binfo
->peer
->as
)
6347 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6353 /* called from terminal list command */
6354 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6355 int display
, safi_t safi
, json_object
*json_paths
)
6358 json_object
*json_path
= NULL
;
6359 json_object
*json_nexthops
= NULL
;
6360 json_object
*json_nexthop_global
= NULL
;
6361 json_object
*json_nexthop_ll
= NULL
;
6364 json_path
= json_object_new_object();
6366 /* short status lead text */
6367 route_vty_short_status_out(vty
, binfo
, json_path
);
6370 /* print prefix and mask */
6372 route_vty_out_route(p
, vty
);
6374 vty_out(vty
, "%*s", 17, " ");
6377 /* Print attribute */
6381 * For ENCAP and EVPN routes, nexthop address family is not
6382 * neccessarily the same as the prefix address family.
6383 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6384 * EVPN routes are also exchanged with a MP nexthop. Currently,
6386 * is only IPv4, the value will be present in either
6388 * attr->mp_nexthop_global_in
6390 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6392 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6398 &attr
->mp_nexthop_global_in
,
6403 inet_ntop(af
, &attr
->mp_nexthop_global
,
6410 } else if (safi
== SAFI_EVPN
) {
6412 json_nexthop_global
= json_object_new_object();
6414 json_object_string_add(
6415 json_nexthop_global
, "ip",
6416 inet_ntoa(attr
->nexthop
));
6417 json_object_string_add(json_nexthop_global
,
6419 json_object_boolean_true_add(
6420 json_nexthop_global
, "used");
6422 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6425 else if (p
->family
== AF_INET
6426 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6428 json_nexthop_global
= json_object_new_object();
6430 if ((safi
== SAFI_MPLS_VPN
)
6431 || (safi
== SAFI_EVPN
))
6432 json_object_string_add(
6433 json_nexthop_global
, "ip",
6435 attr
->mp_nexthop_global_in
));
6437 json_object_string_add(
6438 json_nexthop_global
, "ip",
6439 inet_ntoa(attr
->nexthop
));
6441 json_object_string_add(json_nexthop_global
,
6443 json_object_boolean_true_add(
6444 json_nexthop_global
, "used");
6446 if ((safi
== SAFI_MPLS_VPN
)
6447 || (safi
== SAFI_EVPN
))
6448 vty_out(vty
, "%-16s",
6450 attr
->mp_nexthop_global_in
));
6452 vty_out(vty
, "%-16s",
6453 inet_ntoa(attr
->nexthop
));
6458 else if (p
->family
== AF_INET6
6459 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6464 json_nexthop_global
= json_object_new_object();
6465 json_object_string_add(
6466 json_nexthop_global
, "ip",
6468 &attr
->mp_nexthop_global
, buf
,
6470 json_object_string_add(json_nexthop_global
,
6472 json_object_string_add(json_nexthop_global
,
6475 /* We display both LL & GL if both have been
6477 if ((attr
->mp_nexthop_len
== 32)
6478 || (binfo
->peer
->conf_if
)) {
6480 json_object_new_object();
6481 json_object_string_add(
6482 json_nexthop_ll
, "ip",
6485 &attr
->mp_nexthop_local
,
6487 json_object_string_add(json_nexthop_ll
,
6489 json_object_string_add(json_nexthop_ll
,
6494 &attr
->mp_nexthop_global
,
6495 &attr
->mp_nexthop_local
)
6497 && !attr
->mp_nexthop_prefer_global
)
6498 json_object_boolean_true_add(
6502 json_object_boolean_true_add(
6503 json_nexthop_global
,
6506 json_object_boolean_true_add(
6507 json_nexthop_global
, "used");
6509 /* Display LL if LL/Global both in table unless
6510 * prefer-global is set */
6511 if (((attr
->mp_nexthop_len
== 32)
6512 && !attr
->mp_nexthop_prefer_global
)
6513 || (binfo
->peer
->conf_if
)) {
6514 if (binfo
->peer
->conf_if
) {
6517 binfo
->peer
->conf_if
);
6518 len
= 16 - len
; /* len of IPv6
6524 vty_out(vty
, "\n%*s",
6527 vty_out(vty
, "%*s", len
,
6534 &attr
->mp_nexthop_local
,
6539 vty_out(vty
, "\n%*s",
6542 vty_out(vty
, "%*s", len
,
6550 &attr
->mp_nexthop_global
,
6555 vty_out(vty
, "\n%*s", 36, " ");
6557 vty_out(vty
, "%*s", len
, " ");
6563 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6565 json_object_int_add(json_path
, "med",
6568 vty_out(vty
, "%10u", attr
->med
);
6569 else if (!json_paths
)
6573 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6575 json_object_int_add(json_path
, "localpref",
6578 vty_out(vty
, "%7u", attr
->local_pref
);
6579 else if (!json_paths
)
6583 json_object_int_add(json_path
, "weight", attr
->weight
);
6585 vty_out(vty
, "%7u ", attr
->weight
);
6589 json_object_string_add(json_path
, "peerId",
6590 sockunion2str(&binfo
->peer
->su
,
6598 json_object_string_add(json_path
, "aspath",
6601 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6606 json_object_string_add(
6607 json_path
, "origin",
6608 bgp_origin_long_str
[attr
->origin
]);
6610 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6613 json_object_string_add(json_path
, "alert",
6616 vty_out(vty
, "No attributes to print\n");
6620 if (json_nexthop_global
|| json_nexthop_ll
) {
6621 json_nexthops
= json_object_new_array();
6623 if (json_nexthop_global
)
6624 json_object_array_add(json_nexthops
,
6625 json_nexthop_global
);
6627 if (json_nexthop_ll
)
6628 json_object_array_add(json_nexthops
,
6631 json_object_object_add(json_path
, "nexthops",
6635 json_object_array_add(json_paths
, json_path
);
6639 /* prints an additional line, indented, with VNC info, if
6641 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6642 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6647 /* called from terminal list command */
6648 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6649 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6651 json_object
*json_status
= NULL
;
6652 json_object
*json_net
= NULL
;
6654 /* Route status display. */
6656 json_status
= json_object_new_object();
6657 json_net
= json_object_new_object();
6664 /* print prefix and mask */
6666 json_object_string_add(
6667 json_net
, "addrPrefix",
6668 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6670 route_vty_out_route(p
, vty
);
6672 /* Print attribute */
6675 if (p
->family
== AF_INET
6676 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6677 || safi
== SAFI_EVPN
6678 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6679 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6680 || safi
== SAFI_EVPN
)
6681 json_object_string_add(
6682 json_net
, "nextHop",
6684 attr
->mp_nexthop_global_in
));
6686 json_object_string_add(
6687 json_net
, "nextHop",
6688 inet_ntoa(attr
->nexthop
));
6689 } else if (p
->family
== AF_INET6
6690 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6693 json_object_string_add(
6694 json_net
, "netHopGloabal",
6696 &attr
->mp_nexthop_global
, buf
,
6701 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6702 json_object_int_add(json_net
, "metric",
6705 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6706 json_object_int_add(json_net
, "localPref",
6709 json_object_int_add(json_net
, "weight", attr
->weight
);
6713 json_object_string_add(json_net
, "asPath",
6717 json_object_string_add(json_net
, "bgpOriginCode",
6718 bgp_origin_str
[attr
->origin
]);
6720 if (p
->family
== AF_INET
6721 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6722 || safi
== SAFI_EVPN
6723 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6724 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6725 || safi
== SAFI_EVPN
)
6726 vty_out(vty
, "%-16s",
6728 attr
->mp_nexthop_global_in
));
6730 vty_out(vty
, "%-16s",
6731 inet_ntoa(attr
->nexthop
));
6732 } else if (p
->family
== AF_INET6
6733 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6740 &attr
->mp_nexthop_global
, buf
,
6744 vty_out(vty
, "\n%*s", 36, " ");
6746 vty_out(vty
, "%*s", len
, " ");
6749 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6750 vty_out(vty
, "%10u", attr
->med
);
6754 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6755 vty_out(vty
, "%7u", attr
->local_pref
);
6759 vty_out(vty
, "%7u ", attr
->weight
);
6763 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6766 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6770 json_object_boolean_true_add(json_status
, "*");
6771 json_object_boolean_true_add(json_status
, ">");
6772 json_object_object_add(json_net
, "appliedStatusSymbols",
6774 char buf_cut
[BUFSIZ
];
6775 json_object_object_add(
6777 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6783 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6784 struct bgp_info
*binfo
, int display
, safi_t safi
,
6787 json_object
*json_out
= NULL
;
6789 mpls_label_t label
= MPLS_INVALID_LABEL
;
6795 json_out
= json_object_new_object();
6797 /* short status lead text */
6798 route_vty_short_status_out(vty
, binfo
, json_out
);
6800 /* print prefix and mask */
6803 route_vty_out_route(p
, vty
);
6805 vty_out(vty
, "%*s", 17, " ");
6808 /* Print attribute */
6811 if (((p
->family
== AF_INET
)
6812 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6813 || (safi
== SAFI_EVPN
6814 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6815 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6816 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6817 || safi
== SAFI_EVPN
) {
6819 json_object_string_add(
6820 json_out
, "mpNexthopGlobalIn",
6822 attr
->mp_nexthop_global_in
));
6824 vty_out(vty
, "%-16s",
6826 attr
->mp_nexthop_global_in
));
6829 json_object_string_add(
6830 json_out
, "nexthop",
6831 inet_ntoa(attr
->nexthop
));
6833 vty_out(vty
, "%-16s",
6834 inet_ntoa(attr
->nexthop
));
6836 } else if (((p
->family
== AF_INET6
)
6837 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6838 || (safi
== SAFI_EVPN
6839 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6840 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6844 if (attr
->mp_nexthop_len
6845 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6847 json_object_string_add(
6848 json_out
, "mpNexthopGlobalIn",
6851 &attr
->mp_nexthop_global
,
6857 &attr
->mp_nexthop_global
,
6859 } else if (attr
->mp_nexthop_len
6860 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6863 &attr
->mp_nexthop_global
,
6866 &attr
->mp_nexthop_local
,
6868 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6869 json_object_string_add(
6871 "mpNexthopGlobalLocal", buf_c
);
6873 vty_out(vty
, "%s(%s)",
6876 &attr
->mp_nexthop_global
,
6880 &attr
->mp_nexthop_local
,
6886 label
= decode_label(&binfo
->extra
->label
);
6888 if (bgp_is_valid_label(&label
)) {
6890 json_object_int_add(json_out
, "notag", label
);
6891 json_object_array_add(json
, json_out
);
6893 vty_out(vty
, "notag/%d", label
);
6899 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6900 struct bgp_info
*binfo
, int display
,
6901 json_object
*json_paths
)
6905 json_object
*json_path
= NULL
;
6908 json_path
= json_object_new_object();
6913 /* short status lead text */
6914 route_vty_short_status_out(vty
, binfo
, json_path
);
6916 /* print prefix and mask */
6918 route_vty_out_route(p
, vty
);
6920 vty_out(vty
, "%*s", 17, " ");
6922 /* Print attribute */
6926 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6930 vty_out(vty
, "%-16s",
6931 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6935 vty_out(vty
, "%s(%s)",
6936 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6938 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
6946 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
6947 char *str
= esi2str(id
);
6948 vty_out(vty
, "%s", str
);
6949 XFREE(MTYPE_TMP
, str
);
6950 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
6951 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
6952 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
6954 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
6957 if (attr
->ecommunity
) {
6959 struct ecommunity_val
*routermac
= ecommunity_lookup(
6960 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
6961 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
6963 mac
= ecom_mac2str((char *)routermac
->val
);
6965 vty_out(vty
, "/%s", (char *)mac
);
6966 XFREE(MTYPE_TMP
, mac
);
6972 /* dampening route */
6973 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6974 struct bgp_info
*binfo
, int display
, safi_t safi
,
6975 u_char use_json
, json_object
*json
)
6979 char timebuf
[BGP_UPTIME_LEN
];
6981 /* short status lead text */
6982 route_vty_short_status_out(vty
, binfo
, json
);
6984 /* print prefix and mask */
6987 route_vty_out_route(p
, vty
);
6989 vty_out(vty
, "%*s", 17, " ");
6992 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6996 vty_out(vty
, "\n%*s", 34, " ");
6999 json_object_int_add(json
, "peerHost", len
);
7001 vty_out(vty
, "%*s", len
, " ");
7005 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7008 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7012 /* Print attribute */
7018 json_object_string_add(json
, "asPath",
7021 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7026 json_object_string_add(json
, "origin",
7027 bgp_origin_str
[attr
->origin
]);
7029 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7036 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7037 struct bgp_info
*binfo
, int display
, safi_t safi
,
7038 u_char use_json
, json_object
*json
)
7041 struct bgp_damp_info
*bdi
;
7042 char timebuf
[BGP_UPTIME_LEN
];
7048 bdi
= binfo
->extra
->damp_info
;
7050 /* short status lead text */
7051 route_vty_short_status_out(vty
, binfo
, json
);
7053 /* print prefix and mask */
7056 route_vty_out_route(p
, vty
);
7058 vty_out(vty
, "%*s", 17, " ");
7061 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7065 vty_out(vty
, "\n%*s", 33, " ");
7068 json_object_int_add(json
, "peerHost", len
);
7070 vty_out(vty
, "%*s", len
, " ");
7073 len
= vty_out(vty
, "%d", bdi
->flap
);
7080 json_object_int_add(json
, "bdiFlap", len
);
7082 vty_out(vty
, "%*s", len
, " ");
7086 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7089 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7090 BGP_UPTIME_LEN
, 0, NULL
));
7092 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7093 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7095 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7096 BGP_UPTIME_LEN
, use_json
, json
);
7099 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7104 vty_out(vty
, "%*s ", 8, " ");
7107 /* Print attribute */
7113 json_object_string_add(json
, "asPath",
7116 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7121 json_object_string_add(json
, "origin",
7122 bgp_origin_str
[attr
->origin
]);
7124 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7130 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7131 int *first
, const char *header
,
7132 json_object
*json_adv_to
)
7134 char buf1
[INET6_ADDRSTRLEN
];
7135 json_object
*json_peer
= NULL
;
7138 /* 'advertised-to' is a dictionary of peers we have advertised
7140 * prefix too. The key is the peer's IP or swpX, the value is
7142 * hostname if we know it and "" if not.
7144 json_peer
= json_object_new_object();
7147 json_object_string_add(json_peer
, "hostname",
7151 json_object_object_add(json_adv_to
, peer
->conf_if
,
7154 json_object_object_add(
7156 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7160 vty_out(vty
, "%s", header
);
7165 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7167 vty_out(vty
, " %s(%s)", peer
->hostname
,
7170 vty_out(vty
, " %s(%s)", peer
->hostname
,
7171 sockunion2str(&peer
->su
, buf1
,
7175 vty_out(vty
, " %s", peer
->conf_if
);
7178 sockunion2str(&peer
->su
, buf1
,
7184 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7185 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7186 json_object
*json_paths
)
7188 char buf
[INET6_ADDRSTRLEN
];
7190 #if defined(HAVE_CUMULUS)
7191 char buf2
[EVPN_ROUTE_STRLEN
];
7194 int sockunion_vty_out(struct vty
*, union sockunion
*);
7196 json_object
*json_bestpath
= NULL
;
7197 json_object
*json_cluster_list
= NULL
;
7198 json_object
*json_cluster_list_list
= NULL
;
7199 json_object
*json_ext_community
= NULL
;
7200 json_object
*json_last_update
= NULL
;
7201 json_object
*json_nexthop_global
= NULL
;
7202 json_object
*json_nexthop_ll
= NULL
;
7203 json_object
*json_nexthops
= NULL
;
7204 json_object
*json_path
= NULL
;
7205 json_object
*json_peer
= NULL
;
7206 json_object
*json_string
= NULL
;
7207 json_object
*json_adv_to
= NULL
;
7209 struct listnode
*node
, *nnode
;
7211 int addpath_capable
;
7213 unsigned int first_as
;
7216 json_path
= json_object_new_object();
7217 json_peer
= json_object_new_object();
7218 json_nexthop_global
= json_object_new_object();
7221 #if defined(HAVE_CUMULUS)
7222 if (!json_paths
&& safi
== SAFI_EVPN
) {
7225 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7226 vty_out(vty
, " Route %s", buf2
);
7229 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7231 vty_out(vty
, " VNI %s", tag_buf
);
7234 if (binfo
->extra
&& binfo
->extra
->parent
) {
7235 struct bgp_info
*parent_ri
;
7236 struct bgp_node
*rn
, *prn
;
7238 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7239 rn
= parent_ri
->net
;
7240 if (rn
&& rn
->prn
) {
7242 vty_out(vty
, " Imported from %s:%s\n",
7244 (struct prefix_rd
*)&prn
->p
,
7245 buf1
, RD_ADDRSTRLEN
),
7255 /* Line1 display AS-path, Aggregator */
7258 json_object_lock(attr
->aspath
->json
);
7259 json_object_object_add(json_path
, "aspath",
7260 attr
->aspath
->json
);
7262 if (attr
->aspath
->segments
)
7263 aspath_print_vty(vty
, " %s",
7266 vty_out(vty
, " Local");
7270 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7272 json_object_boolean_true_add(json_path
,
7275 vty_out(vty
, ", (removed)");
7278 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7280 json_object_boolean_true_add(json_path
,
7283 vty_out(vty
, ", (stale)");
7286 if (CHECK_FLAG(attr
->flag
,
7287 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7289 json_object_int_add(json_path
, "aggregatorAs",
7290 attr
->aggregator_as
);
7291 json_object_string_add(
7292 json_path
, "aggregatorId",
7293 inet_ntoa(attr
->aggregator_addr
));
7295 vty_out(vty
, ", (aggregated by %u %s)",
7296 attr
->aggregator_as
,
7297 inet_ntoa(attr
->aggregator_addr
));
7301 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7302 PEER_FLAG_REFLECTOR_CLIENT
)) {
7304 json_object_boolean_true_add(
7305 json_path
, "rxedFromRrClient");
7307 vty_out(vty
, ", (Received from a RR-client)");
7310 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7311 PEER_FLAG_RSERVER_CLIENT
)) {
7313 json_object_boolean_true_add(
7314 json_path
, "rxedFromRsClient");
7316 vty_out(vty
, ", (Received from a RS-client)");
7319 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7321 json_object_boolean_true_add(
7322 json_path
, "dampeningHistoryEntry");
7324 vty_out(vty
, ", (history entry)");
7325 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7327 json_object_boolean_true_add(
7328 json_path
, "dampeningSuppressed");
7330 vty_out(vty
, ", (suppressed due to dampening)");
7336 /* Line2 display Next-hop, Neighbor, Router-id */
7337 /* Display the nexthop */
7338 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
7339 p
->family
== AF_EVPN
)
7340 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7341 || safi
== SAFI_EVPN
7342 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7343 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7344 || safi
== SAFI_EVPN
) {
7346 json_object_string_add(
7347 json_nexthop_global
, "ip",
7349 attr
->mp_nexthop_global_in
));
7353 attr
->mp_nexthop_global_in
));
7356 json_object_string_add(
7357 json_nexthop_global
, "ip",
7358 inet_ntoa(attr
->nexthop
));
7361 inet_ntoa(attr
->nexthop
));
7365 json_object_string_add(json_nexthop_global
,
7369 json_object_string_add(
7370 json_nexthop_global
, "ip",
7372 &attr
->mp_nexthop_global
, buf
,
7374 json_object_string_add(json_nexthop_global
,
7376 json_object_string_add(json_nexthop_global
,
7381 &attr
->mp_nexthop_global
, buf
,
7386 /* Display the IGP cost or 'inaccessible' */
7387 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7389 json_object_boolean_false_add(
7390 json_nexthop_global
, "accessible");
7392 vty_out(vty
, " (inaccessible)");
7394 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7396 json_object_int_add(
7397 json_nexthop_global
, "metric",
7398 binfo
->extra
->igpmetric
);
7400 vty_out(vty
, " (metric %u)",
7401 binfo
->extra
->igpmetric
);
7404 /* IGP cost is 0, display this only for json */
7407 json_object_int_add(json_nexthop_global
,
7412 json_object_boolean_true_add(
7413 json_nexthop_global
, "accessible");
7416 /* Display peer "from" output */
7417 /* This path was originated locally */
7418 if (binfo
->peer
== bgp
->peer_self
) {
7420 if (safi
== SAFI_EVPN
7421 || (p
->family
== AF_INET
7422 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7424 json_object_string_add(
7425 json_peer
, "peerId", "0.0.0.0");
7427 vty_out(vty
, " from 0.0.0.0 ");
7430 json_object_string_add(json_peer
,
7433 vty_out(vty
, " from :: ");
7437 json_object_string_add(
7438 json_peer
, "routerId",
7439 inet_ntoa(bgp
->router_id
));
7441 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7444 /* We RXed this path from one of our peers */
7448 json_object_string_add(
7449 json_peer
, "peerId",
7450 sockunion2str(&binfo
->peer
->su
, buf
,
7452 json_object_string_add(
7453 json_peer
, "routerId",
7455 &binfo
->peer
->remote_id
, buf1
,
7458 if (binfo
->peer
->hostname
)
7459 json_object_string_add(
7460 json_peer
, "hostname",
7461 binfo
->peer
->hostname
);
7463 if (binfo
->peer
->domainname
)
7464 json_object_string_add(
7465 json_peer
, "domainname",
7466 binfo
->peer
->domainname
);
7468 if (binfo
->peer
->conf_if
)
7469 json_object_string_add(
7470 json_peer
, "interface",
7471 binfo
->peer
->conf_if
);
7473 if (binfo
->peer
->conf_if
) {
7474 if (binfo
->peer
->hostname
7477 BGP_FLAG_SHOW_HOSTNAME
))
7478 vty_out(vty
, " from %s(%s)",
7479 binfo
->peer
->hostname
,
7480 binfo
->peer
->conf_if
);
7482 vty_out(vty
, " from %s",
7483 binfo
->peer
->conf_if
);
7485 if (binfo
->peer
->hostname
7488 BGP_FLAG_SHOW_HOSTNAME
))
7489 vty_out(vty
, " from %s(%s)",
7490 binfo
->peer
->hostname
,
7493 vty_out(vty
, " from %s",
7502 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7503 vty_out(vty
, " (%s)",
7504 inet_ntoa(attr
->originator_id
));
7506 vty_out(vty
, " (%s)",
7509 &binfo
->peer
->remote_id
,
7517 /* display the link-local nexthop */
7518 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7520 json_nexthop_ll
= json_object_new_object();
7521 json_object_string_add(
7522 json_nexthop_ll
, "ip",
7524 &attr
->mp_nexthop_local
, buf
,
7526 json_object_string_add(json_nexthop_ll
, "afi",
7528 json_object_string_add(json_nexthop_ll
, "scope",
7531 json_object_boolean_true_add(json_nexthop_ll
,
7534 if (!attr
->mp_nexthop_prefer_global
)
7535 json_object_boolean_true_add(
7536 json_nexthop_ll
, "used");
7538 json_object_boolean_true_add(
7539 json_nexthop_global
, "used");
7541 vty_out(vty
, " (%s) %s\n",
7543 &attr
->mp_nexthop_local
, buf
,
7545 attr
->mp_nexthop_prefer_global
7550 /* If we do not have a link-local nexthop then we must flag the
7554 json_object_boolean_true_add(
7555 json_nexthop_global
, "used");
7558 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7559 * Int/Ext/Local, Atomic, best */
7561 json_object_string_add(
7562 json_path
, "origin",
7563 bgp_origin_long_str
[attr
->origin
]);
7565 vty_out(vty
, " Origin %s",
7566 bgp_origin_long_str
[attr
->origin
]);
7568 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7570 json_object_int_add(json_path
, "med",
7573 vty_out(vty
, ", metric %u", attr
->med
);
7576 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7578 json_object_int_add(json_path
, "localpref",
7581 vty_out(vty
, ", localpref %u",
7585 json_object_int_add(json_path
, "localpref",
7586 bgp
->default_local_pref
);
7588 vty_out(vty
, ", localpref %u",
7589 bgp
->default_local_pref
);
7592 if (attr
->weight
!= 0) {
7594 json_object_int_add(json_path
, "weight",
7597 vty_out(vty
, ", weight %u", attr
->weight
);
7600 if (attr
->tag
!= 0) {
7602 json_object_int_add(json_path
, "tag",
7605 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7609 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7611 json_object_boolean_false_add(json_path
,
7614 vty_out(vty
, ", invalid");
7615 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7617 json_object_boolean_true_add(json_path
,
7620 vty_out(vty
, ", valid");
7623 if (binfo
->peer
!= bgp
->peer_self
) {
7624 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7625 if (CHECK_FLAG(bgp
->config
,
7626 BGP_CONFIG_CONFEDERATION
)) {
7628 json_object_string_add(
7633 ", confed-internal");
7636 json_object_string_add(
7640 vty_out(vty
, ", internal");
7643 if (bgp_confederation_peers_check(
7644 bgp
, binfo
->peer
->as
)) {
7646 json_object_string_add(
7651 ", confed-external");
7654 json_object_string_add(
7658 vty_out(vty
, ", external");
7661 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7663 json_object_boolean_true_add(json_path
,
7665 json_object_boolean_true_add(json_path
,
7668 vty_out(vty
, ", aggregated, local");
7670 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7672 json_object_boolean_true_add(json_path
,
7675 vty_out(vty
, ", sourced");
7678 json_object_boolean_true_add(json_path
,
7680 json_object_boolean_true_add(json_path
,
7683 vty_out(vty
, ", sourced, local");
7687 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7689 json_object_boolean_true_add(json_path
,
7692 vty_out(vty
, ", atomic-aggregate");
7695 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7696 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7697 && bgp_info_mpath_count(binfo
))) {
7699 json_object_boolean_true_add(json_path
,
7702 vty_out(vty
, ", multipath");
7705 // Mark the bestpath(s)
7706 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7707 first_as
= aspath_get_first_as(attr
->aspath
);
7712 json_object_new_object();
7713 json_object_int_add(json_bestpath
,
7714 "bestpathFromAs", first_as
);
7717 vty_out(vty
, ", bestpath-from-AS %d",
7721 ", bestpath-from-AS Local");
7725 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7729 json_object_new_object();
7730 json_object_boolean_true_add(json_bestpath
,
7733 vty_out(vty
, ", best");
7737 json_object_object_add(json_path
, "bestpath",
7743 /* Line 4 display Community */
7744 if (attr
->community
) {
7746 json_object_lock(attr
->community
->json
);
7747 json_object_object_add(json_path
, "community",
7748 attr
->community
->json
);
7750 vty_out(vty
, " Community: %s\n",
7751 attr
->community
->str
);
7755 /* Line 5 display Extended-community */
7756 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7758 json_ext_community
= json_object_new_object();
7759 json_object_string_add(json_ext_community
,
7761 attr
->ecommunity
->str
);
7762 json_object_object_add(json_path
,
7763 "extendedCommunity",
7764 json_ext_community
);
7766 vty_out(vty
, " Extended Community: %s\n",
7767 attr
->ecommunity
->str
);
7771 /* Line 6 display Large community */
7772 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))
7773 vty_out(vty
, " Large Community: %s\n",
7774 attr
->lcommunity
->str
);
7776 /* Line 7 display Originator, Cluster-id */
7777 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7778 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7780 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7782 json_object_string_add(
7783 json_path
, "originatorId",
7784 inet_ntoa(attr
->originator_id
));
7786 vty_out(vty
, " Originator: %s",
7787 inet_ntoa(attr
->originator_id
));
7790 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7795 json_object_new_object();
7796 json_cluster_list_list
=
7797 json_object_new_array();
7800 i
< attr
->cluster
->length
/ 4;
7802 json_string
= json_object_new_string(
7806 json_object_array_add(
7807 json_cluster_list_list
,
7811 /* struct cluster_list does not have
7813 * aspath and community do. Add this
7816 json_object_string_add(json_cluster_list,
7817 "string", attr->cluster->str);
7819 json_object_object_add(
7820 json_cluster_list
, "list",
7821 json_cluster_list_list
);
7822 json_object_object_add(
7823 json_path
, "clusterList",
7826 vty_out(vty
, ", Cluster list: ");
7829 i
< attr
->cluster
->length
/ 4;
7843 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7844 bgp_damp_info_vty(vty
, binfo
, json_path
);
7847 #if defined(HAVE_CUMULUS)
7848 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7849 && safi
!= SAFI_EVPN
)
7851 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
7854 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
7856 json_object_int_add(json_path
, "remoteLabel",
7859 vty_out(vty
, " Remote label: %d\n", label
);
7863 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7865 json_object_int_add(json_path
, "labelIndex",
7868 vty_out(vty
, " Label Index: %d\n",
7872 /* Line 8 display Addpath IDs */
7873 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7875 json_object_int_add(json_path
, "addpathRxId",
7876 binfo
->addpath_rx_id
);
7877 json_object_int_add(json_path
, "addpathTxId",
7878 binfo
->addpath_tx_id
);
7880 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7881 binfo
->addpath_rx_id
,
7882 binfo
->addpath_tx_id
);
7886 /* If we used addpath to TX a non-bestpath we need to display
7887 * "Advertised to" on a path-by-path basis */
7888 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7891 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7893 bgp_addpath_encode_tx(peer
, afi
, safi
);
7894 has_adj
= bgp_adj_out_lookup(
7895 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7897 if ((addpath_capable
&& has_adj
)
7898 || (!addpath_capable
&& has_adj
7899 && CHECK_FLAG(binfo
->flags
,
7900 BGP_INFO_SELECTED
))) {
7901 if (json_path
&& !json_adv_to
)
7903 json_object_new_object();
7905 route_vty_out_advertised_to(
7914 json_object_object_add(json_path
,
7925 /* Line 9 display Uptime */
7926 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
7928 json_last_update
= json_object_new_object();
7929 json_object_int_add(json_last_update
, "epoch", tbuf
);
7930 json_object_string_add(json_last_update
, "string",
7932 json_object_object_add(json_path
, "lastUpdate",
7935 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
7938 /* We've constructed the json object for this path, add it to the json
7942 if (json_nexthop_global
|| json_nexthop_ll
) {
7943 json_nexthops
= json_object_new_array();
7945 if (json_nexthop_global
)
7946 json_object_array_add(json_nexthops
,
7947 json_nexthop_global
);
7949 if (json_nexthop_ll
)
7950 json_object_array_add(json_nexthops
,
7953 json_object_object_add(json_path
, "nexthops",
7957 json_object_object_add(json_path
, "peer", json_peer
);
7958 json_object_array_add(json_paths
, json_path
);
7963 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7964 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7965 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
7967 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
7968 const char *prefix_list_str
, afi_t afi
,
7969 safi_t safi
, enum bgp_show_type type
);
7970 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
7971 const char *filter
, afi_t afi
, safi_t safi
,
7972 enum bgp_show_type type
);
7973 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
7974 const char *rmap_str
, afi_t afi
, safi_t safi
,
7975 enum bgp_show_type type
);
7976 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
7977 const char *com
, int exact
, afi_t afi
,
7979 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
7980 const char *prefix
, afi_t afi
, safi_t safi
,
7981 enum bgp_show_type type
);
7982 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
7983 safi_t safi
, enum bgp_show_type type
);
7984 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
7985 struct cmd_token
**argv
, int exact
, afi_t afi
,
7988 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
,
7989 struct bgp_table
*table
, enum bgp_show_type type
,
7990 void *output_arg
, u_char use_json
)
7992 struct bgp_info
*ri
;
7993 struct bgp_node
*rn
;
7996 unsigned long output_count
;
7997 unsigned long total_count
;
8001 json_object
*json_paths
= NULL
;
8006 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
8007 ", \"routerId\": \"%s\", \"routes\": { ",
8008 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
8009 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8011 table
->version
, inet_ntoa(bgp
->router_id
));
8012 json_paths
= json_object_new_object();
8015 /* This is first entry point, so reset total line. */
8019 /* Start processing of routes. */
8020 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
8021 if (rn
->info
!= NULL
) {
8023 if (!first
&& use_json
) {
8027 json_paths
= json_object_new_array();
8031 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8033 if (type
== bgp_show_type_flap_statistics
8034 || type
== bgp_show_type_flap_neighbor
8035 || type
== bgp_show_type_dampend_paths
8036 || type
== bgp_show_type_damp_neighbor
) {
8038 && ri
->extra
->damp_info
))
8041 if (type
== bgp_show_type_regexp
) {
8042 regex_t
*regex
= output_arg
;
8044 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8048 if (type
== bgp_show_type_prefix_list
) {
8049 struct prefix_list
*plist
= output_arg
;
8051 if (prefix_list_apply(plist
, &rn
->p
)
8055 if (type
== bgp_show_type_filter_list
) {
8056 struct as_list
*as_list
= output_arg
;
8058 if (as_list_apply(as_list
,
8060 != AS_FILTER_PERMIT
)
8063 if (type
== bgp_show_type_route_map
) {
8064 struct route_map
*rmap
= output_arg
;
8065 struct bgp_info binfo
;
8066 struct attr dummy_attr
;
8069 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8071 binfo
.peer
= ri
->peer
;
8072 binfo
.attr
= &dummy_attr
;
8074 ret
= route_map_apply(rmap
, &rn
->p
,
8076 if (ret
== RMAP_DENYMATCH
)
8079 if (type
== bgp_show_type_neighbor
8080 || type
== bgp_show_type_flap_neighbor
8081 || type
== bgp_show_type_damp_neighbor
) {
8082 union sockunion
*su
= output_arg
;
8084 if (ri
->peer
== NULL
8085 || ri
->peer
->su_remote
== NULL
8087 ri
->peer
->su_remote
, su
))
8090 if (type
== bgp_show_type_cidr_only
) {
8091 u_int32_t destination
;
8094 ntohl(rn
->p
.u
.prefix4
.s_addr
);
8095 if (IN_CLASSC(destination
)
8096 && rn
->p
.prefixlen
== 24)
8098 if (IN_CLASSB(destination
)
8099 && rn
->p
.prefixlen
== 16)
8101 if (IN_CLASSA(destination
)
8102 && rn
->p
.prefixlen
== 8)
8105 if (type
== bgp_show_type_prefix_longer
) {
8106 struct prefix
*p
= output_arg
;
8108 if (!prefix_match(p
, &rn
->p
))
8111 if (type
== bgp_show_type_community_all
) {
8112 if (!ri
->attr
->community
)
8115 if (type
== bgp_show_type_community
) {
8116 struct community
*com
= output_arg
;
8118 if (!ri
->attr
->community
8119 || !community_match(
8120 ri
->attr
->community
,
8124 if (type
== bgp_show_type_community_exact
) {
8125 struct community
*com
= output_arg
;
8127 if (!ri
->attr
->community
8129 ri
->attr
->community
,
8133 if (type
== bgp_show_type_community_list
) {
8134 struct community_list
*list
=
8137 if (!community_list_match(
8138 ri
->attr
->community
, list
))
8142 == bgp_show_type_community_list_exact
) {
8143 struct community_list
*list
=
8146 if (!community_list_exact_match(
8147 ri
->attr
->community
, list
))
8150 if (type
== bgp_show_type_lcommunity
) {
8151 struct lcommunity
*lcom
= output_arg
;
8153 if (!ri
->attr
->lcommunity
8154 || !lcommunity_match(
8155 ri
->attr
->lcommunity
,
8159 if (type
== bgp_show_type_lcommunity_list
) {
8160 struct community_list
*list
=
8163 if (!lcommunity_list_match(
8164 ri
->attr
->lcommunity
, list
))
8167 if (type
== bgp_show_type_lcommunity_all
) {
8168 if (!ri
->attr
->lcommunity
)
8171 if (type
== bgp_show_type_dampend_paths
8172 || type
== bgp_show_type_damp_neighbor
) {
8173 if (!CHECK_FLAG(ri
->flags
,
8175 || CHECK_FLAG(ri
->flags
,
8180 if (!use_json
&& header
) {
8182 "BGP table version is %" PRIu64
8183 ", local router ID is %s\n",
8185 inet_ntoa(bgp
->router_id
));
8186 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8187 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8188 if (type
== bgp_show_type_dampend_paths
8189 || type
== bgp_show_type_damp_neighbor
)
8191 BGP_SHOW_DAMP_HEADER
);
8193 type
== bgp_show_type_flap_statistics
8194 || type
== bgp_show_type_flap_neighbor
)
8196 BGP_SHOW_FLAP_HEADER
);
8198 vty_out(vty
, BGP_SHOW_HEADER
);
8202 if (type
== bgp_show_type_dampend_paths
8203 || type
== bgp_show_type_damp_neighbor
)
8205 vty
, &rn
->p
, ri
, display
,
8206 SAFI_UNICAST
, use_json
,
8208 else if (type
== bgp_show_type_flap_statistics
8209 || type
== bgp_show_type_flap_neighbor
)
8211 vty
, &rn
->p
, ri
, display
,
8212 SAFI_UNICAST
, use_json
,
8215 route_vty_out(vty
, &rn
->p
, ri
, display
,
8216 SAFI_UNICAST
, json_paths
);
8224 sprintf(buf2
, "%s/%d",
8225 inet_ntop(p
->family
,
8229 vty_out(vty
, "\"%s\": ", buf2
);
8231 json_object_to_json_string(
8233 json_object_free(json_paths
);
8240 json_object_free(json_paths
);
8241 vty_out(vty
, " } }\n");
8243 /* No route is displayed */
8244 if (output_count
== 0) {
8245 if (type
== bgp_show_type_normal
)
8247 "No BGP prefixes displayed, %ld exist\n",
8251 "\nDisplayed %ld routes and %ld total paths\n",
8252 output_count
, total_count
);
8258 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8259 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8261 struct bgp_table
*table
;
8264 bgp
= bgp_get_default();
8269 vty_out(vty
, "No BGP process is configured\n");
8271 vty_out(vty
, "{}\n");
8275 /* use MPLS and ENCAP specific shows until they are merged */
8276 if (safi
== SAFI_MPLS_VPN
) {
8277 return bgp_show_mpls_vpn(vty
, afi
, NULL
, type
, output_arg
, 0,
8280 /* labeled-unicast routes live in the unicast table */
8281 else if (safi
== SAFI_LABELED_UNICAST
)
8282 safi
= SAFI_UNICAST
;
8284 table
= bgp
->rib
[afi
][safi
];
8286 return bgp_show_table(vty
, bgp
, table
, type
, output_arg
, use_json
);
8289 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8290 safi_t safi
, u_char use_json
)
8292 struct listnode
*node
, *nnode
;
8297 vty_out(vty
, "{\n");
8299 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8302 vty_out(vty
, ",\n");
8306 vty_out(vty
, "\"%s\":",
8307 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8311 vty_out(vty
, "\nInstance %s:\n",
8312 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8316 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8321 vty_out(vty
, "}\n");
8324 /* Header of detailed BGP route information */
8325 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8326 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8327 afi_t afi
, safi_t safi
, json_object
*json
)
8329 struct bgp_info
*ri
;
8332 struct listnode
*node
, *nnode
;
8333 char buf1
[INET6_ADDRSTRLEN
];
8334 char buf2
[INET6_ADDRSTRLEN
];
8335 #if defined(HAVE_CUMULUS)
8336 char buf3
[EVPN_ROUTE_STRLEN
];
8342 int no_advertise
= 0;
8345 int has_valid_label
= 0;
8346 mpls_label_t label
= 0;
8347 json_object
*json_adv_to
= NULL
;
8350 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8352 if (has_valid_label
)
8353 label
= label_pton(&rn
->local_label
);
8356 if (has_valid_label
)
8357 json_object_int_add(json
, "localLabel", label
);
8359 json_object_string_add(json
, "prefix",
8360 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8362 json_object_int_add(json
, "prefixlen", p
->prefixlen
);
8364 #if defined(HAVE_CUMULUS)
8365 if (safi
== SAFI_EVPN
)
8366 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8367 prd
? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8370 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8371 buf3
, sizeof(buf3
)));
8373 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8374 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8375 ? prefix_rd2str(prd
, buf1
,
8378 safi
== SAFI_MPLS_VPN
? ":" : "",
8379 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8383 if (p
->family
== AF_ETHERNET
)
8384 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8386 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8388 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8389 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8390 || safi
== SAFI_EVPN
)
8391 ? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8393 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8395 buf2
, p
->prefixlen
);
8398 if (has_valid_label
)
8399 vty_out(vty
, "Local label: %d\n", label
);
8400 #if defined(HAVE_CUMULUS)
8401 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8403 if (bgp_labeled_safi(safi
))
8405 vty_out(vty
, "not allocated\n");
8408 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8410 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8412 if (ri
->extra
&& ri
->extra
->suppress
)
8414 if (ri
->attr
->community
!= NULL
) {
8415 if (community_include(ri
->attr
->community
,
8416 COMMUNITY_NO_ADVERTISE
))
8418 if (community_include(ri
->attr
->community
,
8419 COMMUNITY_NO_EXPORT
))
8421 if (community_include(ri
->attr
->community
,
8422 COMMUNITY_LOCAL_AS
))
8429 vty_out(vty
, "Paths: (%d available", count
);
8431 vty_out(vty
, ", best #%d", best
);
8432 if (safi
== SAFI_UNICAST
)
8433 vty_out(vty
, ", table %s",
8435 == BGP_INSTANCE_TYPE_DEFAULT
)
8436 ? "Default-IP-Routing-Table"
8439 vty_out(vty
, ", no best path");
8442 vty_out(vty
, ", not advertised to any peer");
8444 vty_out(vty
, ", not advertised to EBGP peer");
8446 vty_out(vty
, ", not advertised outside local AS");
8450 ", Advertisements suppressed by an aggregate.");
8451 vty_out(vty
, ")\n");
8454 /* If we are not using addpath then we can display Advertised to and
8456 * show what peers we advertised the bestpath to. If we are using
8458 * though then we must display Advertised to on a path-by-path basis. */
8459 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8460 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8461 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8462 if (json
&& !json_adv_to
)
8463 json_adv_to
= json_object_new_object();
8465 route_vty_out_advertised_to(
8467 " Advertised to non peer-group peers:\n ",
8474 json_object_object_add(json
, "advertisedTo",
8479 vty_out(vty
, " Not advertised to any peer");
8485 /* Display specified route of BGP table. */
8486 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8487 struct bgp_table
*rib
, const char *ip_str
,
8488 afi_t afi
, safi_t safi
,
8489 struct prefix_rd
*prd
, int prefix_check
,
8490 enum bgp_path_type pathtype
, u_char use_json
)
8495 struct prefix match
;
8496 struct bgp_node
*rn
;
8497 struct bgp_node
*rm
;
8498 struct bgp_info
*ri
;
8499 struct bgp_table
*table
;
8500 json_object
*json
= NULL
;
8501 json_object
*json_paths
= NULL
;
8503 /* Check IP address argument. */
8504 ret
= str2prefix(ip_str
, &match
);
8506 vty_out(vty
, "address is malformed\n");
8510 match
.family
= afi2family(afi
);
8513 json
= json_object_new_object();
8514 json_paths
= json_object_new_array();
8517 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8518 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8519 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8522 if ((table
= rn
->info
) != NULL
) {
8525 if ((rm
= bgp_node_match(table
, &match
))
8529 != match
.prefixlen
) {
8530 bgp_unlock_node(rm
);
8534 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8536 route_vty_out_detail_header(
8547 if (pathtype
== BGP_PATH_ALL
8549 == BGP_PATH_BESTPATH
8554 == BGP_PATH_MULTIPATH
8560 BGP_INFO_SELECTED
))))
8561 route_vty_out_detail(
8568 bgp_unlock_node(rm
);
8575 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8577 || rn
->p
.prefixlen
== match
.prefixlen
) {
8578 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8580 route_vty_out_detail_header(
8581 vty
, bgp
, rn
, NULL
, afi
,
8587 if (pathtype
== BGP_PATH_ALL
8588 || (pathtype
== BGP_PATH_BESTPATH
8592 || (pathtype
== BGP_PATH_MULTIPATH
8598 BGP_INFO_SELECTED
))))
8599 route_vty_out_detail(
8600 vty
, bgp
, &rn
->p
, ri
,
8601 afi
, safi
, json_paths
);
8605 bgp_unlock_node(rn
);
8611 json_object_object_add(json
, "paths", json_paths
);
8613 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8614 json
, JSON_C_TO_STRING_PRETTY
));
8615 json_object_free(json
);
8618 vty_out(vty
, "%% Network not in table\n");
8626 /* Display specified route of Main RIB */
8627 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8628 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8629 int prefix_check
, enum bgp_path_type pathtype
,
8633 bgp
= bgp_get_default();
8636 vty_out(vty
, "No BGP process is configured\n");
8638 vty_out(vty
, "{}\n");
8643 /* labeled-unicast routes live in the unicast table */
8644 if (safi
== SAFI_LABELED_UNICAST
)
8645 safi
= SAFI_UNICAST
;
8647 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8648 afi
, safi
, prd
, prefix_check
, pathtype
,
8652 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8653 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8656 struct lcommunity
*lcom
;
8662 b
= buffer_new(1024);
8663 for (i
= 0; i
< argc
; i
++) {
8665 buffer_putc(b
, ' ');
8667 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8669 buffer_putstr(b
, argv
[i
]->arg
);
8673 buffer_putc(b
, '\0');
8675 str
= buffer_getstr(b
);
8678 lcom
= lcommunity_str2com(str
);
8679 XFREE(MTYPE_TMP
, str
);
8681 vty_out(vty
, "%% Large-community malformed\n");
8685 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8689 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8690 const char *lcom
, afi_t afi
, safi_t safi
,
8693 struct community_list
*list
;
8695 list
= community_list_lookup(bgp_clist
, lcom
,
8696 LARGE_COMMUNITY_LIST_MASTER
);
8698 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8703 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8707 DEFUN (show_ip_bgp_large_community_list
,
8708 show_ip_bgp_large_community_list_cmd
,
8709 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8713 BGP_INSTANCE_HELP_STR
8715 BGP_SAFI_WITH_LABEL_HELP_STR
8716 "Display routes matching the large-community-list\n"
8717 "large-community-list number\n"
8718 "large-community-list name\n"
8722 afi_t afi
= AFI_IP6
;
8723 safi_t safi
= SAFI_UNICAST
;
8726 if (argv_find(argv
, argc
, "ip", &idx
))
8728 if (argv_find(argv
, argc
, "view", &idx
)
8729 || argv_find(argv
, argc
, "vrf", &idx
))
8730 vrf
= argv
[++idx
]->arg
;
8731 if (argv_find(argv
, argc
, "ipv4", &idx
)
8732 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8733 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8734 if (argv_find(argv
, argc
, "unicast", &idx
)
8735 || argv_find(argv
, argc
, "multicast", &idx
))
8736 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8739 int uj
= use_json(argc
, argv
);
8741 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8743 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8747 argv_find(argv
, argc
, "large-community-list", &idx
);
8748 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8751 DEFUN (show_ip_bgp_large_community
,
8752 show_ip_bgp_large_community_cmd
,
8753 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8757 BGP_INSTANCE_HELP_STR
8759 BGP_SAFI_WITH_LABEL_HELP_STR
8760 "Display routes matching the large-communities\n"
8761 "List of large-community numbers\n"
8765 afi_t afi
= AFI_IP6
;
8766 safi_t safi
= SAFI_UNICAST
;
8769 if (argv_find(argv
, argc
, "ip", &idx
))
8771 if (argv_find(argv
, argc
, "view", &idx
)
8772 || argv_find(argv
, argc
, "vrf", &idx
))
8773 vrf
= argv
[++idx
]->arg
;
8774 if (argv_find(argv
, argc
, "ipv4", &idx
)
8775 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8776 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8777 if (argv_find(argv
, argc
, "unicast", &idx
)
8778 || argv_find(argv
, argc
, "multicast", &idx
))
8779 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8782 int uj
= use_json(argc
, argv
);
8784 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8786 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8790 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8791 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8793 return bgp_show(vty
, bgp
, afi
, safi
,
8794 bgp_show_type_lcommunity_all
, NULL
, uj
);
8797 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8800 /* BGP route print out function. */
8803 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8806 |dampening <flap-statistics|dampened-paths|parameters>\
8811 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
8812 |community-list <(1-500)|WORD> [exact-match]\
8813 |A.B.C.D/M longer-prefixes\
8814 |X:X::X:X/M longer-prefixes>\
8819 BGP_INSTANCE_HELP_STR
8821 BGP_SAFI_WITH_LABEL_HELP_STR
8822 "Display only routes with non-natural netmasks\n"
8823 "Display detailed information about dampening\n"
8824 "Display flap statistics of routes\n"
8825 "Display paths suppressed due to dampening\n"
8826 "Display detail of configured dampening parameters\n"
8827 "Display routes matching the route-map\n"
8828 "A route-map to match on\n"
8829 "Display routes conforming to the prefix-list\n"
8830 "Prefix-list name\n"
8831 "Display routes conforming to the filter-list\n"
8832 "Regular expression access list name\n"
8833 "BGP RIB advertisement statistics\n"
8834 "Display routes matching the communities\n"
8836 "Do not send outside local AS (well-known community)\n"
8837 "Do not advertise to any peer (well-known community)\n"
8838 "Do not export to next AS (well-known community)\n"
8839 "Exact match of the communities\n"
8840 "Display routes matching the community-list\n"
8841 "community-list number\n"
8842 "community-list name\n"
8843 "Exact match of the communities\n"
8845 "Display route and more specific routes\n"
8847 "Display route and more specific routes\n"
8850 afi_t afi
= AFI_IP6
;
8851 safi_t safi
= SAFI_UNICAST
;
8852 int exact_match
= 0;
8853 enum bgp_show_type sh_type
= bgp_show_type_normal
;
8854 struct bgp
*bgp
= NULL
;
8857 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8862 int uj
= use_json(argc
, argv
);
8866 if (argv_find(argv
, argc
, "cidr-only", &idx
))
8867 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
8870 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8871 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
8872 return bgp_show(vty
, bgp
, afi
, safi
,
8873 bgp_show_type_dampend_paths
, NULL
, uj
);
8874 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
8875 return bgp_show(vty
, bgp
, afi
, safi
,
8876 bgp_show_type_flap_statistics
, NULL
,
8878 else if (argv_find(argv
, argc
, "parameters", &idx
))
8879 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8882 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8883 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8884 safi
, bgp_show_type_prefix_list
);
8886 if (argv_find(argv
, argc
, "filter-list", &idx
))
8887 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8888 safi
, bgp_show_type_filter_list
);
8890 if (argv_find(argv
, argc
, "statistics", &idx
))
8891 return bgp_table_stats(vty
, bgp
, afi
, safi
);
8893 if (argv_find(argv
, argc
, "route-map", &idx
))
8894 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8895 safi
, bgp_show_type_route_map
);
8897 if (argv_find(argv
, argc
, "community", &idx
)) {
8898 /* show a specific community */
8899 if (argv_find(argv
, argc
, "local-AS", &idx
)
8900 || argv_find(argv
, argc
, "no-advertise", &idx
)
8901 || argv_find(argv
, argc
, "no-export", &idx
)) {
8902 if (argv_find(argv
, argc
, "exact_match", &idx
))
8904 return bgp_show_community(vty
, bgp
, argc
, argv
,
8905 exact_match
, afi
, safi
);
8907 /* show all communities */
8909 return bgp_show(vty
, bgp
, afi
, safi
,
8910 bgp_show_type_community_all
, NULL
, uj
);
8913 if (argv_find(argv
, argc
, "community-list", &idx
)) {
8914 const char *clist_number_or_name
= argv
[++idx
]->arg
;
8915 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
8917 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
8918 exact_match
, afi
, safi
);
8921 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8922 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8923 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
8925 bgp_show_type_prefix_longer
);
8927 if (safi
== SAFI_MPLS_VPN
)
8928 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
8931 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
8934 DEFUN (show_ip_bgp_route
,
8935 show_ip_bgp_route_cmd
,
8936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
8937 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
8941 BGP_INSTANCE_HELP_STR
8943 BGP_SAFI_WITH_LABEL_HELP_STR
8944 "Network in the BGP routing table to display\n"
8946 "Network in the BGP routing table to display\n"
8948 "Display only the bestpath\n"
8949 "Display only multipaths\n"
8952 int prefix_check
= 0;
8954 afi_t afi
= AFI_IP6
;
8955 safi_t safi
= SAFI_UNICAST
;
8956 char *prefix
= NULL
;
8957 struct bgp
*bgp
= NULL
;
8958 enum bgp_path_type path_type
;
8959 u_char uj
= use_json(argc
, argv
);
8963 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8970 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8974 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8975 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
8976 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
8978 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8979 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8982 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
8983 && afi
!= AFI_IP6
) {
8985 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
8988 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
8991 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
8995 prefix
= argv
[idx
]->arg
;
8997 /* [<bestpath|multipath>] */
8998 if (argv_find(argv
, argc
, "bestpath", &idx
))
8999 path_type
= BGP_PATH_BESTPATH
;
9000 else if (argv_find(argv
, argc
, "multipath", &idx
))
9001 path_type
= BGP_PATH_MULTIPATH
;
9003 path_type
= BGP_PATH_ALL
;
9005 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9009 DEFUN (show_ip_bgp_regexp
,
9010 show_ip_bgp_regexp_cmd
,
9011 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9015 BGP_INSTANCE_HELP_STR
9017 BGP_SAFI_WITH_LABEL_HELP_STR
9018 "Display routes matching the AS path regular expression\n"
9019 "A regular-expression to match the BGP AS paths\n")
9021 afi_t afi
= AFI_IP6
;
9022 safi_t safi
= SAFI_UNICAST
;
9023 struct bgp
*bgp
= NULL
;
9026 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9031 // get index of regex
9032 argv_find(argv
, argc
, "regexp", &idx
);
9035 char *regstr
= argv_concat(argv
, argc
, idx
);
9036 int rc
= bgp_show_regexp(vty
, (const char *)regstr
, afi
, safi
,
9037 bgp_show_type_regexp
);
9038 XFREE(MTYPE_TMP
, regstr
);
9042 DEFUN (show_ip_bgp_instance_all
,
9043 show_ip_bgp_instance_all_cmd
,
9044 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9048 BGP_INSTANCE_ALL_HELP_STR
9050 BGP_SAFI_WITH_LABEL_HELP_STR
9054 safi_t safi
= SAFI_UNICAST
;
9055 struct bgp
*bgp
= NULL
;
9058 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9063 int uj
= use_json(argc
, argv
);
9067 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9071 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
9072 safi_t safi
, enum bgp_show_type type
)
9077 regex
= bgp_regcomp(regstr
);
9079 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9083 rc
= bgp_show(vty
, NULL
, afi
, safi
, type
, regex
, 0);
9084 bgp_regex_free(regex
);
9088 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9089 const char *prefix_list_str
, afi_t afi
,
9090 safi_t safi
, enum bgp_show_type type
)
9092 struct prefix_list
*plist
;
9094 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9095 if (plist
== NULL
) {
9096 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9101 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9104 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9105 const char *filter
, afi_t afi
, safi_t safi
,
9106 enum bgp_show_type type
)
9108 struct as_list
*as_list
;
9110 as_list
= as_list_lookup(filter
);
9111 if (as_list
== NULL
) {
9112 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9117 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9120 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9121 const char *rmap_str
, afi_t afi
, safi_t safi
,
9122 enum bgp_show_type type
)
9124 struct route_map
*rmap
;
9126 rmap
= route_map_lookup_by_name(rmap_str
);
9128 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9132 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9135 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9136 struct cmd_token
**argv
, int exact
, afi_t afi
,
9139 struct community
*com
;
9146 b
= buffer_new(1024);
9147 for (i
= 0; i
< argc
; i
++) {
9149 buffer_putc(b
, ' ');
9151 if (strmatch(argv
[i
]->text
, "unicast")
9152 || strmatch(argv
[i
]->text
, "multicast"))
9157 buffer_putstr(b
, argv
[i
]->arg
);
9159 buffer_putc(b
, '\0');
9161 str
= buffer_getstr(b
);
9164 com
= community_str2com(str
);
9165 XFREE(MTYPE_TMP
, str
);
9167 vty_out(vty
, "%% Community malformed: \n");
9171 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9172 (exact
? bgp_show_type_community_exact
9173 : bgp_show_type_community
),
9175 community_free(com
);
9180 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9181 const char *com
, int exact
, afi_t afi
,
9184 struct community_list
*list
;
9186 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9188 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9192 return bgp_show(vty
, bgp
, afi
, safi
,
9193 (exact
? bgp_show_type_community_list_exact
9194 : bgp_show_type_community_list
),
9198 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9199 const char *prefix
, afi_t afi
, safi_t safi
,
9200 enum bgp_show_type type
)
9207 ret
= str2prefix(prefix
, p
);
9209 vty_out(vty
, "%% Malformed Prefix\n");
9213 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9218 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9219 const char *ip_str
, u_char use_json
)
9225 /* Get peer sockunion. */
9226 ret
= str2sockunion(ip_str
, &su
);
9228 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9230 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9234 json_object
*json_no
= NULL
;
9235 json_no
= json_object_new_object();
9236 json_object_string_add(
9238 "malformedAddressOrName",
9240 vty_out(vty
, "%s\n",
9241 json_object_to_json_string(
9243 json_object_free(json_no
);
9246 "%% Malformed address or name: %s\n",
9254 /* Peer structure lookup. */
9255 peer
= peer_lookup(bgp
, &su
);
9258 json_object
*json_no
= NULL
;
9259 json_no
= json_object_new_object();
9260 json_object_string_add(json_no
, "warning",
9261 "No such neighbor");
9262 vty_out(vty
, "%s\n",
9263 json_object_to_json_string(json_no
));
9264 json_object_free(json_no
);
9266 vty_out(vty
, "No such neighbor\n");
9274 BGP_STATS_MAXBITLEN
= 0,
9278 BGP_STATS_UNAGGREGATEABLE
,
9279 BGP_STATS_MAX_AGGREGATEABLE
,
9280 BGP_STATS_AGGREGATES
,
9282 BGP_STATS_ASPATH_COUNT
,
9283 BGP_STATS_ASPATH_MAXHOPS
,
9284 BGP_STATS_ASPATH_TOTHOPS
,
9285 BGP_STATS_ASPATH_MAXSIZE
,
9286 BGP_STATS_ASPATH_TOTSIZE
,
9287 BGP_STATS_ASN_HIGHEST
,
9291 static const char *table_stats_strs
[] = {
9292 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9293 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9294 [BGP_STATS_RIB
] = "Total Advertisements",
9295 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9296 [BGP_STATS_MAX_AGGREGATEABLE
] =
9297 "Maximum aggregateable prefixes",
9298 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9299 [BGP_STATS_SPACE
] = "Address space advertised",
9300 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9301 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9302 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9303 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9304 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9305 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9306 [BGP_STATS_MAX
] = NULL
,
9309 struct bgp_table_stats
{
9310 struct bgp_table
*table
;
9311 unsigned long long counts
[BGP_STATS_MAX
];
9315 #define TALLY_SIGFIG 100000
9316 static unsigned long
9317 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9319 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9320 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9321 unsigned long ret
= newtot
/ count
;
9323 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9330 static int bgp_table_stats_walker(struct thread
*t
)
9332 struct bgp_node
*rn
;
9333 struct bgp_node
*top
;
9334 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9335 unsigned int space
= 0;
9337 if (!(top
= bgp_table_top(ts
->table
)))
9340 switch (top
->p
.family
) {
9342 space
= IPV4_MAX_BITLEN
;
9345 space
= IPV6_MAX_BITLEN
;
9349 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9351 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9352 struct bgp_info
*ri
;
9353 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9354 unsigned int rinum
= 0;
9362 ts
->counts
[BGP_STATS_PREFIXES
]++;
9363 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9366 ts
->counts
[BGP_STATS_AVGPLEN
]
9367 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9368 ts
->counts
[BGP_STATS_AVGPLEN
],
9372 /* check if the prefix is included by any other announcements */
9373 while (prn
&& !prn
->info
)
9374 prn
= bgp_node_parent_nolock(prn
);
9376 if (prn
== NULL
|| prn
== top
) {
9377 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9378 /* announced address space */
9380 ts
->counts
[BGP_STATS_SPACE
] +=
9381 1 << (space
- rn
->p
.prefixlen
);
9382 } else if (prn
->info
)
9383 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9385 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9387 ts
->counts
[BGP_STATS_RIB
]++;
9390 && (CHECK_FLAG(ri
->attr
->flag
,
9392 BGP_ATTR_ATOMIC_AGGREGATE
))))
9393 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9396 if (ri
->attr
&& ri
->attr
->aspath
) {
9398 aspath_count_hops(ri
->attr
->aspath
);
9400 aspath_size(ri
->attr
->aspath
);
9401 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9403 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9405 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9406 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9409 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9410 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9413 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9414 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9416 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9417 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9418 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9420 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9421 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9422 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9425 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9426 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9434 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9437 struct bgp_table_stats ts
;
9440 if (!bgp
->rib
[afi
][safi
]) {
9441 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9446 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9448 /* labeled-unicast routes live in the unicast table */
9449 if (safi
== SAFI_LABELED_UNICAST
)
9450 safi
= SAFI_UNICAST
;
9452 memset(&ts
, 0, sizeof(ts
));
9453 ts
.table
= bgp
->rib
[afi
][safi
];
9454 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9456 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9457 if (!table_stats_strs
[i
])
9462 case BGP_STATS_ASPATH_AVGHOPS
:
9463 case BGP_STATS_ASPATH_AVGSIZE
:
9464 case BGP_STATS_AVGPLEN
:
9465 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9466 vty_out (vty
, "%12.2f",
9467 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9470 case BGP_STATS_ASPATH_TOTHOPS
:
9471 case BGP_STATS_ASPATH_TOTSIZE
:
9472 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9473 vty_out(vty
, "%12.2f",
9475 ? (float)ts
.counts
[i
]
9477 [BGP_STATS_ASPATH_COUNT
]
9480 case BGP_STATS_TOTPLEN
:
9481 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9482 vty_out(vty
, "%12.2f",
9484 ? (float)ts
.counts
[i
]
9486 [BGP_STATS_PREFIXES
]
9489 case BGP_STATS_SPACE
:
9490 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9491 vty_out(vty
, "%12llu\n", ts
.counts
[i
]);
9492 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 9)
9494 vty_out(vty
, "%30s: ", "%% announced ");
9495 vty_out(vty
, "%12.2f\n",
9496 100 * (float)ts
.counts
[BGP_STATS_SPACE
]
9497 / (float)((uint64_t)1UL
9499 [BGP_STATS_MAXBITLEN
]));
9500 vty_out(vty
, "%30s: ", "/8 equivalent ");
9501 vty_out(vty
, "%12.2f\n",
9502 (float)ts
.counts
[BGP_STATS_SPACE
]
9505 [BGP_STATS_MAXBITLEN
]
9507 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 25)
9509 vty_out(vty
, "%30s: ", "/24 equivalent ");
9510 vty_out(vty
, "%12.2f",
9511 (float)ts
.counts
[BGP_STATS_SPACE
]
9514 [BGP_STATS_MAXBITLEN
]
9518 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9519 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9536 PCOUNT_PFCNT
, /* the figure we display to users */
9540 static const char *pcount_strs
[] = {
9541 [PCOUNT_ADJ_IN
] = "Adj-in",
9542 [PCOUNT_DAMPED
] = "Damped",
9543 [PCOUNT_REMOVED
] = "Removed",
9544 [PCOUNT_HISTORY
] = "History",
9545 [PCOUNT_STALE
] = "Stale",
9546 [PCOUNT_VALID
] = "Valid",
9547 [PCOUNT_ALL
] = "All RIB",
9548 [PCOUNT_COUNTED
] = "PfxCt counted",
9549 [PCOUNT_PFCNT
] = "Useable",
9550 [PCOUNT_MAX
] = NULL
,
9553 struct peer_pcounts
{
9554 unsigned int count
[PCOUNT_MAX
];
9555 const struct peer
*peer
;
9556 const struct bgp_table
*table
;
9559 static int bgp_peer_count_walker(struct thread
*t
)
9561 struct bgp_node
*rn
;
9562 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9563 const struct peer
*peer
= pc
->peer
;
9565 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9566 struct bgp_adj_in
*ain
;
9567 struct bgp_info
*ri
;
9569 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9570 if (ain
->peer
== peer
)
9571 pc
->count
[PCOUNT_ADJ_IN
]++;
9573 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9574 char buf
[SU_ADDRSTRLEN
];
9576 if (ri
->peer
!= peer
)
9579 pc
->count
[PCOUNT_ALL
]++;
9581 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9582 pc
->count
[PCOUNT_DAMPED
]++;
9583 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9584 pc
->count
[PCOUNT_HISTORY
]++;
9585 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9586 pc
->count
[PCOUNT_REMOVED
]++;
9587 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9588 pc
->count
[PCOUNT_STALE
]++;
9589 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9590 pc
->count
[PCOUNT_VALID
]++;
9591 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9592 pc
->count
[PCOUNT_PFCNT
]++;
9594 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9595 pc
->count
[PCOUNT_COUNTED
]++;
9596 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9598 "%s [pcount] %s/%d is counted but flags 0x%x",
9600 inet_ntop(rn
->p
.family
,
9601 &rn
->p
.u
.prefix
, buf
,
9603 rn
->p
.prefixlen
, ri
->flags
);
9605 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9607 "%s [pcount] %s/%d not counted but flags 0x%x",
9609 inet_ntop(rn
->p
.family
,
9610 &rn
->p
.u
.prefix
, buf
,
9612 rn
->p
.prefixlen
, ri
->flags
);
9619 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9620 safi_t safi
, u_char use_json
)
9622 struct peer_pcounts pcounts
= {.peer
= peer
};
9624 json_object
*json
= NULL
;
9625 json_object
*json_loop
= NULL
;
9628 json
= json_object_new_object();
9629 json_loop
= json_object_new_object();
9632 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9633 || !peer
->bgp
->rib
[afi
][safi
]) {
9635 json_object_string_add(
9637 "No such neighbor or address family");
9638 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9639 json_object_free(json
);
9641 vty_out(vty
, "%% No such neighbor or address family\n");
9646 memset(&pcounts
, 0, sizeof(pcounts
));
9647 pcounts
.peer
= peer
;
9648 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9650 /* in-place call via thread subsystem so as to record execution time
9651 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9652 * * on just vty_read()).
9654 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9657 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9658 json_object_string_add(json
, "multiProtocol",
9659 afi_safi_print(afi
, safi
));
9660 json_object_int_add(json
, "pfxCounter",
9661 peer
->pcount
[afi
][safi
]);
9663 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9664 json_object_int_add(json_loop
, pcount_strs
[i
],
9667 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9669 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9670 json_object_string_add(json
, "pfxctDriftFor",
9672 json_object_string_add(
9673 json
, "recommended",
9674 "Please report this bug, with the above command output");
9676 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9677 json_object_free(json
);
9681 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9682 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9683 peer
->hostname
, peer
->host
,
9684 afi_safi_print(afi
, safi
));
9686 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9687 afi_safi_print(afi
, safi
));
9690 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9691 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9693 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9694 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9697 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9698 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9700 "Please report this bug, with the above command output\n");
9707 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9708 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9709 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9710 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9714 BGP_INSTANCE_HELP_STR
9717 "Detailed information on TCP and BGP neighbor connections\n"
9718 "Neighbor to display information about\n"
9719 "Neighbor to display information about\n"
9720 "Neighbor on BGP configured interface\n"
9721 "Display detailed prefix count information\n"
9724 afi_t afi
= AFI_IP6
;
9725 safi_t safi
= SAFI_UNICAST
;
9728 struct bgp
*bgp
= NULL
;
9730 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9735 int uj
= use_json(argc
, argv
);
9739 argv_find(argv
, argc
, "neighbors", &idx
);
9740 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9744 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9747 #ifdef KEEP_OLD_VPN_COMMANDS
9748 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9749 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9750 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9755 "Display information about all VPNv4 NLRIs\n"
9756 "Detailed information on TCP and BGP neighbor connections\n"
9757 "Neighbor to display information about\n"
9758 "Neighbor to display information about\n"
9759 "Neighbor on BGP configured interface\n"
9760 "Display detailed prefix count information\n"
9765 u_char uj
= use_json(argc
, argv
);
9767 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9771 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9774 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9775 show_ip_bgp_vpn_all_route_prefix_cmd
,
9776 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9781 "Display information about all VPNv4 NLRIs\n"
9782 "Network in the BGP routing table to display\n"
9783 "Network in the BGP routing table to display\n"
9787 char *network
= NULL
;
9788 struct bgp
*bgp
= bgp_get_default();
9790 vty_out(vty
, "Can't find default instance\n");
9794 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9795 network
= argv
[idx
]->arg
;
9796 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9797 network
= argv
[idx
]->arg
;
9799 vty_out(vty
, "Unable to figure out Network\n");
9803 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9804 BGP_PATH_ALL
, use_json(argc
, argv
));
9806 #endif /* KEEP_OLD_VPN_COMMANDS */
9808 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9809 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9810 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9816 "Display information about all EVPN NLRIs\n"
9817 "Network in the BGP routing table to display\n"
9818 "Network in the BGP routing table to display\n"
9822 char *network
= NULL
;
9824 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9825 network
= argv
[idx
]->arg
;
9826 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9827 network
= argv
[idx
]->arg
;
9829 vty_out(vty
, "Unable to figure out Network\n");
9832 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9833 BGP_PATH_ALL
, use_json(argc
, argv
));
9836 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9837 safi_t safi
, int in
, const char *rmap_name
,
9838 u_char use_json
, json_object
*json
)
9840 struct bgp_table
*table
;
9841 struct bgp_adj_in
*ain
;
9842 struct bgp_adj_out
*adj
;
9843 unsigned long output_count
;
9844 unsigned long filtered_count
;
9845 struct bgp_node
*rn
;
9851 struct update_subgroup
*subgrp
;
9852 json_object
*json_scode
= NULL
;
9853 json_object
*json_ocode
= NULL
;
9854 json_object
*json_ar
= NULL
;
9855 struct peer_af
*paf
;
9858 json_scode
= json_object_new_object();
9859 json_ocode
= json_object_new_object();
9860 json_ar
= json_object_new_object();
9862 json_object_string_add(json_scode
, "suppressed", "s");
9863 json_object_string_add(json_scode
, "damped", "d");
9864 json_object_string_add(json_scode
, "history", "h");
9865 json_object_string_add(json_scode
, "valid", "*");
9866 json_object_string_add(json_scode
, "best", ">");
9867 json_object_string_add(json_scode
, "multipath", "=");
9868 json_object_string_add(json_scode
, "internal", "i");
9869 json_object_string_add(json_scode
, "ribFailure", "r");
9870 json_object_string_add(json_scode
, "stale", "S");
9871 json_object_string_add(json_scode
, "removed", "R");
9873 json_object_string_add(json_ocode
, "igp", "i");
9874 json_object_string_add(json_ocode
, "egp", "e");
9875 json_object_string_add(json_ocode
, "incomplete", "?");
9882 json_object_string_add(json
, "alert", "no BGP");
9883 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9884 json_object_free(json
);
9886 vty_out(vty
, "%% No bgp\n");
9890 table
= bgp
->rib
[afi
][safi
];
9892 output_count
= filtered_count
= 0;
9893 subgrp
= peer_subgroup(peer
, afi
, safi
);
9896 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
9898 json_object_int_add(json
, "bgpTableVersion",
9900 json_object_string_add(json
, "bgpLocalRouterId",
9901 inet_ntoa(bgp
->router_id
));
9902 json_object_object_add(json
, "bgpStatusCodes",
9904 json_object_object_add(json
, "bgpOriginCodes",
9906 json_object_string_add(json
,
9907 "bgpOriginatingDefaultNetwork",
9910 vty_out(vty
, "BGP table version is %" PRIu64
9911 ", local router ID is %s\n",
9912 table
->version
, inet_ntoa(bgp
->router_id
));
9913 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9914 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9916 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
9921 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9923 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
9924 if (ain
->peer
== peer
) {
9927 json_object_int_add(
9931 json_object_string_add(
9936 json_object_object_add(
9940 json_object_object_add(
9946 "BGP table version is 0, local router ID is %s\n",
9950 BGP_SHOW_SCODE_HEADER
);
9952 BGP_SHOW_OCODE_HEADER
);
9963 bgp_attr_dup(&attr
, ain
->attr
);
9964 if (bgp_input_modifier(
9965 peer
, &rn
->p
, &attr
,
9981 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
9982 SUBGRP_FOREACH_PEER(adj
->subgroup
, paf
)
9983 if (paf
->peer
== peer
) {
9986 json_object_int_add(
9987 json
, "bgpTableVersion",
9989 json_object_string_add(
9994 json_object_object_add(
9995 json
, "bgpStatusCodes",
9997 json_object_object_add(
9998 json
, "bgpOriginCodes",
10002 "BGP table version is %" PRIu64
10003 ", local router ID is %s\n",
10008 BGP_SHOW_SCODE_HEADER
);
10010 BGP_SHOW_OCODE_HEADER
);
10017 vty_out(vty
, BGP_SHOW_HEADER
);
10022 bgp_attr_dup(&attr
, adj
->attr
);
10023 ret
= bgp_output_modifier(
10024 peer
, &rn
->p
, &attr
, afi
, safi
,
10026 if (ret
!= RMAP_DENY
) {
10027 route_vty_out_tmp(vty
, &rn
->p
,
10039 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10041 if (output_count
!= 0) {
10043 json_object_int_add(json
, "totalPrefixCounter",
10046 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10050 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10051 json_object_free(json
);
10055 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10056 safi_t safi
, int in
, const char *rmap_name
,
10059 json_object
*json
= NULL
;
10062 json
= json_object_new_object();
10064 /* labeled-unicast routes live in the unicast table */
10065 if (safi
== SAFI_LABELED_UNICAST
)
10066 safi
= SAFI_UNICAST
;
10068 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10070 json_object_string_add(
10072 "No such neighbor or address family");
10073 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10074 json_object_free(json
);
10076 vty_out(vty
, "%% No such neighbor or address family\n");
10078 return CMD_WARNING
;
10082 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10083 PEER_FLAG_SOFT_RECONFIG
)) {
10085 json_object_string_add(
10087 "Inbound soft reconfiguration not enabled");
10088 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10089 json_object_free(json
);
10092 "%% Inbound soft reconfiguration not enabled\n");
10094 return CMD_WARNING
;
10097 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10099 return CMD_SUCCESS
;
10102 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10103 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10104 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10105 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10109 BGP_INSTANCE_HELP_STR
10111 BGP_SAFI_WITH_LABEL_HELP_STR
10112 "Detailed information on TCP and BGP neighbor connections\n"
10113 "Neighbor to display information about\n"
10114 "Neighbor to display information about\n"
10115 "Neighbor on BGP configured interface\n"
10116 "Display the received routes from neighbor\n"
10117 "Display the routes advertised to a BGP neighbor\n"
10118 "Route-map to modify the attributes\n"
10119 "Name of the route map\n"
10122 afi_t afi
= AFI_IP6
;
10123 safi_t safi
= SAFI_UNICAST
;
10124 char *rmap_name
= NULL
;
10125 char *peerstr
= NULL
;
10127 struct bgp
*bgp
= NULL
;
10132 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10135 return CMD_WARNING
;
10137 int uj
= use_json(argc
, argv
);
10141 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10142 argv_find(argv
, argc
, "neighbors", &idx
);
10143 peerstr
= argv
[++idx
]->arg
;
10145 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10147 return CMD_WARNING
;
10149 if (argv_find(argv
, argc
, "received-routes", &idx
))
10151 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10153 if (argv_find(argv
, argc
, "route-map", &idx
))
10154 rmap_name
= argv
[++idx
]->arg
;
10156 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10159 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10160 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10161 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10167 "Address Family modifier\n"
10168 "Detailed information on TCP and BGP neighbor connections\n"
10169 "Neighbor to display information about\n"
10170 "Neighbor to display information about\n"
10171 "Neighbor on BGP configured interface\n"
10172 "Display information received from a BGP neighbor\n"
10173 "Display the prefixlist filter\n"
10176 afi_t afi
= AFI_IP6
;
10177 safi_t safi
= SAFI_UNICAST
;
10178 char *peerstr
= NULL
;
10181 union sockunion su
;
10187 /* show [ip] bgp */
10188 if (argv_find(argv
, argc
, "ip", &idx
))
10190 /* [<ipv4|ipv6> [unicast]] */
10191 if (argv_find(argv
, argc
, "ipv4", &idx
))
10193 if (argv_find(argv
, argc
, "ipv6", &idx
))
10195 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10196 argv_find(argv
, argc
, "neighbors", &idx
);
10197 peerstr
= argv
[++idx
]->arg
;
10199 u_char uj
= use_json(argc
, argv
);
10201 ret
= str2sockunion(peerstr
, &su
);
10203 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10206 vty_out(vty
, "{}\n");
10209 "%% Malformed address or name: %s\n",
10211 return CMD_WARNING
;
10214 peer
= peer_lookup(NULL
, &su
);
10217 vty_out(vty
, "{}\n");
10219 vty_out(vty
, "No peer\n");
10220 return CMD_WARNING
;
10224 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10225 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10228 vty_out(vty
, "Address Family: %s\n",
10229 afi_safi_print(afi
, safi
));
10230 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10233 vty_out(vty
, "{}\n");
10235 vty_out(vty
, "No functional output\n");
10238 return CMD_SUCCESS
;
10241 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10242 afi_t afi
, safi_t safi
,
10243 enum bgp_show_type type
, u_char use_json
)
10245 /* labeled-unicast routes live in the unicast table */
10246 if (safi
== SAFI_LABELED_UNICAST
)
10247 safi
= SAFI_UNICAST
;
10249 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10251 json_object
*json_no
= NULL
;
10252 json_no
= json_object_new_object();
10253 json_object_string_add(
10254 json_no
, "warning",
10255 "No such neighbor or address family");
10256 vty_out(vty
, "%s\n",
10257 json_object_to_json_string(json_no
));
10258 json_object_free(json_no
);
10260 vty_out(vty
, "%% No such neighbor or address family\n");
10261 return CMD_WARNING
;
10264 /* labeled-unicast routes live in the unicast table */
10265 if (safi
== SAFI_LABELED_UNICAST
)
10266 safi
= SAFI_UNICAST
;
10268 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10271 DEFUN (show_ip_bgp_neighbor_routes
,
10272 show_ip_bgp_neighbor_routes_cmd
,
10273 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10274 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10278 BGP_INSTANCE_HELP_STR
10280 BGP_SAFI_WITH_LABEL_HELP_STR
10281 "Detailed information on TCP and BGP neighbor connections\n"
10282 "Neighbor to display information about\n"
10283 "Neighbor to display information about\n"
10284 "Neighbor on BGP configured interface\n"
10285 "Display flap statistics of the routes learned from neighbor\n"
10286 "Display the dampened routes received from neighbor\n"
10287 "Display routes learned from neighbor\n"
10290 char *peerstr
= NULL
;
10291 struct bgp
*bgp
= NULL
;
10292 afi_t afi
= AFI_IP6
;
10293 safi_t safi
= SAFI_UNICAST
;
10295 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10299 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10302 return CMD_WARNING
;
10304 int uj
= use_json(argc
, argv
);
10308 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10309 argv_find(argv
, argc
, "neighbors", &idx
);
10310 peerstr
= argv
[++idx
]->arg
;
10312 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10314 vty_out(vty
, "No such neighbor\n");
10315 return CMD_WARNING
;
10318 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10319 sh_type
= bgp_show_type_flap_neighbor
;
10320 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10321 sh_type
= bgp_show_type_damp_neighbor
;
10322 else if (argv_find(argv
, argc
, "routes", &idx
))
10323 sh_type
= bgp_show_type_neighbor
;
10325 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10328 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10330 struct bgp_distance
{
10331 /* Distance value for the IP source prefix. */
10334 /* Name of the access-list to be matched. */
10338 DEFUN (show_bgp_afi_vpn_rd_route
,
10339 show_bgp_afi_vpn_rd_route_cmd
,
10340 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:nn_or_IP-address:nn <A.B.C.D/M|X:X::X:X/M> [json]",
10344 "Address Family modifier\n"
10345 "Display information for a route distinguisher\n"
10346 "Route Distinguisher\n"
10347 "Network in the BGP routing table to display\n"
10348 "Network in the BGP routing table to display\n"
10352 struct prefix_rd prd
;
10353 afi_t afi
= AFI_MAX
;
10356 argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
);
10357 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10359 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10360 return CMD_WARNING
;
10362 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10363 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10366 static struct bgp_distance
*bgp_distance_new(void)
10368 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10371 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10373 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10376 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10377 const char *ip_str
, const char *access_list_str
)
10384 struct bgp_node
*rn
;
10385 struct bgp_distance
*bdistance
;
10387 afi
= bgp_node_afi(vty
);
10388 safi
= bgp_node_safi(vty
);
10390 ret
= str2prefix(ip_str
, &p
);
10392 vty_out(vty
, "Malformed prefix\n");
10393 return CMD_WARNING_CONFIG_FAILED
;
10396 distance
= atoi(distance_str
);
10398 /* Get BGP distance node. */
10399 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10401 bdistance
= rn
->info
;
10402 bgp_unlock_node(rn
);
10404 bdistance
= bgp_distance_new();
10405 rn
->info
= bdistance
;
10408 /* Set distance value. */
10409 bdistance
->distance
= distance
;
10411 /* Reset access-list configuration. */
10412 if (bdistance
->access_list
) {
10413 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10414 bdistance
->access_list
= NULL
;
10416 if (access_list_str
)
10417 bdistance
->access_list
=
10418 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10420 return CMD_SUCCESS
;
10423 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10424 const char *ip_str
, const char *access_list_str
)
10431 struct bgp_node
*rn
;
10432 struct bgp_distance
*bdistance
;
10434 afi
= bgp_node_afi(vty
);
10435 safi
= bgp_node_safi(vty
);
10437 ret
= str2prefix(ip_str
, &p
);
10439 vty_out(vty
, "Malformed prefix\n");
10440 return CMD_WARNING_CONFIG_FAILED
;
10443 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10444 (struct prefix
*)&p
);
10446 vty_out(vty
, "Can't find specified prefix\n");
10447 return CMD_WARNING_CONFIG_FAILED
;
10450 bdistance
= rn
->info
;
10451 distance
= atoi(distance_str
);
10453 if (bdistance
->distance
!= distance
) {
10454 vty_out(vty
, "Distance does not match configured\n");
10455 return CMD_WARNING_CONFIG_FAILED
;
10458 if (bdistance
->access_list
)
10459 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10460 bgp_distance_free(bdistance
);
10463 bgp_unlock_node(rn
);
10464 bgp_unlock_node(rn
);
10466 return CMD_SUCCESS
;
10469 /* Apply BGP information to distance method. */
10470 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10471 safi_t safi
, struct bgp
*bgp
)
10473 struct bgp_node
*rn
;
10476 struct bgp_distance
*bdistance
;
10477 struct access_list
*alist
;
10478 struct bgp_static
*bgp_static
;
10483 peer
= rinfo
->peer
;
10485 /* Check source address. */
10486 sockunion2hostprefix(&peer
->su
, &q
);
10487 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10489 bdistance
= rn
->info
;
10490 bgp_unlock_node(rn
);
10492 if (bdistance
->access_list
) {
10493 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10495 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10496 return bdistance
->distance
;
10498 return bdistance
->distance
;
10501 /* Backdoor check. */
10502 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10504 bgp_static
= rn
->info
;
10505 bgp_unlock_node(rn
);
10507 if (bgp_static
->backdoor
) {
10508 if (bgp
->distance_local
[afi
][safi
])
10509 return bgp
->distance_local
[afi
][safi
];
10511 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10515 if (peer
->sort
== BGP_PEER_EBGP
) {
10516 if (bgp
->distance_ebgp
[afi
][safi
])
10517 return bgp
->distance_ebgp
[afi
][safi
];
10518 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10520 if (bgp
->distance_ibgp
[afi
][safi
])
10521 return bgp
->distance_ibgp
[afi
][safi
];
10522 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10526 DEFUN (bgp_distance
,
10528 "distance bgp (1-255) (1-255) (1-255)",
10529 "Define an administrative distance\n"
10531 "Distance for routes external to the AS\n"
10532 "Distance for routes internal to the AS\n"
10533 "Distance for local routes\n")
10535 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10536 int idx_number
= 2;
10537 int idx_number_2
= 3;
10538 int idx_number_3
= 4;
10542 afi
= bgp_node_afi(vty
);
10543 safi
= bgp_node_safi(vty
);
10545 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10546 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10547 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10548 return CMD_SUCCESS
;
10551 DEFUN (no_bgp_distance
,
10552 no_bgp_distance_cmd
,
10553 "no distance bgp [(1-255) (1-255) (1-255)]",
10555 "Define an administrative distance\n"
10557 "Distance for routes external to the AS\n"
10558 "Distance for routes internal to the AS\n"
10559 "Distance for local routes\n")
10561 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10565 afi
= bgp_node_afi(vty
);
10566 safi
= bgp_node_safi(vty
);
10568 bgp
->distance_ebgp
[afi
][safi
] = 0;
10569 bgp
->distance_ibgp
[afi
][safi
] = 0;
10570 bgp
->distance_local
[afi
][safi
] = 0;
10571 return CMD_SUCCESS
;
10575 DEFUN (bgp_distance_source
,
10576 bgp_distance_source_cmd
,
10577 "distance (1-255) A.B.C.D/M",
10578 "Define an administrative distance\n"
10579 "Administrative distance\n"
10580 "IP source prefix\n")
10582 int idx_number
= 1;
10583 int idx_ipv4_prefixlen
= 2;
10584 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10585 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10586 return CMD_SUCCESS
;
10589 DEFUN (no_bgp_distance_source
,
10590 no_bgp_distance_source_cmd
,
10591 "no distance (1-255) A.B.C.D/M",
10593 "Define an administrative distance\n"
10594 "Administrative distance\n"
10595 "IP source prefix\n")
10597 int idx_number
= 2;
10598 int idx_ipv4_prefixlen
= 3;
10599 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10600 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10601 return CMD_SUCCESS
;
10604 DEFUN (bgp_distance_source_access_list
,
10605 bgp_distance_source_access_list_cmd
,
10606 "distance (1-255) A.B.C.D/M WORD",
10607 "Define an administrative distance\n"
10608 "Administrative distance\n"
10609 "IP source prefix\n"
10610 "Access list name\n")
10612 int idx_number
= 1;
10613 int idx_ipv4_prefixlen
= 2;
10615 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10616 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10617 return CMD_SUCCESS
;
10620 DEFUN (no_bgp_distance_source_access_list
,
10621 no_bgp_distance_source_access_list_cmd
,
10622 "no distance (1-255) A.B.C.D/M WORD",
10624 "Define an administrative distance\n"
10625 "Administrative distance\n"
10626 "IP source prefix\n"
10627 "Access list name\n")
10629 int idx_number
= 2;
10630 int idx_ipv4_prefixlen
= 3;
10632 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10633 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10634 return CMD_SUCCESS
;
10637 DEFUN (ipv6_bgp_distance_source
,
10638 ipv6_bgp_distance_source_cmd
,
10639 "distance (1-255) X:X::X:X/M",
10640 "Define an administrative distance\n"
10641 "Administrative distance\n"
10642 "IP source prefix\n")
10644 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10645 return CMD_SUCCESS
;
10648 DEFUN (no_ipv6_bgp_distance_source
,
10649 no_ipv6_bgp_distance_source_cmd
,
10650 "no distance (1-255) X:X::X:X/M",
10652 "Define an administrative distance\n"
10653 "Administrative distance\n"
10654 "IP source prefix\n")
10656 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10657 return CMD_SUCCESS
;
10660 DEFUN (ipv6_bgp_distance_source_access_list
,
10661 ipv6_bgp_distance_source_access_list_cmd
,
10662 "distance (1-255) X:X::X:X/M WORD",
10663 "Define an administrative distance\n"
10664 "Administrative distance\n"
10665 "IP source prefix\n"
10666 "Access list name\n")
10668 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10669 return CMD_SUCCESS
;
10672 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10673 no_ipv6_bgp_distance_source_access_list_cmd
,
10674 "no distance (1-255) X:X::X:X/M WORD",
10676 "Define an administrative distance\n"
10677 "Administrative distance\n"
10678 "IP source prefix\n"
10679 "Access list name\n")
10681 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10682 return CMD_SUCCESS
;
10685 DEFUN (bgp_damp_set
,
10687 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10688 "BGP Specific commands\n"
10689 "Enable route-flap dampening\n"
10690 "Half-life time for the penalty\n"
10691 "Value to start reusing a route\n"
10692 "Value to start suppressing a route\n"
10693 "Maximum duration to suppress a stable route\n")
10695 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10696 int idx_half_life
= 2;
10698 int idx_suppress
= 4;
10699 int idx_max_suppress
= 5;
10700 int half
= DEFAULT_HALF_LIFE
* 60;
10701 int reuse
= DEFAULT_REUSE
;
10702 int suppress
= DEFAULT_SUPPRESS
;
10703 int max
= 4 * half
;
10706 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10707 reuse
= atoi(argv
[idx_reuse
]->arg
);
10708 suppress
= atoi(argv
[idx_suppress
]->arg
);
10709 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10710 } else if (argc
== 3) {
10711 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10715 if (suppress
< reuse
) {
10717 "Suppress value cannot be less than reuse value \n");
10721 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10722 reuse
, suppress
, max
);
10725 DEFUN (bgp_damp_unset
,
10726 bgp_damp_unset_cmd
,
10727 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10729 "BGP Specific commands\n"
10730 "Enable route-flap dampening\n"
10731 "Half-life time for the penalty\n"
10732 "Value to start reusing a route\n"
10733 "Value to start suppressing a route\n"
10734 "Maximum duration to suppress a stable route\n")
10736 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10737 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10740 /* Display specified route of BGP table. */
10741 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10742 const char *ip_str
, afi_t afi
, safi_t safi
,
10743 struct prefix_rd
*prd
, int prefix_check
)
10746 struct prefix match
;
10747 struct bgp_node
*rn
;
10748 struct bgp_node
*rm
;
10749 struct bgp_info
*ri
;
10750 struct bgp_info
*ri_temp
;
10752 struct bgp_table
*table
;
10754 /* BGP structure lookup. */
10756 bgp
= bgp_lookup_by_name(view_name
);
10758 vty_out(vty
, "%% Can't find BGP instance %s\n",
10760 return CMD_WARNING
;
10763 bgp
= bgp_get_default();
10765 vty_out(vty
, "%% No BGP process is configured\n");
10766 return CMD_WARNING
;
10770 /* Check IP address argument. */
10771 ret
= str2prefix(ip_str
, &match
);
10773 vty_out(vty
, "%% address is malformed\n");
10774 return CMD_WARNING
;
10777 match
.family
= afi2family(afi
);
10779 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10780 || (safi
== SAFI_EVPN
)) {
10781 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10782 rn
= bgp_route_next(rn
)) {
10783 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10786 if ((table
= rn
->info
) != NULL
)
10787 if ((rm
= bgp_node_match(table
, &match
))
10791 == match
.prefixlen
) {
10799 bgp_damp_info_free(
10809 bgp_unlock_node(rm
);
10813 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10816 || rn
->p
.prefixlen
== match
.prefixlen
) {
10819 if (ri
->extra
&& ri
->extra
->damp_info
) {
10820 ri_temp
= ri
->next
;
10821 bgp_damp_info_free(
10822 ri
->extra
->damp_info
,
10830 bgp_unlock_node(rn
);
10834 return CMD_SUCCESS
;
10837 DEFUN (clear_ip_bgp_dampening
,
10838 clear_ip_bgp_dampening_cmd
,
10839 "clear ip bgp dampening",
10843 "Clear route flap dampening information\n")
10845 bgp_damp_info_clean();
10846 return CMD_SUCCESS
;
10849 DEFUN (clear_ip_bgp_dampening_prefix
,
10850 clear_ip_bgp_dampening_prefix_cmd
,
10851 "clear ip bgp dampening A.B.C.D/M",
10855 "Clear route flap dampening information\n"
10858 int idx_ipv4_prefixlen
= 4;
10859 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10860 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
10863 DEFUN (clear_ip_bgp_dampening_address
,
10864 clear_ip_bgp_dampening_address_cmd
,
10865 "clear ip bgp dampening A.B.C.D",
10869 "Clear route flap dampening information\n"
10870 "Network to clear damping information\n")
10873 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
10874 SAFI_UNICAST
, NULL
, 0);
10877 DEFUN (clear_ip_bgp_dampening_address_mask
,
10878 clear_ip_bgp_dampening_address_mask_cmd
,
10879 "clear ip bgp dampening A.B.C.D A.B.C.D",
10883 "Clear route flap dampening information\n"
10884 "Network to clear damping information\n"
10888 int idx_ipv4_2
= 5;
10890 char prefix_str
[BUFSIZ
];
10892 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
10895 vty_out(vty
, "%% Inconsistent address and mask\n");
10896 return CMD_WARNING
;
10899 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
10903 /* also used for encap safi */
10904 static int bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
10905 afi_t afi
, safi_t safi
, int *write
)
10907 struct bgp_node
*prn
;
10908 struct bgp_node
*rn
;
10909 struct bgp_table
*table
;
10911 struct prefix_rd
*prd
;
10912 struct bgp_static
*bgp_static
;
10913 mpls_label_t label
;
10914 char buf
[SU_ADDRSTRLEN
];
10915 char rdbuf
[RD_ADDRSTRLEN
];
10917 /* Network configuration. */
10918 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10919 prn
= bgp_route_next(prn
))
10920 if ((table
= prn
->info
) != NULL
)
10921 for (rn
= bgp_table_top(table
); rn
;
10922 rn
= bgp_route_next(rn
))
10923 if ((bgp_static
= rn
->info
) != NULL
) {
10925 prd
= (struct prefix_rd
*)&prn
->p
;
10927 /* "address-family" display. */
10928 bgp_config_write_family_header(
10929 vty
, afi
, safi
, write
);
10931 /* "network" configuration display. */
10932 prefix_rd2str(prd
, rdbuf
,
10934 label
= decode_label(
10935 &bgp_static
->label
);
10937 vty_out(vty
, " network %s/%d rd %s",
10938 inet_ntop(p
->family
,
10941 p
->prefixlen
, rdbuf
);
10942 if (safi
== SAFI_MPLS_VPN
)
10943 vty_out(vty
, " label %u",
10946 if (bgp_static
->rmap
.name
)
10947 vty_out(vty
, " route-map %s",
10948 bgp_static
->rmap
.name
);
10950 if (bgp_static
->backdoor
)
10954 vty_out(vty
, "\n");
10959 static int bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
10960 afi_t afi
, safi_t safi
, int *write
)
10962 struct bgp_node
*prn
;
10963 struct bgp_node
*rn
;
10964 struct bgp_table
*table
;
10966 struct prefix_rd
*prd
;
10967 struct bgp_static
*bgp_static
;
10968 char buf
[PREFIX_STRLEN
];
10969 char buf2
[SU_ADDRSTRLEN
];
10970 char rdbuf
[RD_ADDRSTRLEN
];
10972 /* Network configuration. */
10973 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10974 prn
= bgp_route_next(prn
))
10975 if ((table
= prn
->info
) != NULL
)
10976 for (rn
= bgp_table_top(table
); rn
;
10977 rn
= bgp_route_next(rn
))
10978 if ((bgp_static
= rn
->info
) != NULL
) {
10979 char *macrouter
= NULL
;
10982 if (bgp_static
->router_mac
)
10983 macrouter
= prefix_mac2str(
10984 bgp_static
->router_mac
,
10986 if (bgp_static
->eth_s_id
)
10988 bgp_static
->eth_s_id
);
10990 prd
= (struct prefix_rd
*)&prn
->p
;
10992 /* "address-family" display. */
10993 bgp_config_write_family_header(
10994 vty
, afi
, safi
, write
);
10996 /* "network" configuration display. */
10997 prefix_rd2str(prd
, rdbuf
,
11001 &bgp_static
->igpnexthop
, buf2
,
11004 prefix2str(p
, buf
, sizeof(buf
)),
11006 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
11013 esi
, buf2
, macrouter
);
11014 vty_out(vty
, "\n");
11016 XFREE(MTYPE_TMP
, macrouter
);
11018 XFREE(MTYPE_TMP
, esi
);
11023 /* Configuration of static route announcement and aggregate
11025 int bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11026 safi_t safi
, int *write
)
11028 struct bgp_node
*rn
;
11030 struct bgp_static
*bgp_static
;
11031 struct bgp_aggregate
*bgp_aggregate
;
11032 char buf
[SU_ADDRSTRLEN
];
11034 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
11035 return bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
, write
);
11037 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
11038 return bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
,
11041 /* Network configuration. */
11042 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11043 rn
= bgp_route_next(rn
))
11044 if ((bgp_static
= rn
->info
) != NULL
) {
11047 /* "address-family" display. */
11048 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11050 /* "network" configuration display. */
11051 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11052 && afi
== AFI_IP
) {
11053 u_int32_t destination
;
11054 struct in_addr netmask
;
11056 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11057 masklen2ip(p
->prefixlen
, &netmask
);
11058 vty_out(vty
, " network %s",
11059 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11062 if ((IN_CLASSC(destination
)
11063 && p
->prefixlen
== 24)
11064 || (IN_CLASSB(destination
)
11065 && p
->prefixlen
== 16)
11066 || (IN_CLASSA(destination
)
11067 && p
->prefixlen
== 8)
11068 || p
->u
.prefix4
.s_addr
== 0) {
11069 /* Natural mask is not display. */
11071 vty_out(vty
, " mask %s",
11072 inet_ntoa(netmask
));
11074 vty_out(vty
, " network %s/%d",
11075 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11080 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11081 vty_out(vty
, " label-index %u",
11082 bgp_static
->label_index
);
11084 if (bgp_static
->rmap
.name
)
11085 vty_out(vty
, " route-map %s",
11086 bgp_static
->rmap
.name
);
11088 if (bgp_static
->backdoor
)
11089 vty_out(vty
, " backdoor");
11092 vty_out(vty
, "\n");
11095 /* Aggregate-address configuration. */
11096 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11097 rn
= bgp_route_next(rn
))
11098 if ((bgp_aggregate
= rn
->info
) != NULL
) {
11101 /* "address-family" display. */
11102 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11104 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11105 && afi
== AFI_IP
) {
11106 struct in_addr netmask
;
11108 masklen2ip(p
->prefixlen
, &netmask
);
11109 vty_out(vty
, " aggregate-address %s %s",
11110 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11112 inet_ntoa(netmask
));
11114 vty_out(vty
, " aggregate-address %s/%d",
11115 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11120 if (bgp_aggregate
->as_set
)
11121 vty_out(vty
, " as-set");
11123 if (bgp_aggregate
->summary_only
)
11124 vty_out(vty
, " summary-only");
11126 vty_out(vty
, "\n");
11132 int bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11133 safi_t safi
, int *write
)
11135 struct bgp_node
*rn
;
11136 struct bgp_distance
*bdistance
;
11138 /* Distance configuration. */
11139 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11140 && bgp
->distance_local
[afi
][safi
]
11141 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11142 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11143 || bgp
->distance_local
[afi
][safi
]
11144 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11145 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11146 vty_out(vty
, " distance bgp %d %d %d\n",
11147 bgp
->distance_ebgp
[afi
][safi
],
11148 bgp
->distance_ibgp
[afi
][safi
],
11149 bgp
->distance_local
[afi
][safi
]);
11152 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11153 rn
= bgp_route_next(rn
))
11154 if ((bdistance
= rn
->info
) != NULL
) {
11155 char buf
[PREFIX_STRLEN
];
11157 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11158 vty_out(vty
, " distance %d %s %s\n",
11159 bdistance
->distance
,
11160 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11161 bdistance
->access_list
? bdistance
->access_list
11168 /* Allocate routing table structure and install commands. */
11169 void bgp_route_init(void)
11174 /* Init BGP distance table. */
11175 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11176 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
11177 bgp_distance_table
[afi
][safi
] =
11178 bgp_table_init(afi
, safi
);
11180 /* IPv4 BGP commands. */
11181 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11182 install_element(BGP_NODE
, &bgp_network_cmd
);
11183 install_element(BGP_NODE
, &bgp_network_mask_cmd
);
11184 install_element(BGP_NODE
, &bgp_network_mask_natural_cmd
);
11185 install_element(BGP_NODE
, &bgp_network_route_map_cmd
);
11186 install_element(BGP_NODE
, &bgp_network_mask_route_map_cmd
);
11187 install_element(BGP_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11188 install_element(BGP_NODE
, &bgp_network_backdoor_cmd
);
11189 install_element(BGP_NODE
, &bgp_network_mask_backdoor_cmd
);
11190 install_element(BGP_NODE
, &bgp_network_mask_natural_backdoor_cmd
);
11191 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11192 install_element(BGP_NODE
, &no_bgp_network_cmd
);
11193 install_element(BGP_NODE
, &no_bgp_network_mask_cmd
);
11194 install_element(BGP_NODE
, &no_bgp_network_mask_natural_cmd
);
11196 install_element(BGP_NODE
, &aggregate_address_cmd
);
11197 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11198 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11199 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11201 /* IPv4 unicast configuration. */
11202 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11203 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11204 install_element(BGP_IPV4_NODE
, &bgp_network_mask_cmd
);
11205 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_cmd
);
11206 install_element(BGP_IPV4_NODE
, &bgp_network_route_map_cmd
);
11207 install_element(BGP_IPV4_NODE
, &bgp_network_mask_route_map_cmd
);
11208 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11209 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_cmd
);
11210 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_route_map_cmd
);
11211 install_element(BGP_IPV4_NODE
, &no_bgp_network_label_index_cmd
);
11212 install_element(BGP_IPV4_NODE
,
11213 &no_bgp_network_label_index_route_map_cmd
);
11214 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11215 install_element(BGP_IPV4_NODE
, &no_bgp_network_cmd
);
11216 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_cmd
);
11217 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_natural_cmd
);
11219 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11220 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11221 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11222 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11224 /* IPv4 multicast configuration. */
11225 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11226 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11227 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_cmd
);
11228 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_natural_cmd
);
11229 install_element(BGP_IPV4M_NODE
, &bgp_network_route_map_cmd
);
11230 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_route_map_cmd
);
11231 install_element(BGP_IPV4M_NODE
,
11232 &bgp_network_mask_natural_route_map_cmd
);
11233 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11234 install_element(BGP_IPV4M_NODE
, &no_bgp_network_cmd
);
11235 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_cmd
);
11236 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_natural_cmd
);
11237 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11238 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11239 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11240 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11242 /* IPv4 labeled-unicast configuration. */
11243 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11244 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11245 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11246 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11248 install_element(VIEW_NODE
,
11249 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11250 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11251 install_element(VIEW_NODE
,
11252 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11253 #ifdef KEEP_OLD_VPN_COMMANDS
11254 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11255 #endif /* KEEP_OLD_VPN_COMMANDS */
11256 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11257 install_element(VIEW_NODE
,
11258 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11260 /* BGP dampening clear commands */
11261 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11262 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11264 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11265 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11268 install_element(ENABLE_NODE
,
11269 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11270 #ifdef KEEP_OLD_VPN_COMMANDS
11271 install_element(ENABLE_NODE
,
11272 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11273 #endif /* KEEP_OLD_VPN_COMMANDS */
11275 /* New config IPv6 BGP commands. */
11276 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11277 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11278 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_route_map_cmd
);
11279 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11280 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_cmd
);
11281 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_label_index_cmd
);
11282 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_label_index_cmd
);
11283 install_element(BGP_IPV6_NODE
,
11284 &ipv6_bgp_network_label_index_route_map_cmd
);
11285 install_element(BGP_IPV6_NODE
,
11286 &no_ipv6_bgp_network_label_index_route_map_cmd
);
11288 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11289 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11291 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11292 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_network_cmd
);
11294 install_element(BGP_IPV6L_NODE
, &bgp_table_map_cmd
);
11295 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
11296 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_route_map_cmd
);
11297 install_element(BGP_IPV6L_NODE
, &no_bgp_table_map_cmd
);
11298 install_element(BGP_IPV6L_NODE
, &no_ipv6_bgp_network_cmd
);
11300 install_element(BGP_NODE
, &bgp_distance_cmd
);
11301 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11302 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11303 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11304 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11305 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11306 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11307 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11308 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11309 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11310 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11311 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11312 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11313 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11314 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11315 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11316 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11317 install_element(BGP_IPV4M_NODE
,
11318 &no_bgp_distance_source_access_list_cmd
);
11319 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11320 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11321 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11322 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11323 install_element(BGP_IPV6_NODE
,
11324 &ipv6_bgp_distance_source_access_list_cmd
);
11325 install_element(BGP_IPV6_NODE
,
11326 &no_ipv6_bgp_distance_source_access_list_cmd
);
11327 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11328 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11329 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11330 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11331 install_element(BGP_IPV6M_NODE
,
11332 &ipv6_bgp_distance_source_access_list_cmd
);
11333 install_element(BGP_IPV6M_NODE
,
11334 &no_ipv6_bgp_distance_source_access_list_cmd
);
11336 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11337 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11338 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11339 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11341 /* IPv4 Multicast Mode */
11342 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11343 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11345 /* Large Communities */
11346 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11347 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11350 void bgp_route_finish(void)
11355 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11356 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
11357 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11358 bgp_distance_table
[afi
][safi
] = NULL
;