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
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
78 #include "bgpd/bgp_pbr.h"
80 #ifndef VTYSH_EXTRACT_PL
81 #include "bgpd/bgp_route_clippy.c"
84 /* Extern from bgp_dump.c */
85 extern const char *bgp_origin_str
[];
86 extern const char *bgp_origin_long_str
[];
89 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
90 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
91 static const struct message bgp_pmsi_tnltype_str
[] = {
92 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
93 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
94 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
95 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
96 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
97 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
98 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
99 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
103 #define VRFID_NONE_STR "-"
105 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
106 safi_t safi
, struct prefix
*p
,
107 struct prefix_rd
*prd
)
110 struct bgp_node
*prn
= NULL
;
116 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
117 || (safi
== SAFI_EVPN
)) {
118 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
120 if (prn
->info
== NULL
)
121 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
123 bgp_unlock_node(prn
);
127 rn
= bgp_node_get(table
, p
);
129 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
130 || (safi
== SAFI_EVPN
))
136 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
137 safi_t safi
, struct prefix
*p
,
138 struct prefix_rd
*prd
)
141 struct bgp_node
*prn
= NULL
;
146 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
147 || (safi
== SAFI_EVPN
)) {
148 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
152 if (prn
->info
== NULL
) {
153 bgp_unlock_node(prn
);
160 rn
= bgp_node_lookup(table
, p
);
165 /* Allocate bgp_info_extra */
166 static struct bgp_info_extra
*bgp_info_extra_new(void)
168 struct bgp_info_extra
*new;
169 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
170 new->label
[0] = MPLS_INVALID_LABEL
;
175 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
177 struct bgp_info_extra
*e
;
179 if (!extra
|| !*extra
)
184 bgp_damp_info_free(e
->damp_info
, 0);
188 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
191 bgp_unlock_node((struct bgp_node
*)bi
->net
);
193 bgp_info_unlock(e
->parent
);
198 bgp_unlock(e
->bgp_orig
);
199 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
204 /* Get bgp_info extra information for the given bgp_info, lazy allocated
207 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
210 ri
->extra
= bgp_info_extra_new();
214 /* Allocate new bgp info structure. */
215 struct bgp_info
*bgp_info_new(void)
217 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
220 /* Free bgp route information. */
221 static void bgp_info_free(struct bgp_info
*binfo
)
224 bgp_attr_unintern(&binfo
->attr
);
226 bgp_unlink_nexthop(binfo
);
227 bgp_info_extra_free(&binfo
->extra
);
228 bgp_info_mpath_free(&binfo
->mpath
);
230 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
232 XFREE(MTYPE_BGP_ROUTE
, binfo
);
235 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
241 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
243 assert(binfo
&& binfo
->lock
> 0);
246 if (binfo
->lock
== 0) {
248 zlog_debug ("%s: unlocked and freeing", __func__
);
249 zlog_backtrace (LOG_DEBUG
);
251 bgp_info_free(binfo
);
256 if (binfo
->lock
== 1)
258 zlog_debug ("%s: unlocked to 1", __func__
);
259 zlog_backtrace (LOG_DEBUG
);
266 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
268 struct bgp_info
*top
;
280 peer_lock(ri
->peer
); /* bgp_info peer reference */
283 /* Do the actual removal of info from RIB, for use by bgp_process
284 completion callback *only* */
285 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
288 ri
->next
->prev
= ri
->prev
;
290 ri
->prev
->next
= ri
->next
;
294 bgp_info_mpath_dequeue(ri
);
299 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
301 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
302 /* set of previous already took care of pcount */
303 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
306 /* undo the effects of a previous call to bgp_info_delete; typically
307 called when a route is deleted and then quickly re-added before the
308 deletion has been processed */
309 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
311 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
312 /* unset of previous already took care of pcount */
313 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
316 /* Adjust pcount as required */
317 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
319 struct bgp_table
*table
;
321 assert(rn
&& bgp_node_table(rn
));
322 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
324 table
= bgp_node_table(rn
);
326 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
329 if (!BGP_INFO_COUNTABLE(ri
)
330 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
332 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
334 /* slight hack, but more robust against errors. */
335 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
336 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
339 "%s: Asked to decrement 0 prefix count for peer %s",
340 __func__
, ri
->peer
->host
);
341 zlog_backtrace(LOG_WARNING
);
342 zlog_warn("%s: Please report to Quagga bugzilla",
345 } else if (BGP_INFO_COUNTABLE(ri
)
346 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
347 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
348 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
352 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
354 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
357 /* Set/unset bgp_info flags, adjusting any other state as needed.
358 * This is here primarily to keep prefix-count in check.
360 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
362 SET_FLAG(ri
->flags
, flag
);
364 /* early bath if we know it's not a flag that changes countability state
366 if (!CHECK_FLAG(flag
,
367 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
370 bgp_pcount_adjust(rn
, ri
);
373 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
376 UNSET_FLAG(ri
->flags
, flag
);
378 /* early bath if we know it's not a flag that changes countability state
380 if (!CHECK_FLAG(flag
,
381 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
384 bgp_pcount_adjust(rn
, ri
);
387 /* Get MED value. If MED value is missing and "bgp bestpath
388 missing-as-worst" is specified, treat it as the worst value. */
389 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
391 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
394 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
401 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
403 if (ri
->addpath_rx_id
)
404 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
407 sprintf(buf
, "path %s", ri
->peer
->host
);
410 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
412 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
413 struct bgp_info
*exist
, int *paths_eq
,
414 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
415 char *pfx_buf
, afi_t afi
, safi_t safi
)
417 struct attr
*newattr
, *existattr
;
418 bgp_peer_sort_t new_sort
;
419 bgp_peer_sort_t exist_sort
;
425 uint32_t exist_weight
;
426 uint32_t newm
, existm
;
427 struct in_addr new_id
;
428 struct in_addr exist_id
;
431 int internal_as_route
;
434 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
435 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
437 uint32_t exist_mm_seq
;
444 zlog_debug("%s: new is NULL", pfx_buf
);
449 bgp_info_path_with_addpath_rx_str(new, new_buf
);
453 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
459 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
460 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
461 pfx_buf
, new_buf
, new->flags
, exist_buf
,
466 existattr
= exist
->attr
;
468 /* For EVPN routes, we cannot just go by local vs remote, we have to
469 * look at the MAC mobility sequence number, if present.
471 if (safi
== SAFI_EVPN
) {
472 /* This is an error condition described in RFC 7432 Section
474 * states that in this scenario "the PE MUST alert the operator"
476 * does not state what other action to take. In order to provide
478 * consistency in this scenario we are going to prefer the path
482 if (newattr
->sticky
!= existattr
->sticky
) {
484 prefix2str(&new->net
->p
, pfx_buf
,
486 * PREFIX2STR_BUFFER
);
487 bgp_info_path_with_addpath_rx_str(new, new_buf
);
488 bgp_info_path_with_addpath_rx_str(exist
,
492 if (newattr
->sticky
&& !existattr
->sticky
) {
494 "%s: %s wins over %s due to sticky MAC flag",
495 pfx_buf
, new_buf
, exist_buf
);
499 if (!newattr
->sticky
&& existattr
->sticky
) {
501 "%s: %s loses to %s due to sticky MAC flag",
502 pfx_buf
, new_buf
, exist_buf
);
507 new_mm_seq
= mac_mobility_seqnum(newattr
);
508 exist_mm_seq
= mac_mobility_seqnum(existattr
);
510 if (new_mm_seq
> exist_mm_seq
) {
513 "%s: %s wins over %s due to MM seq %u > %u",
514 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
519 if (new_mm_seq
< exist_mm_seq
) {
522 "%s: %s loses to %s due to MM seq %u < %u",
523 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
529 /* 1. Weight check. */
530 new_weight
= newattr
->weight
;
531 exist_weight
= existattr
->weight
;
533 if (new_weight
> exist_weight
) {
535 zlog_debug("%s: %s wins over %s due to weight %d > %d",
536 pfx_buf
, new_buf
, exist_buf
, new_weight
,
541 if (new_weight
< exist_weight
) {
543 zlog_debug("%s: %s loses to %s due to weight %d < %d",
544 pfx_buf
, new_buf
, exist_buf
, new_weight
,
549 /* 2. Local preference check. */
550 new_pref
= exist_pref
= bgp
->default_local_pref
;
552 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
553 new_pref
= newattr
->local_pref
;
554 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
555 exist_pref
= existattr
->local_pref
;
557 if (new_pref
> exist_pref
) {
560 "%s: %s wins over %s due to localpref %d > %d",
561 pfx_buf
, new_buf
, exist_buf
, new_pref
,
566 if (new_pref
< exist_pref
) {
569 "%s: %s loses to %s due to localpref %d < %d",
570 pfx_buf
, new_buf
, exist_buf
, new_pref
,
575 /* 3. Local route check. We prefer:
577 * - BGP_ROUTE_AGGREGATE
578 * - BGP_ROUTE_REDISTRIBUTE
580 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
581 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
584 "%s: %s wins over %s due to preferred BGP_ROUTE type",
585 pfx_buf
, new_buf
, exist_buf
);
589 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
590 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
593 "%s: %s loses to %s due to preferred BGP_ROUTE type",
594 pfx_buf
, new_buf
, exist_buf
);
598 /* 4. AS path length check. */
599 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
600 int exist_hops
= aspath_count_hops(existattr
->aspath
);
601 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
603 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
606 aspath_hops
= aspath_count_hops(newattr
->aspath
);
607 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
609 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
612 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
613 pfx_buf
, new_buf
, exist_buf
,
615 (exist_hops
+ exist_confeds
));
619 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
622 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
623 pfx_buf
, new_buf
, exist_buf
,
625 (exist_hops
+ exist_confeds
));
629 int newhops
= aspath_count_hops(newattr
->aspath
);
631 if (newhops
< exist_hops
) {
634 "%s: %s wins over %s due to aspath hopcount %d < %d",
635 pfx_buf
, new_buf
, exist_buf
,
636 newhops
, exist_hops
);
640 if (newhops
> exist_hops
) {
643 "%s: %s loses to %s due to aspath hopcount %d > %d",
644 pfx_buf
, new_buf
, exist_buf
,
645 newhops
, exist_hops
);
651 /* 5. Origin check. */
652 if (newattr
->origin
< existattr
->origin
) {
654 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
655 pfx_buf
, new_buf
, exist_buf
,
656 bgp_origin_long_str
[newattr
->origin
],
657 bgp_origin_long_str
[existattr
->origin
]);
661 if (newattr
->origin
> existattr
->origin
) {
663 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
664 pfx_buf
, new_buf
, exist_buf
,
665 bgp_origin_long_str
[newattr
->origin
],
666 bgp_origin_long_str
[existattr
->origin
]);
671 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
672 && aspath_count_hops(existattr
->aspath
) == 0);
673 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
674 && aspath_count_confeds(existattr
->aspath
) > 0
675 && aspath_count_hops(newattr
->aspath
) == 0
676 && aspath_count_hops(existattr
->aspath
) == 0);
678 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
679 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
680 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
681 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
682 || internal_as_route
) {
683 new_med
= bgp_med_value(new->attr
, bgp
);
684 exist_med
= bgp_med_value(exist
->attr
, bgp
);
686 if (new_med
< exist_med
) {
689 "%s: %s wins over %s due to MED %d < %d",
690 pfx_buf
, new_buf
, exist_buf
, new_med
,
695 if (new_med
> exist_med
) {
698 "%s: %s loses to %s due to MED %d > %d",
699 pfx_buf
, new_buf
, exist_buf
, new_med
,
705 /* 7. Peer type check. */
706 new_sort
= new->peer
->sort
;
707 exist_sort
= exist
->peer
->sort
;
709 if (new_sort
== BGP_PEER_EBGP
710 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
713 "%s: %s wins over %s due to eBGP peer > iBGP peer",
714 pfx_buf
, new_buf
, exist_buf
);
718 if (exist_sort
== BGP_PEER_EBGP
719 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
722 "%s: %s loses to %s due to iBGP peer < eBGP peer",
723 pfx_buf
, new_buf
, exist_buf
);
727 /* 8. IGP metric check. */
731 newm
= new->extra
->igpmetric
;
733 existm
= exist
->extra
->igpmetric
;
738 "%s: %s wins over %s due to IGP metric %d < %d",
739 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
746 "%s: %s loses to %s due to IGP metric %d > %d",
747 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
751 /* 9. Same IGP metric. Compare the cluster list length as
752 representative of IGP hops metric. Rewrite the metric value
753 pair (newm, existm) with the cluster list length. Prefer the
754 path with smaller cluster list length. */
755 if (newm
== existm
) {
756 if (peer_sort(new->peer
) == BGP_PEER_IBGP
757 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
758 && (mpath_cfg
== NULL
760 mpath_cfg
->ibgp_flags
,
761 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
762 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
763 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
768 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
769 pfx_buf
, new_buf
, exist_buf
,
777 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
778 pfx_buf
, new_buf
, exist_buf
,
785 /* 10. confed-external vs. confed-internal */
786 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
787 if (new_sort
== BGP_PEER_CONFED
788 && exist_sort
== BGP_PEER_IBGP
) {
791 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
792 pfx_buf
, new_buf
, exist_buf
);
796 if (exist_sort
== BGP_PEER_CONFED
797 && new_sort
== BGP_PEER_IBGP
) {
800 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
801 pfx_buf
, new_buf
, exist_buf
);
806 /* 11. Maximum path check. */
807 if (newm
== existm
) {
808 /* If one path has a label but the other does not, do not treat
809 * them as equals for multipath
811 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
813 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
816 "%s: %s and %s cannot be multipath, one has a label while the other does not",
817 pfx_buf
, new_buf
, exist_buf
);
818 } else if (bgp_flag_check(bgp
,
819 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
822 * For the two paths, all comparison steps till IGP
824 * have succeeded - including AS_PATH hop count. Since
826 * bestpath as-path multipath-relax' knob is on, we
828 * an exact match of AS_PATH. Thus, mark the paths are
830 * That will trigger both these paths to get into the
838 "%s: %s and %s are equal via multipath-relax",
839 pfx_buf
, new_buf
, exist_buf
);
840 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
841 if (aspath_cmp(new->attr
->aspath
,
842 exist
->attr
->aspath
)) {
847 "%s: %s and %s are equal via matching aspaths",
848 pfx_buf
, new_buf
, exist_buf
);
850 } else if (new->peer
->as
== exist
->peer
->as
) {
855 "%s: %s and %s are equal via same remote-as",
856 pfx_buf
, new_buf
, exist_buf
);
860 * TODO: If unequal cost ibgp multipath is enabled we can
861 * mark the paths as equal here instead of returning
866 "%s: %s wins over %s after IGP metric comparison",
867 pfx_buf
, new_buf
, exist_buf
);
870 "%s: %s loses to %s after IGP metric comparison",
871 pfx_buf
, new_buf
, exist_buf
);
876 /* 12. If both paths are external, prefer the path that was received
877 first (the oldest one). This step minimizes route-flap, since a
878 newer path won't displace an older one, even if it was the
879 preferred route based on the additional decision criteria below. */
880 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
881 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
882 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
885 "%s: %s wins over %s due to oldest external",
886 pfx_buf
, new_buf
, exist_buf
);
890 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
893 "%s: %s loses to %s due to oldest external",
894 pfx_buf
, new_buf
, exist_buf
);
899 /* 13. Router-ID comparision. */
900 /* If one of the paths is "stale", the corresponding peer router-id will
901 * be 0 and would always win over the other path. If originator id is
902 * used for the comparision, it will decide which path is better.
904 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
905 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
907 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
908 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
909 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
911 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
913 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
916 "%s: %s wins over %s due to Router-ID comparison",
917 pfx_buf
, new_buf
, exist_buf
);
921 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
924 "%s: %s loses to %s due to Router-ID comparison",
925 pfx_buf
, new_buf
, exist_buf
);
929 /* 14. Cluster length comparision. */
930 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
931 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
933 if (new_cluster
< exist_cluster
) {
936 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
937 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
942 if (new_cluster
> exist_cluster
) {
945 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
946 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
951 /* 15. Neighbor address comparision. */
952 /* Do this only if neither path is "stale" as stale paths do not have
953 * valid peer information (as the connection may or may not be up).
955 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
958 "%s: %s wins over %s due to latter path being STALE",
959 pfx_buf
, new_buf
, exist_buf
);
963 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
966 "%s: %s loses to %s due to former path being STALE",
967 pfx_buf
, new_buf
, exist_buf
);
971 /* locally configured routes to advertise do not have su_remote */
972 if (new->peer
->su_remote
== NULL
)
974 if (exist
->peer
->su_remote
== NULL
)
977 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
982 "%s: %s loses to %s due to Neighor IP comparison",
983 pfx_buf
, new_buf
, exist_buf
);
990 "%s: %s wins over %s due to Neighor IP comparison",
991 pfx_buf
, new_buf
, exist_buf
);
996 zlog_debug("%s: %s wins over %s due to nothing left to compare",
997 pfx_buf
, new_buf
, exist_buf
);
1002 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1003 * is preferred, or 0 if they are the same (usually will only occur if
1004 * multipath is enabled
1005 * This version is compatible with */
1006 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1007 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1012 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1026 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1027 struct attr
*attr
, afi_t afi
,
1030 struct bgp_filter
*filter
;
1032 filter
= &peer
->filter
[afi
][safi
];
1034 #define FILTER_EXIST_WARN(F, f, filter) \
1035 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1036 zlog_warn("%s: Could not find configured input %s-list %s!", \
1037 peer->host, #f, F##_IN_NAME(filter));
1039 if (DISTRIBUTE_IN_NAME(filter
)) {
1040 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1042 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1046 if (PREFIX_LIST_IN_NAME(filter
)) {
1047 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1049 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1053 if (FILTER_LIST_IN_NAME(filter
)) {
1054 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1056 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1061 return FILTER_PERMIT
;
1062 #undef FILTER_EXIST_WARN
1065 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1066 struct attr
*attr
, afi_t afi
,
1069 struct bgp_filter
*filter
;
1071 filter
= &peer
->filter
[afi
][safi
];
1073 #define FILTER_EXIST_WARN(F, f, filter) \
1074 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1075 zlog_warn("%s: Could not find configured output %s-list %s!", \
1076 peer->host, #f, F##_OUT_NAME(filter));
1078 if (DISTRIBUTE_OUT_NAME(filter
)) {
1079 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1081 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1085 if (PREFIX_LIST_OUT_NAME(filter
)) {
1086 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1088 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1093 if (FILTER_LIST_OUT_NAME(filter
)) {
1094 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1096 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1101 return FILTER_PERMIT
;
1102 #undef FILTER_EXIST_WARN
1105 /* If community attribute includes no_export then return 1. */
1106 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1108 if (attr
->community
) {
1109 /* NO_ADVERTISE check. */
1110 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1113 /* NO_EXPORT check. */
1114 if (peer
->sort
== BGP_PEER_EBGP
1115 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1118 /* NO_EXPORT_SUBCONFED check. */
1119 if (peer
->sort
== BGP_PEER_EBGP
1120 || peer
->sort
== BGP_PEER_CONFED
)
1121 if (community_include(attr
->community
,
1122 COMMUNITY_NO_EXPORT_SUBCONFED
))
1128 /* Route reflection loop check. */
1129 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1131 struct in_addr cluster_id
;
1133 if (attr
->cluster
) {
1134 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1135 cluster_id
= peer
->bgp
->cluster_id
;
1137 cluster_id
= peer
->bgp
->router_id
;
1139 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1145 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1146 struct attr
*attr
, afi_t afi
, safi_t safi
,
1147 const char *rmap_name
)
1149 struct bgp_filter
*filter
;
1150 struct bgp_info info
;
1151 route_map_result_t ret
;
1152 struct route_map
*rmap
= NULL
;
1154 filter
= &peer
->filter
[afi
][safi
];
1156 /* Apply default weight value. */
1157 if (peer
->weight
[afi
][safi
])
1158 attr
->weight
= peer
->weight
[afi
][safi
];
1161 rmap
= route_map_lookup_by_name(rmap_name
);
1166 if (ROUTE_MAP_IN_NAME(filter
)) {
1167 rmap
= ROUTE_MAP_IN(filter
);
1174 /* Route map apply. */
1176 memset(&info
, 0, sizeof(struct bgp_info
));
1177 /* Duplicate current value to new strucutre for modification. */
1181 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1183 /* Apply BGP route map to the attribute. */
1184 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1186 peer
->rmap_type
= 0;
1188 if (ret
== RMAP_DENYMATCH
)
1194 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1195 struct attr
*attr
, afi_t afi
, safi_t safi
,
1196 const char *rmap_name
)
1198 struct bgp_info info
;
1199 route_map_result_t ret
;
1200 struct route_map
*rmap
= NULL
;
1204 * So if we get to this point and have no rmap_name
1205 * we want to just show the output as it currently
1211 /* Apply default weight value. */
1212 if (peer
->weight
[afi
][safi
])
1213 attr
->weight
= peer
->weight
[afi
][safi
];
1215 rmap
= route_map_lookup_by_name(rmap_name
);
1218 * If we have a route map name and we do not find
1219 * the routemap that means we have an implicit
1225 memset(&info
, 0, sizeof(struct bgp_info
));
1226 /* Route map apply. */
1227 /* Duplicate current value to new strucutre for modification. */
1231 rmap_type
= peer
->rmap_type
;
1232 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1234 /* Apply BGP route map to the attribute. */
1235 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1237 peer
->rmap_type
= rmap_type
;
1239 if (ret
== RMAP_DENYMATCH
)
1241 * caller has multiple error paths with bgp_attr_flush()
1248 /* If this is an EBGP peer with remove-private-AS */
1249 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1250 struct peer
*peer
, struct attr
*attr
)
1252 if (peer
->sort
== BGP_PEER_EBGP
1253 && (peer_af_flag_check(peer
, afi
, safi
,
1254 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1255 || peer_af_flag_check(peer
, afi
, safi
,
1256 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1257 || peer_af_flag_check(peer
, afi
, safi
,
1258 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1259 || peer_af_flag_check(peer
, afi
, safi
,
1260 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1261 // Take action on the entire aspath
1262 if (peer_af_flag_check(peer
, afi
, safi
,
1263 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1264 || peer_af_flag_check(peer
, afi
, safi
,
1265 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1266 if (peer_af_flag_check(
1268 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1269 attr
->aspath
= aspath_replace_private_asns(
1270 attr
->aspath
, bgp
->as
);
1272 // The entire aspath consists of private ASNs so create
1274 else if (aspath_private_as_check(attr
->aspath
))
1275 attr
->aspath
= aspath_empty_get();
1277 // There are some public and some private ASNs, remove
1280 attr
->aspath
= aspath_remove_private_asns(
1284 // 'all' was not specified so the entire aspath must be private
1286 // for us to do anything
1287 else if (aspath_private_as_check(attr
->aspath
)) {
1288 if (peer_af_flag_check(
1290 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1291 attr
->aspath
= aspath_replace_private_asns(
1292 attr
->aspath
, bgp
->as
);
1294 attr
->aspath
= aspath_empty_get();
1299 /* If this is an EBGP peer with as-override */
1300 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1301 struct peer
*peer
, struct attr
*attr
)
1303 if (peer
->sort
== BGP_PEER_EBGP
1304 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1305 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1306 attr
->aspath
= aspath_replace_specific_asn(
1307 attr
->aspath
, peer
->as
, bgp
->as
);
1311 void bgp_attr_add_gshut_community(struct attr
*attr
)
1313 struct community
*old
;
1314 struct community
*new;
1315 struct community
*merge
;
1316 struct community
*gshut
;
1318 old
= attr
->community
;
1319 gshut
= community_str2com("graceful-shutdown");
1324 merge
= community_merge(community_dup(old
), gshut
);
1326 if (old
->refcnt
== 0)
1327 community_free(old
);
1329 new = community_uniq_sort(merge
);
1330 community_free(merge
);
1332 new = community_dup(gshut
);
1335 community_free(gshut
);
1336 attr
->community
= new;
1337 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1339 /* When we add the graceful-shutdown community we must also
1340 * lower the local-preference */
1341 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1342 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1346 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1348 if (family
== AF_INET
) {
1349 attr
->nexthop
.s_addr
= 0;
1350 attr
->mp_nexthop_global_in
.s_addr
= 0;
1352 if (family
== AF_INET6
)
1353 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1354 if (family
== AF_EVPN
)
1355 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1358 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1359 struct update_subgroup
*subgrp
, struct prefix
*p
,
1362 struct bgp_filter
*filter
;
1365 struct peer
*onlypeer
;
1367 struct attr
*riattr
;
1368 char buf
[PREFIX_STRLEN
];
1374 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1376 if (DISABLE_BGP_ANNOUNCE
)
1379 afi
= SUBGRP_AFI(subgrp
);
1380 safi
= SUBGRP_SAFI(subgrp
);
1381 peer
= SUBGRP_PEER(subgrp
);
1383 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1384 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1387 filter
= &peer
->filter
[afi
][safi
];
1388 bgp
= SUBGRP_INST(subgrp
);
1389 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1392 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1393 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1394 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1397 * direct and direct_ext type routes originate internally even
1398 * though they can have peer pointers that reference other
1401 prefix2str(p
, buf
, PREFIX_STRLEN
);
1402 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1408 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1409 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1410 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1411 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1413 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1418 /* With addpath we may be asked to TX all kinds of paths so make sure
1420 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1421 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1422 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1426 /* If this is not the bestpath then check to see if there is an enabled
1428 * feature that requires us to advertise it */
1429 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1430 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1435 /* Aggregate-address suppress check. */
1436 if (ri
->extra
&& ri
->extra
->suppress
)
1437 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1442 * If we are doing VRF 2 VRF leaking via the import
1443 * statement, we want to prevent the route going
1444 * off box as that the RT and RD created are localy
1445 * significant and globaly useless.
1447 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1448 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1451 /* If it's labeled safi, make sure the route has a valid label. */
1452 if (safi
== SAFI_LABELED_UNICAST
) {
1453 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1454 if (!bgp_is_valid_label(&label
)) {
1455 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1456 zlog_debug("u%" PRIu64
":s%" PRIu64
1457 " %s/%d is filtered - no label (%p)",
1458 subgrp
->update_group
->id
, subgrp
->id
,
1459 inet_ntop(p
->family
, &p
->u
.prefix
,
1460 buf
, SU_ADDRSTRLEN
),
1461 p
->prefixlen
, &label
);
1466 /* Do not send back route to sender. */
1467 if (onlypeer
&& from
== onlypeer
) {
1471 /* Do not send the default route in the BGP table if the neighbor is
1472 * configured for default-originate */
1473 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1474 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1475 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1477 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1481 /* Transparency check. */
1482 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1483 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1488 /* If community is not disabled check the no-export and local. */
1489 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1490 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1492 "subgrpannouncecheck: community filter check fail");
1496 /* If the attribute has originator-id and it is same as remote
1498 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1499 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1500 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1502 "%s [Update:SEND] %s originator-id is same as "
1505 prefix2str(p
, buf
, sizeof(buf
)));
1509 /* ORF prefix-list filter check */
1510 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1511 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1512 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1513 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1514 if (peer
->orf_plist
[afi
][safi
]) {
1515 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1517 if (bgp_debug_update(NULL
, p
,
1518 subgrp
->update_group
, 0))
1520 "%s [Update:SEND] %s is filtered via ORF",
1528 /* Output filter check. */
1529 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1530 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1531 zlog_debug("%s [Update:SEND] %s is filtered",
1532 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1536 #ifdef BGP_SEND_ASPATH_CHECK
1537 /* AS path loop check. */
1538 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1539 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1541 "%s [Update:SEND] suppress announcement to peer AS %u "
1542 "that is part of AS path.",
1543 onlypeer
->host
, onlypeer
->as
);
1546 #endif /* BGP_SEND_ASPATH_CHECK */
1548 /* If we're a CONFED we need to loop check the CONFED ID too */
1549 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1550 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1551 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1553 "%s [Update:SEND] suppress announcement to peer AS %u"
1555 peer
->host
, bgp
->confed_id
);
1560 /* Route-Reflect check. */
1561 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1566 /* IBGP reflection check. */
1567 if (reflect
&& !samepeer_safe
) {
1568 /* A route from a Client peer. */
1569 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1570 PEER_FLAG_REFLECTOR_CLIENT
)) {
1571 /* Reflect to all the Non-Client peers and also to the
1572 Client peers other than the originator. Originator
1574 is already done. So there is noting to do. */
1575 /* no bgp client-to-client reflection check. */
1576 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1577 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1578 PEER_FLAG_REFLECTOR_CLIENT
))
1581 /* A route from a Non-client peer. Reflect to all other
1583 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1584 PEER_FLAG_REFLECTOR_CLIENT
))
1589 /* For modify attribute, copy it to temporary structure. */
1590 bgp_attr_dup(attr
, riattr
);
1592 /* If local-preference is not set. */
1593 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1594 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1595 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1596 attr
->local_pref
= bgp
->default_local_pref
;
1599 /* If originator-id is not set and the route is to be reflected,
1600 set the originator id */
1602 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1603 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1604 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1607 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1609 if (peer
->sort
== BGP_PEER_EBGP
1610 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1611 if (from
!= bgp
->peer_self
&& !transparent
1612 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1613 PEER_FLAG_MED_UNCHANGED
))
1615 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1618 /* Since the nexthop attribute can vary per peer, it is not explicitly
1620 * in announce check, only certain flags and length (or number of
1622 * -- for IPv6/MP_REACH) are set here in order to guide the update
1624 * code in setting the nexthop(s) on a per peer basis in
1626 * Typically, the source nexthop in the attribute is preserved but in
1628 * scenarios where we know it will always be overwritten, we reset the
1629 * nexthop to "0" in an attempt to achieve better Update packing. An
1630 * example of this is when a prefix from each of 2 IBGP peers needs to
1632 * announced to an EBGP peer (and they have the same attributes barring
1636 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1638 #define NEXTHOP_IS_V6 \
1639 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1640 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1641 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1642 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1644 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1646 * the peer (group) is configured to receive link-local nexthop
1648 * and it is available in the prefix OR we're not reflecting the route
1650 * the peer (group) to whom we're going to announce is on a shared
1652 * and this is either a self-originated route or the peer is EBGP.
1654 if (NEXTHOP_IS_V6
) {
1655 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1656 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1657 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1658 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1659 || (!reflect
&& peer
->shared_network
1660 && (from
== bgp
->peer_self
1661 || peer
->sort
== BGP_PEER_EBGP
))) {
1662 attr
->mp_nexthop_len
=
1663 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1666 /* Clear off link-local nexthop in source, whenever it is not
1668 * ensure more prefixes share the same attribute for
1671 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1672 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1673 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1676 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1677 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1679 /* Route map & unsuppress-map apply. */
1680 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1681 struct bgp_info info
;
1682 struct bgp_info_extra dummy_info_extra
;
1683 struct attr dummy_attr
;
1685 memset(&info
, 0, sizeof(struct bgp_info
));
1690 memcpy(&dummy_info_extra
, ri
->extra
,
1691 sizeof(struct bgp_info_extra
));
1692 info
.extra
= &dummy_info_extra
;
1695 /* don't confuse inbound and outbound setting */
1696 RESET_FLAG(attr
->rmap_change_flags
);
1699 * The route reflector is not allowed to modify the attributes
1700 * of the reflected IBGP routes unless explicitly allowed.
1702 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1703 && !bgp_flag_check(bgp
,
1704 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1705 bgp_attr_dup(&dummy_attr
, attr
);
1706 info
.attr
= &dummy_attr
;
1709 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1711 if (ri
->extra
&& ri
->extra
->suppress
)
1712 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1715 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1718 peer
->rmap_type
= 0;
1720 if (ret
== RMAP_DENYMATCH
) {
1721 bgp_attr_flush(attr
);
1726 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1727 if (peer
->sort
== BGP_PEER_IBGP
1728 || peer
->sort
== BGP_PEER_CONFED
) {
1729 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1730 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1732 bgp_attr_add_gshut_community(attr
);
1736 /* After route-map has been applied, we check to see if the nexthop to
1737 * be carried in the attribute (that is used for the announcement) can
1738 * be cleared off or not. We do this in all cases where we would be
1739 * setting the nexthop to "ourselves". For IPv6, we only need to
1741 * the global nexthop here; the link-local nexthop would have been
1743 * already, and if not, it is required by the update formation code.
1744 * Also see earlier comments in this function.
1747 * If route-map has performed some operation on the nexthop or the peer
1748 * configuration says to pass it unchanged, we cannot reset the nexthop
1749 * here, so only attempt to do it if these aren't true. Note that the
1750 * route-map handler itself might have cleared the nexthop, if for
1752 * it is configured as 'peer-address'.
1754 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1755 riattr
->rmap_change_flags
)
1757 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1758 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1759 /* We can reset the nexthop, if setting (or forcing) it to
1761 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1762 PEER_FLAG_NEXTHOP_SELF
)
1763 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1764 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1766 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1767 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1768 subgroup_announce_reset_nhop(
1769 (peer_cap_enhe(peer
, afi
, safi
)
1773 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1774 /* Can also reset the nexthop if announcing to EBGP, but
1776 * no peer in the subgroup is on a shared subnet.
1777 * Note: 3rd party nexthop currently implemented for
1780 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1782 subgroup_announce_reset_nhop(
1783 (peer_cap_enhe(peer
, afi
, safi
)
1787 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1789 * This flag is used for leaked vpn-vrf routes
1791 int family
= p
->family
;
1793 if (peer_cap_enhe(peer
, afi
, safi
))
1796 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1798 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1799 __func__
, family2str(family
));
1800 subgroup_announce_reset_nhop(family
, attr
);
1803 /* If IPv6/MP and nexthop does not have any override and happens
1805 * be a link-local address, reset it so that we don't pass along
1807 * source's link-local IPv6 address to recipients who may not be
1809 * the same interface.
1811 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1812 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1813 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1820 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1821 struct bgp_maxpaths_cfg
*mpath_cfg
,
1822 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1824 struct bgp_info
*new_select
;
1825 struct bgp_info
*old_select
;
1826 struct bgp_info
*ri
;
1827 struct bgp_info
*ri1
;
1828 struct bgp_info
*ri2
;
1829 struct bgp_info
*nextri
= NULL
;
1830 int paths_eq
, do_mpath
, debug
;
1831 struct list mp_list
;
1832 char pfx_buf
[PREFIX2STR_BUFFER
];
1833 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1835 bgp_mp_list_init(&mp_list
);
1837 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1839 debug
= bgp_debug_bestpath(&rn
->p
);
1842 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1844 /* bgp deterministic-med */
1846 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1848 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1849 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1850 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1852 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1853 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1855 if (BGP_INFO_HOLDDOWN(ri1
))
1857 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1858 if (ri1
->peer
->status
!= Established
)
1863 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1864 if (CHECK_FLAG(ri2
->flags
,
1865 BGP_INFO_DMED_CHECK
))
1867 if (BGP_INFO_HOLDDOWN(ri2
))
1870 && ri2
->peer
!= bgp
->peer_self
1873 PEER_STATUS_NSF_WAIT
))
1874 if (ri2
->peer
->status
1878 if (aspath_cmp_left(ri1
->attr
->aspath
,
1880 || aspath_cmp_left_confed(
1882 ri2
->attr
->aspath
)) {
1883 if (bgp_info_cmp(bgp
, ri2
,
1889 bgp_info_unset_flag(
1891 BGP_INFO_DMED_SELECTED
);
1897 BGP_INFO_DMED_CHECK
);
1901 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1902 bgp_info_set_flag(rn
, new_select
,
1903 BGP_INFO_DMED_SELECTED
);
1906 bgp_info_path_with_addpath_rx_str(new_select
,
1908 zlog_debug("%s: %s is the bestpath from AS %u",
1910 aspath_get_first_as(
1911 new_select
->attr
->aspath
));
1916 /* Check old selected route and new selected route. */
1919 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1921 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1924 if (BGP_INFO_HOLDDOWN(ri
)) {
1925 /* reap REMOVED routes, if needs be
1926 * selected route must stay for a while longer though
1928 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1929 && (ri
!= old_select
))
1930 bgp_info_reap(rn
, ri
);
1933 zlog_debug("%s: ri %p in holddown", __func__
,
1939 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1940 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1941 if (ri
->peer
->status
!= Established
) {
1945 "%s: ri %p non self peer %s not estab state",
1946 __func__
, ri
, ri
->peer
->host
);
1951 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1952 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1953 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1955 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1959 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1961 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1962 debug
, pfx_buf
, afi
, safi
)) {
1967 /* Now that we know which path is the bestpath see if any of the other
1969 * qualify as multipaths
1973 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1975 sprintf(path_buf
, "NONE");
1977 "%s: After path selection, newbest is %s oldbest was %s",
1979 old_select
? old_select
->peer
->host
: "NONE");
1982 if (do_mpath
&& new_select
) {
1983 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1987 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1989 if (ri
== new_select
) {
1992 "%s: %s is the bestpath, add to the multipath list",
1994 bgp_mp_list_add(&mp_list
, ri
);
1998 if (BGP_INFO_HOLDDOWN(ri
))
2001 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2002 && !CHECK_FLAG(ri
->peer
->sflags
,
2003 PEER_STATUS_NSF_WAIT
))
2004 if (ri
->peer
->status
!= Established
)
2007 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2010 "%s: %s has the same nexthop as the bestpath, skip it",
2015 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2016 debug
, pfx_buf
, afi
, safi
);
2021 "%s: %s is equivalent to the bestpath, add to the multipath list",
2023 bgp_mp_list_add(&mp_list
, ri
);
2028 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2029 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2030 bgp_mp_list_clear(&mp_list
);
2032 result
->old
= old_select
;
2033 result
->new = new_select
;
2039 * A new route/change in bestpath of an existing route. Evaluate the path
2040 * for advertisement to the subgroup.
2042 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2043 struct bgp_info
*selected
,
2044 struct bgp_node
*rn
,
2045 uint32_t addpath_tx_id
)
2048 struct peer
*onlypeer
;
2054 afi
= SUBGRP_AFI(subgrp
);
2055 safi
= SUBGRP_SAFI(subgrp
);
2056 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2059 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2060 char buf_prefix
[PREFIX_STRLEN
];
2061 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2062 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2066 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2067 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2068 PEER_STATUS_ORF_WAIT_REFRESH
))
2071 memset(&attr
, 0, sizeof(struct attr
));
2072 /* It's initialized in bgp_announce_check() */
2074 /* Announcement to the subgroup. If the route is filtered withdraw it.
2077 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2078 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2080 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2081 selected
->addpath_tx_id
);
2084 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2086 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2093 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2094 * This is called at the end of route processing.
2096 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2098 struct bgp_info
*ri
;
2100 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2101 if (BGP_INFO_HOLDDOWN(ri
))
2103 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2104 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2109 * Has the route changed from the RIB's perspective? This is invoked only
2110 * if the route selection returns the same best route as earlier - to
2111 * determine if we need to update zebra or not.
2113 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2115 struct bgp_info
*mpinfo
;
2117 /* If this is multipath, check all selected paths for any nexthop
2118 * change or attribute change. Some attribute changes (e.g., community)
2119 * aren't of relevance to the RIB, but we'll update zebra to ensure
2120 * we handle the case of BGP nexthop change. This is the behavior
2121 * when the best path has an attribute change anyway.
2123 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2124 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2128 * If this is multipath, check all selected paths for any nexthop change
2130 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2131 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2132 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2133 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2137 /* Nothing has changed from the RIB's perspective. */
2141 struct bgp_process_queue
{
2143 STAILQ_HEAD(, bgp_node
) pqueue
;
2144 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2146 unsigned int queued
;
2150 * old_select = The old best path
2151 * new_select = the new best path
2153 * if (!old_select && new_select)
2154 * We are sending new information on.
2156 * if (old_select && new_select) {
2157 * if (new_select != old_select)
2158 * We have a new best path send a change
2160 * We've received a update with new attributes that needs
2164 * if (old_select && !new_select)
2165 * We have no eligible route that we can announce or the rn
2168 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2169 afi_t afi
, safi_t safi
)
2171 struct bgp_info
*new_select
;
2172 struct bgp_info
*old_select
;
2173 struct bgp_info_pair old_and_new
;
2174 char pfx_buf
[PREFIX2STR_BUFFER
];
2177 /* Is it end of initial update? (after startup) */
2179 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2180 sizeof(bgp
->update_delay_zebra_resume_time
));
2182 bgp
->main_zebra_update_hold
= 0;
2183 FOREACH_AFI_SAFI (afi
, safi
) {
2184 if (bgp_fibupd_safi(safi
))
2185 bgp_zebra_announce_table(bgp
, afi
, safi
);
2187 bgp
->main_peers_update_hold
= 0;
2189 bgp_start_routeadv(bgp
);
2193 struct prefix
*p
= &rn
->p
;
2195 debug
= bgp_debug_bestpath(&rn
->p
);
2197 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2198 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2199 afi2str(afi
), safi2str(safi
));
2202 /* Best path selection. */
2203 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2205 old_select
= old_and_new
.old
;
2206 new_select
= old_and_new
.new;
2208 /* Do we need to allocate or free labels?
2209 * Right now, since we only deal with per-prefix labels, it is not
2210 * necessary to do this upon changes to best path except if the label
2213 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2216 || bgp_label_index_differs(new_select
, old_select
)
2217 || new_select
->sub_type
!= old_select
->sub_type
) {
2218 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2219 && new_select
->attr
->flag
2221 BGP_ATTR_PREFIX_SID
)
2222 && new_select
->attr
->label_index
2223 != BGP_INVALID_LABEL_INDEX
) {
2226 BGP_NODE_REGISTERED_FOR_LABEL
))
2227 bgp_unregister_for_label(rn
);
2228 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2230 bgp_set_valid_label(&rn
->local_label
);
2232 bgp_register_for_label(rn
, new_select
);
2234 } else if (CHECK_FLAG(rn
->flags
,
2235 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2236 bgp_unregister_for_label(rn
);
2238 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2239 bgp_unregister_for_label(rn
);
2243 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2245 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2246 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2247 old_select
, new_select
);
2250 /* If best route remains the same and this is not due to user-initiated
2251 * clear, see exactly what needs to be done.
2253 if (old_select
&& old_select
== new_select
2254 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2255 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2256 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2257 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2259 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2260 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2262 if (bgp_fibupd_safi(safi
)
2263 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2265 if (new_select
->type
== ZEBRA_ROUTE_BGP
2266 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2267 || new_select
->sub_type
2268 == BGP_ROUTE_IMPORTED
))
2270 bgp_zebra_announce(rn
, p
, old_select
,
2274 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2275 bgp_zebra_clear_route_change_flags(rn
);
2277 /* If there is a change of interest to peers, reannounce the
2279 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2280 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2281 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2283 /* unicast routes must also be annouced to
2284 * labeled-unicast update-groups */
2285 if (safi
== SAFI_UNICAST
)
2286 group_announce_route(bgp
, afi
,
2287 SAFI_LABELED_UNICAST
, rn
,
2290 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2291 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2294 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2298 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2300 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2302 /* bestpath has changed; bump version */
2303 if (old_select
|| new_select
) {
2304 bgp_bump_version(rn
);
2306 if (!bgp
->t_rmap_def_originate_eval
) {
2310 update_group_refresh_default_originate_route_map
,
2311 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2312 &bgp
->t_rmap_def_originate_eval
);
2317 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2320 zlog_debug("%s: setting SELECTED flag", __func__
);
2321 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2322 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2323 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2327 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2328 if (old_select
!= new_select
) {
2330 vnc_import_bgp_exterior_del_route(bgp
, p
,
2332 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2335 vnc_import_bgp_exterior_add_route(bgp
, p
,
2337 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2343 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2345 /* unicast routes must also be annouced to labeled-unicast update-groups
2347 if (safi
== SAFI_UNICAST
)
2348 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2352 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2353 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2354 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2355 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2356 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2357 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2359 /* if this is an evpn imported type-5 prefix,
2360 * we need to withdraw the route first to clear
2361 * the nh neigh and the RMAC entry.
2364 is_route_parent_evpn(old_select
))
2365 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2367 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2369 /* Withdraw the route from the kernel. */
2370 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2371 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2372 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2373 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2375 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2379 /* advertise/withdraw type-5 routes */
2380 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2381 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2382 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2384 /* apply the route-map */
2385 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2388 ret
= route_map_apply(
2389 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2390 &rn
->p
, RMAP_BGP
, new_select
);
2391 if (ret
== RMAP_MATCH
)
2392 bgp_evpn_advertise_type5_route(
2393 bgp
, &rn
->p
, new_select
->attr
,
2396 bgp_evpn_advertise_type5_route(bgp
,
2402 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2403 (!old_select
->extra
|| !old_select
->extra
->parent
))
2404 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2407 /* Clear any route change flags. */
2408 bgp_zebra_clear_route_change_flags(rn
);
2410 /* Reap old select bgp_info, if it has been removed */
2411 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2412 bgp_info_reap(rn
, old_select
);
2414 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2418 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2420 struct bgp_process_queue
*pqnode
= data
;
2421 struct bgp
*bgp
= pqnode
->bgp
;
2422 struct bgp_table
*table
;
2423 struct bgp_node
*rn
;
2426 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2427 bgp_process_main_one(bgp
, NULL
, 0, 0);
2428 /* should always have dedicated wq call */
2429 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2433 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2434 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2435 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2436 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2437 table
= bgp_node_table(rn
);
2438 /* note, new RNs may be added as part of processing */
2439 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2441 bgp_unlock_node(rn
);
2442 bgp_table_unlock(table
);
2448 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2450 struct bgp_process_queue
*pqnode
= data
;
2452 bgp_unlock(pqnode
->bgp
);
2454 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2457 void bgp_process_queue_init(void)
2459 if (!bm
->process_main_queue
) {
2460 bm
->process_main_queue
=
2461 work_queue_new(bm
->master
, "process_main_queue");
2463 if (!bm
->process_main_queue
) {
2464 zlog_err("%s: Failed to allocate work queue", __func__
);
2469 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2470 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2471 bm
->process_main_queue
->spec
.max_retries
= 0;
2472 bm
->process_main_queue
->spec
.hold
= 50;
2473 /* Use a higher yield value of 50ms for main queue processing */
2474 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2477 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2479 struct bgp_process_queue
*pqnode
;
2481 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2482 sizeof(struct bgp_process_queue
));
2484 /* unlocked in bgp_processq_del */
2485 pqnode
->bgp
= bgp_lock(bgp
);
2486 STAILQ_INIT(&pqnode
->pqueue
);
2491 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2493 #define ARBITRARY_PROCESS_QLEN 10000
2494 struct work_queue
*wq
= bm
->process_main_queue
;
2495 struct bgp_process_queue
*pqnode
;
2496 int pqnode_reuse
= 0;
2498 /* already scheduled for processing? */
2499 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2505 /* Add route nodes to an existing work queue item until reaching the
2506 limit only if is from the same BGP view and it's not an EOIU marker
2508 if (work_queue_item_count(wq
)) {
2509 struct work_queue_item
*item
= work_queue_last_item(wq
);
2510 pqnode
= item
->data
;
2512 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2513 || pqnode
->bgp
!= bgp
2514 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2515 pqnode
= bgp_processq_alloc(bgp
);
2519 pqnode
= bgp_processq_alloc(bgp
);
2520 /* all unlocked in bgp_process_wq */
2521 bgp_table_lock(bgp_node_table(rn
));
2523 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2526 /* can't be enqueued twice */
2527 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2528 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2532 work_queue_add(wq
, pqnode
);
2537 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2539 struct bgp_process_queue
*pqnode
;
2541 if (bm
->process_main_queue
== NULL
)
2544 pqnode
= bgp_processq_alloc(bgp
);
2546 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2547 work_queue_add(bm
->process_main_queue
, pqnode
);
2550 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2554 peer
= THREAD_ARG(thread
);
2555 peer
->t_pmax_restart
= NULL
;
2557 if (bgp_debug_neighbor_events(peer
))
2559 "%s Maximum-prefix restart timer expired, restore peering",
2562 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2563 zlog_debug("%s: %s peer_clear failed",
2564 __PRETTY_FUNCTION__
, peer
->host
);
2569 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2573 iana_safi_t pkt_safi
;
2575 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2578 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2579 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2580 PEER_STATUS_PREFIX_LIMIT
)
2585 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2587 afi_safi_print(afi
, safi
), peer
->host
,
2588 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2589 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2591 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2592 PEER_FLAG_MAX_PREFIX_WARNING
))
2595 /* Convert AFI, SAFI to values for packet. */
2596 pkt_afi
= afi_int2iana(afi
);
2597 pkt_safi
= safi_int2iana(safi
);
2601 ndata
[0] = (pkt_afi
>> 8);
2603 ndata
[2] = pkt_safi
;
2604 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2605 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2606 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2607 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2609 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2610 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2611 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2615 /* Dynamic peers will just close their connection. */
2616 if (peer_dynamic_neighbor(peer
))
2619 /* restart timer start */
2620 if (peer
->pmax_restart
[afi
][safi
]) {
2621 peer
->v_pmax_restart
=
2622 peer
->pmax_restart
[afi
][safi
] * 60;
2624 if (bgp_debug_neighbor_events(peer
))
2626 "%s Maximum-prefix restart timer started for %d secs",
2627 peer
->host
, peer
->v_pmax_restart
);
2629 BGP_TIMER_ON(peer
->t_pmax_restart
,
2630 bgp_maximum_prefix_restart_timer
,
2631 peer
->v_pmax_restart
);
2636 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2637 PEER_STATUS_PREFIX_LIMIT
);
2639 if (peer
->pcount
[afi
][safi
]
2640 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2641 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2642 PEER_STATUS_PREFIX_THRESHOLD
)
2647 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2648 afi_safi_print(afi
, safi
), peer
->host
,
2649 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2650 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2651 PEER_STATUS_PREFIX_THRESHOLD
);
2653 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2654 PEER_STATUS_PREFIX_THRESHOLD
);
2658 /* Unconditionally remove the route from the RIB, without taking
2659 * damping into consideration (eg, because the session went down)
2661 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2662 afi_t afi
, safi_t safi
)
2664 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2666 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2667 bgp_info_delete(rn
, ri
); /* keep historical info */
2669 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2672 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2673 struct peer
*peer
, afi_t afi
, safi_t safi
,
2674 struct prefix_rd
*prd
)
2676 /* apply dampening, if result is suppressed, we'll be retaining
2677 * the bgp_info in the RIB for historical reference.
2679 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2680 && peer
->sort
== BGP_PEER_EBGP
)
2681 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2682 == BGP_DAMP_SUPPRESSED
) {
2683 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2689 if (safi
== SAFI_MPLS_VPN
) {
2690 struct bgp_node
*prn
= NULL
;
2691 struct bgp_table
*table
= NULL
;
2693 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2694 (struct prefix
*)prd
);
2696 table
= (struct bgp_table
*)(prn
->info
);
2698 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2699 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2701 bgp_unlock_node(prn
);
2703 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2704 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2706 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2707 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2713 /* If this is an EVPN route, process for un-import. */
2714 if (safi
== SAFI_EVPN
)
2715 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2717 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2720 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2721 struct peer
*peer
, struct attr
*attr
,
2722 struct bgp_node
*rn
)
2724 struct bgp_info
*new;
2726 /* Make new BGP info. */
2727 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2729 new->instance
= instance
;
2730 new->sub_type
= sub_type
;
2733 new->uptime
= bgp_clock();
2735 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2739 static void overlay_index_update(struct attr
*attr
,
2740 struct eth_segment_id
*eth_s_id
,
2741 union gw_addr
*gw_ip
)
2746 if (eth_s_id
== NULL
) {
2747 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2748 sizeof(struct eth_segment_id
));
2750 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2751 sizeof(struct eth_segment_id
));
2753 if (gw_ip
== NULL
) {
2754 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2756 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2757 sizeof(union gw_addr
));
2761 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2762 struct eth_segment_id
*eth_s_id
,
2763 union gw_addr
*gw_ip
)
2765 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2766 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2769 if (afi
!= AFI_L2VPN
)
2772 memset(&temp
, 0, 16);
2773 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2774 info_gw_ip
= (union gw_addr
*)&temp
;
2775 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2778 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2779 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2782 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2784 info_gw_ip_remote
= gw_ip
;
2785 if (eth_s_id
== NULL
)
2786 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2788 info_eth_s_id_remote
= eth_s_id
;
2789 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2791 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2792 sizeof(struct eth_segment_id
));
2795 /* Check if received nexthop is valid or not. */
2796 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2801 /* Only validated for unicast and multicast currently. */
2802 /* Also valid for EVPN where the nexthop is an IP address. */
2803 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2806 /* If NEXT_HOP is present, validate it. */
2807 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2808 if (attr
->nexthop
.s_addr
== 0
2809 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2810 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2814 /* If MP_NEXTHOP is present, validate it. */
2815 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2816 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2817 * it is not an IPv6 link-local address.
2819 if (attr
->mp_nexthop_len
) {
2820 switch (attr
->mp_nexthop_len
) {
2821 case BGP_ATTR_NHLEN_IPV4
:
2822 case BGP_ATTR_NHLEN_VPNV4
:
2823 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2824 || IPV4_CLASS_DE(ntohl(
2825 attr
->mp_nexthop_global_in
.s_addr
))
2826 || bgp_nexthop_self(bgp
,
2827 attr
->mp_nexthop_global_in
));
2830 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2831 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2832 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2833 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2834 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2835 || IN6_IS_ADDR_MULTICAST(
2836 &attr
->mp_nexthop_global
));
2848 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2849 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2850 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2851 uint32_t num_labels
, int soft_reconfig
,
2852 struct bgp_route_evpn
*evpn
)
2855 int aspath_loop_count
= 0;
2856 struct bgp_node
*rn
;
2858 struct attr new_attr
;
2859 struct attr
*attr_new
;
2860 struct bgp_info
*ri
;
2861 struct bgp_info
*new;
2862 struct bgp_info_extra
*extra
;
2864 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2866 int do_loop_check
= 1;
2867 int has_valid_label
= 0;
2869 int vnc_implicit_withdraw
= 0;
2873 memset(&new_attr
, 0, sizeof(struct attr
));
2874 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2875 new_attr
.label
= MPLS_INVALID_LABEL
;
2878 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2879 /* TODO: Check to see if we can get rid of "is_valid_label" */
2880 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2881 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2883 has_valid_label
= bgp_is_valid_label(label
);
2885 /* When peer's soft reconfiguration enabled. Record input packet in
2888 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2889 && peer
!= bgp
->peer_self
)
2890 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2892 /* Check previously received route. */
2893 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2894 if (ri
->peer
== peer
&& ri
->type
== type
2895 && ri
->sub_type
== sub_type
2896 && ri
->addpath_rx_id
== addpath_id
)
2899 /* AS path local-as loop check. */
2900 if (peer
->change_local_as
) {
2901 if (peer
->allowas_in
[afi
][safi
])
2902 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2903 else if (!CHECK_FLAG(peer
->flags
,
2904 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2905 aspath_loop_count
= 1;
2907 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2908 > aspath_loop_count
) {
2909 reason
= "as-path contains our own AS;";
2914 /* If the peer is configured for "allowas-in origin" and the last ASN in
2916 * as-path is our ASN then we do not need to call aspath_loop_check
2918 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2919 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2922 /* AS path loop check. */
2923 if (do_loop_check
) {
2924 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2925 > peer
->allowas_in
[afi
][safi
]
2926 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2927 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2928 > peer
->allowas_in
[afi
][safi
])) {
2929 reason
= "as-path contains our own AS;";
2934 /* Route reflector originator ID check. */
2935 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2936 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2937 reason
= "originator is us;";
2941 /* Route reflector cluster ID check. */
2942 if (bgp_cluster_filter(peer
, attr
)) {
2943 reason
= "reflected from the same cluster;";
2947 /* Apply incoming filter. */
2948 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2953 bgp_attr_dup(&new_attr
, attr
);
2955 /* Apply incoming route-map.
2956 * NB: new_attr may now contain newly allocated values from route-map
2958 * commands, so we need bgp_attr_flush in the error paths, until we
2960 * the attr (which takes over the memory references) */
2961 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2963 reason
= "route-map;";
2964 bgp_attr_flush(&new_attr
);
2968 if (peer
->sort
== BGP_PEER_EBGP
) {
2970 /* If we receive the graceful-shutdown community from an eBGP
2971 * peer we must lower local-preference */
2972 if (new_attr
.community
2973 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2974 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2975 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2977 /* If graceful-shutdown is configured then add the GSHUT
2978 * community to all paths received from eBGP peers */
2979 } else if (bgp_flag_check(peer
->bgp
,
2980 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2981 bgp_attr_add_gshut_community(&new_attr
);
2985 /* next hop check. */
2986 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2987 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2988 reason
= "martian or self next-hop;";
2989 bgp_attr_flush(&new_attr
);
2993 attr_new
= bgp_attr_intern(&new_attr
);
2995 /* If the update is implicit withdraw. */
2997 ri
->uptime
= bgp_clock();
2998 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3000 /* Same attribute comes in. */
3001 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3002 && attrhash_cmp(ri
->attr
, attr_new
)
3003 && (!has_valid_label
3004 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3005 num_labels
* sizeof(mpls_label_t
))
3007 && (overlay_index_equal(
3008 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3009 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3010 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3011 BGP_CONFIG_DAMPENING
)
3012 && peer
->sort
== BGP_PEER_EBGP
3013 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3014 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3015 bgp_debug_rdpfxpath2str(
3016 afi
, safi
, prd
, p
, label
,
3017 num_labels
, addpath_id
? 1 : 0,
3018 addpath_id
, pfx_buf
,
3020 zlog_debug("%s rcvd %s", peer
->host
,
3024 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3025 != BGP_DAMP_SUPPRESSED
) {
3026 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3028 bgp_process(bgp
, rn
, afi
, safi
);
3030 } else /* Duplicate - odd */
3032 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3033 if (!peer
->rcvd_attr_printed
) {
3035 "%s rcvd UPDATE w/ attr: %s",
3037 peer
->rcvd_attr_str
);
3038 peer
->rcvd_attr_printed
= 1;
3041 bgp_debug_rdpfxpath2str(
3042 afi
, safi
, prd
, p
, label
,
3043 num_labels
, addpath_id
? 1 : 0,
3044 addpath_id
, pfx_buf
,
3047 "%s rcvd %s...duplicate ignored",
3048 peer
->host
, pfx_buf
);
3051 /* graceful restart STALE flag unset. */
3052 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3053 bgp_info_unset_flag(rn
, ri
,
3055 bgp_process(bgp
, rn
, afi
, safi
);
3059 bgp_unlock_node(rn
);
3060 bgp_attr_unintern(&attr_new
);
3065 /* Withdraw/Announce before we fully processed the withdraw */
3066 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3067 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3068 bgp_debug_rdpfxpath2str(
3069 afi
, safi
, prd
, p
, label
, num_labels
,
3070 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3073 "%s rcvd %s, flapped quicker than processing",
3074 peer
->host
, pfx_buf
);
3077 bgp_info_restore(rn
, ri
);
3080 /* Received Logging. */
3081 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3082 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3083 num_labels
, addpath_id
? 1 : 0,
3084 addpath_id
, pfx_buf
,
3086 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3089 /* graceful restart STALE flag unset. */
3090 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3091 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3093 /* The attribute is changed. */
3094 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3096 /* implicit withdraw, decrement aggregate and pcount here.
3097 * only if update is accepted, they'll increment below.
3099 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3101 /* Update bgp route dampening information. */
3102 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3103 && peer
->sort
== BGP_PEER_EBGP
) {
3104 /* This is implicit withdraw so we should update
3107 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3108 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3111 if (safi
== SAFI_MPLS_VPN
) {
3112 struct bgp_node
*prn
= NULL
;
3113 struct bgp_table
*table
= NULL
;
3115 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3116 (struct prefix
*)prd
);
3118 table
= (struct bgp_table
*)(prn
->info
);
3120 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3121 bgp
, prd
, table
, p
, ri
);
3123 bgp_unlock_node(prn
);
3125 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3126 && (safi
== SAFI_UNICAST
)) {
3127 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3129 * Implicit withdraw case.
3131 ++vnc_implicit_withdraw
;
3132 vnc_import_bgp_del_route(bgp
, p
, ri
);
3133 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3138 /* Special handling for EVPN update of an existing route. If the
3139 * extended community attribute has changed, we need to
3141 * the route using its existing extended community. It will be
3142 * subsequently processed for import with the new extended
3145 if (safi
== SAFI_EVPN
&& !same_attr
) {
3147 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3149 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3152 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3153 attr_new
->ecommunity
);
3155 if (bgp_debug_update(peer
, p
, NULL
, 1))
3157 "Change in EXT-COMM, existing %s new %s",
3159 ri
->attr
->ecommunity
),
3161 attr_new
->ecommunity
));
3162 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3168 /* Update to new attribute. */
3169 bgp_attr_unintern(&ri
->attr
);
3170 ri
->attr
= attr_new
;
3172 /* Update MPLS label */
3173 if (has_valid_label
) {
3174 extra
= bgp_info_extra_get(ri
);
3175 memcpy(&extra
->label
, label
,
3176 num_labels
* sizeof(mpls_label_t
));
3177 extra
->num_labels
= num_labels
;
3178 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3179 bgp_set_valid_label(&extra
->label
[0]);
3183 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3184 && (safi
== SAFI_UNICAST
)) {
3185 if (vnc_implicit_withdraw
) {
3187 * Add back the route with its new attributes
3189 * The route is still selected, until the route
3191 * queued by bgp_process actually runs. We have
3193 * update to the VNC side immediately to avoid
3195 * configuration changes (e.g., route-map
3197 * trigger re-importation of the entire RIB.
3199 vnc_import_bgp_add_route(bgp
, p
, ri
);
3200 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3204 /* Update Overlay Index */
3205 if (afi
== AFI_L2VPN
) {
3206 overlay_index_update(
3207 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3208 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3211 /* Update bgp route dampening information. */
3212 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3213 && peer
->sort
== BGP_PEER_EBGP
) {
3214 /* Now we do normal update dampening. */
3215 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3216 if (ret
== BGP_DAMP_SUPPRESSED
) {
3217 bgp_unlock_node(rn
);
3222 /* Nexthop reachability check - for unicast and
3223 * labeled-unicast.. */
3224 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3225 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3226 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3227 && !CHECK_FLAG(peer
->flags
,
3228 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3230 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3235 struct bgp
*bgp_nexthop
= bgp
;
3237 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3238 bgp_nexthop
= ri
->extra
->bgp_orig
;
3240 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3241 ri
, NULL
, connected
)
3242 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3243 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3245 if (BGP_DEBUG(nht
, NHT
)) {
3246 char buf1
[INET6_ADDRSTRLEN
];
3248 (const void *)&attr_new
3250 buf1
, INET6_ADDRSTRLEN
);
3251 zlog_debug("%s(%s): NH unresolved",
3252 __FUNCTION__
, buf1
);
3254 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3257 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3260 if (safi
== SAFI_MPLS_VPN
) {
3261 struct bgp_node
*prn
= NULL
;
3262 struct bgp_table
*table
= NULL
;
3264 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3265 (struct prefix
*)prd
);
3267 table
= (struct bgp_table
*)(prn
->info
);
3269 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3270 bgp
, prd
, table
, p
, ri
);
3272 bgp_unlock_node(prn
);
3276 /* If this is an EVPN route and some attribute has changed,
3278 * route for import. If the extended community has changed, we
3280 * have done the un-import earlier and the import would result
3282 * route getting injected into appropriate L2 VNIs. If it is
3284 * some other attribute change, the import will result in
3286 * the attributes for the route in the VNI(s).
3288 if (safi
== SAFI_EVPN
&& !same_attr
)
3289 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3291 /* Process change. */
3292 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3294 bgp_process(bgp
, rn
, afi
, safi
);
3295 bgp_unlock_node(rn
);
3297 if (SAFI_UNICAST
== safi
3298 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3299 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3301 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3303 if ((SAFI_MPLS_VPN
== safi
)
3304 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3306 vpn_leak_to_vrf_update(bgp
, ri
);
3310 if (SAFI_MPLS_VPN
== safi
) {
3311 mpls_label_t label_decoded
= decode_label(label
);
3313 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3314 type
, sub_type
, &label_decoded
);
3316 if (SAFI_ENCAP
== safi
) {
3317 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3318 type
, sub_type
, NULL
);
3323 } // End of implicit withdraw
3325 /* Received Logging. */
3326 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3327 if (!peer
->rcvd_attr_printed
) {
3328 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3329 peer
->rcvd_attr_str
);
3330 peer
->rcvd_attr_printed
= 1;
3333 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3334 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3336 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3339 /* Make new BGP info. */
3340 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3342 /* Update MPLS label */
3343 if (has_valid_label
) {
3344 extra
= bgp_info_extra_get(new);
3345 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3346 extra
->num_labels
= num_labels
;
3347 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3348 bgp_set_valid_label(&extra
->label
[0]);
3351 /* Update Overlay Index */
3352 if (afi
== AFI_L2VPN
) {
3353 overlay_index_update(new->attr
,
3354 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3355 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3357 /* Nexthop reachability check. */
3358 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3359 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3360 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3361 && !CHECK_FLAG(peer
->flags
,
3362 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3363 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3368 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3369 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3370 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3372 if (BGP_DEBUG(nht
, NHT
)) {
3373 char buf1
[INET6_ADDRSTRLEN
];
3375 (const void *)&attr_new
->nexthop
,
3376 buf1
, INET6_ADDRSTRLEN
);
3377 zlog_debug("%s(%s): NH unresolved",
3378 __FUNCTION__
, buf1
);
3380 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3383 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3386 new->addpath_rx_id
= addpath_id
;
3388 /* Increment prefix */
3389 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3391 /* Register new BGP information. */
3392 bgp_info_add(rn
, new);
3394 /* route_node_get lock */
3395 bgp_unlock_node(rn
);
3398 if (safi
== SAFI_MPLS_VPN
) {
3399 struct bgp_node
*prn
= NULL
;
3400 struct bgp_table
*table
= NULL
;
3402 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3404 table
= (struct bgp_table
*)(prn
->info
);
3406 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3407 bgp
, prd
, table
, p
, new);
3409 bgp_unlock_node(prn
);
3413 /* If maximum prefix count is configured and current prefix
3415 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3418 /* If this is an EVPN route, process for import. */
3419 if (safi
== SAFI_EVPN
)
3420 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3422 /* Process change. */
3423 bgp_process(bgp
, rn
, afi
, safi
);
3425 if (SAFI_UNICAST
== safi
3426 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3427 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3428 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3430 if ((SAFI_MPLS_VPN
== safi
)
3431 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3433 vpn_leak_to_vrf_update(bgp
, new);
3436 if (SAFI_MPLS_VPN
== safi
) {
3437 mpls_label_t label_decoded
= decode_label(label
);
3439 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3440 sub_type
, &label_decoded
);
3442 if (SAFI_ENCAP
== safi
) {
3443 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3450 /* This BGP update is filtered. Log the reason then update BGP
3453 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3454 if (!peer
->rcvd_attr_printed
) {
3455 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3456 peer
->rcvd_attr_str
);
3457 peer
->rcvd_attr_printed
= 1;
3460 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3461 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3463 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3464 peer
->host
, pfx_buf
, reason
);
3468 /* If this is an EVPN route, un-import it as it is now filtered.
3470 if (safi
== SAFI_EVPN
)
3471 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3473 if (SAFI_UNICAST
== safi
3474 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3475 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3477 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3479 if ((SAFI_MPLS_VPN
== safi
)
3480 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3482 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3485 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3488 bgp_unlock_node(rn
);
3492 * Filtered update is treated as an implicit withdrawal (see
3494 * a few lines above)
3496 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3497 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3505 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3506 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3507 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3508 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3511 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3512 struct bgp_node
*rn
;
3513 struct bgp_info
*ri
;
3516 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3517 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3525 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3527 /* If peer is soft reconfiguration enabled. Record input packet for
3528 * further calculation.
3530 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3531 * routes that are filtered. This tanks out Quagga RS pretty badly due
3533 * the iteration over all RS clients.
3534 * Since we need to remove the entry from adj_in anyway, do that first
3536 * if there was no entry, we don't need to do anything more.
3538 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3539 && peer
!= bgp
->peer_self
)
3540 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3541 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3542 bgp_debug_rdpfxpath2str(
3543 afi
, safi
, prd
, p
, label
, num_labels
,
3544 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3547 "%s withdrawing route %s not in adj-in",
3548 peer
->host
, pfx_buf
);
3550 bgp_unlock_node(rn
);
3554 /* Lookup withdrawn route. */
3555 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3556 if (ri
->peer
== peer
&& ri
->type
== type
3557 && ri
->sub_type
== sub_type
3558 && ri
->addpath_rx_id
== addpath_id
)
3562 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3563 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3564 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3566 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3570 /* Withdraw specified route from routing table. */
3571 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3572 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3573 if (SAFI_UNICAST
== safi
3574 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3575 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3576 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3578 if ((SAFI_MPLS_VPN
== safi
)
3579 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3581 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3583 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3584 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3585 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3587 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3590 /* Unlock bgp_node_get() lock. */
3591 bgp_unlock_node(rn
);
3596 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3599 struct update_subgroup
*subgrp
;
3600 subgrp
= peer_subgroup(peer
, afi
, safi
);
3601 subgroup_default_originate(subgrp
, withdraw
);
3606 * bgp_stop_announce_route_timer
3608 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3610 if (!paf
->t_announce_route
)
3613 THREAD_TIMER_OFF(paf
->t_announce_route
);
3617 * bgp_announce_route_timer_expired
3619 * Callback that is invoked when the route announcement timer for a
3622 static int bgp_announce_route_timer_expired(struct thread
*t
)
3624 struct peer_af
*paf
;
3627 paf
= THREAD_ARG(t
);
3630 if (peer
->status
!= Established
)
3633 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3636 peer_af_announce_route(paf
, 1);
3641 * bgp_announce_route
3643 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3645 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3647 struct peer_af
*paf
;
3648 struct update_subgroup
*subgrp
;
3650 paf
= peer_af_find(peer
, afi
, safi
);
3653 subgrp
= PAF_SUBGRP(paf
);
3656 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3657 * or a refresh has already been triggered.
3659 if (!subgrp
|| paf
->t_announce_route
)
3663 * Start a timer to stagger/delay the announce. This serves
3664 * two purposes - announcement can potentially be combined for
3665 * multiple peers and the announcement doesn't happen in the
3668 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3669 (subgrp
->peer_count
== 1)
3670 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3671 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3672 &paf
->t_announce_route
);
3676 * Announce routes from all AF tables to a peer.
3678 * This should ONLY be called when there is a need to refresh the
3679 * routes to the peer based on a policy change for this peer alone
3680 * or a route refresh request received from the peer.
3681 * The operation will result in splitting the peer from its existing
3682 * subgroups and putting it in new subgroups.
3684 void bgp_announce_route_all(struct peer
*peer
)
3689 FOREACH_AFI_SAFI (afi
, safi
)
3690 bgp_announce_route(peer
, afi
, safi
);
3693 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3694 struct bgp_table
*table
,
3695 struct prefix_rd
*prd
)
3698 struct bgp_node
*rn
;
3699 struct bgp_adj_in
*ain
;
3702 table
= peer
->bgp
->rib
[afi
][safi
];
3704 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3705 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3706 if (ain
->peer
!= peer
)
3709 struct bgp_info
*ri
= rn
->info
;
3710 uint32_t num_labels
= 0;
3711 mpls_label_t
*label_pnt
= NULL
;
3713 if (ri
&& ri
->extra
)
3714 num_labels
= ri
->extra
->num_labels
;
3716 label_pnt
= &ri
->extra
->label
[0];
3718 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3719 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3720 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3721 num_labels
, 1, NULL
);
3724 bgp_unlock_node(rn
);
3730 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3732 struct bgp_node
*rn
;
3733 struct bgp_table
*table
;
3735 if (peer
->status
!= Established
)
3738 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3739 && (safi
!= SAFI_EVPN
))
3740 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3742 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3743 rn
= bgp_route_next(rn
))
3744 if ((table
= rn
->info
) != NULL
) {
3745 struct prefix_rd prd
;
3746 prd
.family
= AF_UNSPEC
;
3748 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3750 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3756 struct bgp_clear_node_queue
{
3757 struct bgp_node
*rn
;
3760 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3762 struct bgp_clear_node_queue
*cnq
= data
;
3763 struct bgp_node
*rn
= cnq
->rn
;
3764 struct peer
*peer
= wq
->spec
.data
;
3765 struct bgp_info
*ri
;
3767 afi_t afi
= bgp_node_table(rn
)->afi
;
3768 safi_t safi
= bgp_node_table(rn
)->safi
;
3773 /* It is possible that we have multiple paths for a prefix from a peer
3774 * if that peer is using AddPath.
3776 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3777 if (ri
->peer
!= peer
)
3780 /* graceful restart STALE flag set. */
3781 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3782 && peer
->nsf
[afi
][safi
]
3783 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3784 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3785 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3787 /* If this is an EVPN route, process for
3789 if (safi
== SAFI_EVPN
)
3790 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3792 /* Handle withdraw for VRF route-leaking and L3VPN */
3793 if (SAFI_UNICAST
== safi
3794 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3795 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3796 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3799 if (SAFI_MPLS_VPN
== safi
&&
3800 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3801 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3804 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3810 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3812 struct bgp_clear_node_queue
*cnq
= data
;
3813 struct bgp_node
*rn
= cnq
->rn
;
3814 struct bgp_table
*table
= bgp_node_table(rn
);
3816 bgp_unlock_node(rn
);
3817 bgp_table_unlock(table
);
3818 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3821 static void bgp_clear_node_complete(struct work_queue
*wq
)
3823 struct peer
*peer
= wq
->spec
.data
;
3825 /* Tickle FSM to start moving again */
3826 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3828 peer_unlock(peer
); /* bgp_clear_route */
3831 static void bgp_clear_node_queue_init(struct peer
*peer
)
3833 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3835 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3836 #undef CLEAR_QUEUE_NAME_LEN
3838 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3840 zlog_err("%s: Failed to allocate work queue", __func__
);
3843 peer
->clear_node_queue
->spec
.hold
= 10;
3844 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3845 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3846 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3847 peer
->clear_node_queue
->spec
.max_retries
= 0;
3849 /* we only 'lock' this peer reference when the queue is actually active
3851 peer
->clear_node_queue
->spec
.data
= peer
;
3854 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3855 struct bgp_table
*table
)
3857 struct bgp_node
*rn
;
3858 int force
= bm
->process_main_queue
? 0 : 1;
3861 table
= peer
->bgp
->rib
[afi
][safi
];
3863 /* If still no table => afi/safi isn't configured at all or smth. */
3867 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3868 struct bgp_info
*ri
, *next
;
3869 struct bgp_adj_in
*ain
;
3870 struct bgp_adj_in
*ain_next
;
3872 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3873 * queued for every clearing peer, regardless of whether it is
3874 * relevant to the peer at hand.
3876 * Overview: There are 3 different indices which need to be
3877 * scrubbed, potentially, when a peer is removed:
3879 * 1 peer's routes visible via the RIB (ie accepted routes)
3880 * 2 peer's routes visible by the (optional) peer's adj-in index
3881 * 3 other routes visible by the peer's adj-out index
3883 * 3 there is no hurry in scrubbing, once the struct peer is
3884 * removed from bgp->peer, we could just GC such deleted peer's
3885 * adj-outs at our leisure.
3887 * 1 and 2 must be 'scrubbed' in some way, at least made
3888 * invisible via RIB index before peer session is allowed to be
3889 * brought back up. So one needs to know when such a 'search' is
3894 * - there'd be a single global queue or a single RIB walker
3895 * - rather than tracking which route_nodes still need to be
3896 * examined on a peer basis, we'd track which peers still
3899 * Given that our per-peer prefix-counts now should be reliable,
3900 * this may actually be achievable. It doesn't seem to be a huge
3901 * problem at this time,
3903 * It is possible that we have multiple paths for a prefix from
3905 * if that peer is using AddPath.
3909 ain_next
= ain
->next
;
3911 if (ain
->peer
== peer
) {
3912 bgp_adj_in_remove(rn
, ain
);
3913 bgp_unlock_node(rn
);
3919 for (ri
= rn
->info
; ri
; ri
= next
) {
3921 if (ri
->peer
!= peer
)
3925 bgp_info_reap(rn
, ri
);
3927 struct bgp_clear_node_queue
*cnq
;
3929 /* both unlocked in bgp_clear_node_queue_del */
3930 bgp_table_lock(bgp_node_table(rn
));
3933 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3934 sizeof(struct bgp_clear_node_queue
));
3936 work_queue_add(peer
->clear_node_queue
, cnq
);
3944 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3946 struct bgp_node
*rn
;
3947 struct bgp_table
*table
;
3949 if (peer
->clear_node_queue
== NULL
)
3950 bgp_clear_node_queue_init(peer
);
3952 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3953 * Idle until it receives a Clearing_Completed event. This protects
3954 * against peers which flap faster than we can we clear, which could
3957 * a) race with routes from the new session being installed before
3958 * clear_route_node visits the node (to delete the route of that
3960 * b) resource exhaustion, clear_route_node likely leads to an entry
3961 * on the process_main queue. Fast-flapping could cause that queue
3965 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3966 * the unlock will happen upon work-queue completion; other wise, the
3967 * unlock happens at the end of this function.
3969 if (!peer
->clear_node_queue
->thread
)
3972 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3973 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3975 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3976 rn
= bgp_route_next(rn
))
3977 if ((table
= rn
->info
) != NULL
)
3978 bgp_clear_route_table(peer
, afi
, safi
, table
);
3980 /* unlock if no nodes got added to the clear-node-queue. */
3981 if (!peer
->clear_node_queue
->thread
)
3985 void bgp_clear_route_all(struct peer
*peer
)
3990 FOREACH_AFI_SAFI (afi
, safi
)
3991 bgp_clear_route(peer
, afi
, safi
);
3994 rfapiProcessPeerDown(peer
);
3998 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4000 struct bgp_table
*table
;
4001 struct bgp_node
*rn
;
4002 struct bgp_adj_in
*ain
;
4003 struct bgp_adj_in
*ain_next
;
4005 table
= peer
->bgp
->rib
[afi
][safi
];
4007 /* It is possible that we have multiple paths for a prefix from a peer
4008 * if that peer is using AddPath.
4010 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4014 ain_next
= ain
->next
;
4016 if (ain
->peer
== peer
) {
4017 bgp_adj_in_remove(rn
, ain
);
4018 bgp_unlock_node(rn
);
4026 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4028 struct bgp_node
*rn
;
4029 struct bgp_info
*ri
;
4030 struct bgp_table
*table
;
4032 if (safi
== SAFI_MPLS_VPN
) {
4033 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4034 rn
= bgp_route_next(rn
)) {
4035 struct bgp_node
*rm
;
4036 struct bgp_info
*ri
;
4038 /* look for neighbor in tables */
4039 if ((table
= rn
->info
) == NULL
)
4042 for (rm
= bgp_table_top(table
); rm
;
4043 rm
= bgp_route_next(rm
))
4044 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4045 if (ri
->peer
!= peer
)
4047 if (!CHECK_FLAG(ri
->flags
,
4051 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4056 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4057 rn
= bgp_route_next(rn
))
4058 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4059 if (ri
->peer
!= peer
)
4061 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4063 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4069 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4072 struct bgp_node
*rn
;
4073 struct bgp_info
*ri
;
4074 struct bgp_info
*next
;
4076 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4077 for (ri
= rn
->info
; ri
; ri
= next
) {
4079 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4080 && ri
->type
== ZEBRA_ROUTE_BGP
4081 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4082 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4083 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4085 if (bgp_fibupd_safi(safi
))
4086 bgp_zebra_withdraw(&rn
->p
, ri
,
4088 bgp_info_reap(rn
, ri
);
4093 /* Delete all kernel routes. */
4094 void bgp_cleanup_routes(struct bgp
*bgp
)
4097 struct bgp_node
*rn
;
4099 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4100 if (afi
== AFI_L2VPN
)
4102 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4105 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4107 if (afi
!= AFI_L2VPN
) {
4109 safi
= SAFI_MPLS_VPN
;
4110 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4111 rn
= bgp_route_next(rn
)) {
4113 bgp_cleanup_table(bgp
,
4114 (struct bgp_table
*)(rn
->info
),
4116 bgp_table_finish((struct bgp_table
**)&(
4119 bgp_unlock_node(rn
);
4123 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4124 rn
= bgp_route_next(rn
)) {
4126 bgp_cleanup_table(bgp
,
4127 (struct bgp_table
*)(rn
->info
),
4129 bgp_table_finish((struct bgp_table
**)&(
4132 bgp_unlock_node(rn
);
4137 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4138 rn
= bgp_route_next(rn
)) {
4140 bgp_cleanup_table(bgp
,
4141 (struct bgp_table
*)(rn
->info
),
4143 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4145 bgp_unlock_node(rn
);
4150 void bgp_reset(void)
4153 bgp_zclient_reset();
4154 access_list_reset();
4155 prefix_list_reset();
4158 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4160 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4161 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4162 PEER_CAP_ADDPATH_AF_TX_RCV
));
4165 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4167 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4168 struct bgp_nlri
*packet
)
4177 int addpath_encoded
;
4178 uint32_t addpath_id
;
4181 lim
= pnt
+ packet
->length
;
4183 safi
= packet
->safi
;
4185 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4187 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4188 syntactic validity. If the field is syntactically incorrect,
4189 then the Error Subcode is set to Invalid Network Field. */
4190 for (; pnt
< lim
; pnt
+= psize
) {
4191 /* Clear prefix structure. */
4192 memset(&p
, 0, sizeof(struct prefix
));
4194 if (addpath_encoded
) {
4196 /* When packet overflow occurs return immediately. */
4197 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4200 addpath_id
= ntohl(*((uint32_t *)pnt
));
4201 pnt
+= BGP_ADDPATH_ID_LEN
;
4204 /* Fetch prefix length. */
4205 p
.prefixlen
= *pnt
++;
4206 /* afi/safi validity already verified by caller,
4207 * bgp_update_receive */
4208 p
.family
= afi2family(afi
);
4210 /* Prefix length check. */
4211 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4213 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4214 peer
->host
, p
.prefixlen
, packet
->afi
);
4218 /* Packet size overflow check. */
4219 psize
= PSIZE(p
.prefixlen
);
4221 /* When packet overflow occur return immediately. */
4222 if (pnt
+ psize
> lim
) {
4224 "%s [Error] Update packet error (prefix length %d overflows packet)",
4225 peer
->host
, p
.prefixlen
);
4229 /* Defensive coding, double-check the psize fits in a struct
4231 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4233 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4234 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4238 /* Fetch prefix from NLRI packet. */
4239 memcpy(p
.u
.val
, pnt
, psize
);
4241 /* Check address. */
4242 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4243 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4244 /* From RFC4271 Section 6.3:
4246 * If a prefix in the NLRI field is semantically
4248 * (e.g., an unexpected multicast IP address),
4250 * be logged locally, and the prefix SHOULD be
4254 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4255 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4260 /* Check address. */
4261 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4262 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4266 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4268 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4273 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4277 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4279 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4286 /* Normal process. */
4288 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4289 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4290 NULL
, NULL
, 0, 0, NULL
);
4292 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4293 safi
, ZEBRA_ROUTE_BGP
,
4294 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4297 /* Address family configuration mismatch or maximum-prefix count
4303 /* Packet length consistency check. */
4306 "%s [Error] Update packet error (prefix length mismatch with total length)",
4314 static struct bgp_static
*bgp_static_new(void)
4316 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4319 static void bgp_static_free(struct bgp_static
*bgp_static
)
4321 if (bgp_static
->rmap
.name
)
4322 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4323 if (bgp_static
->eth_s_id
)
4324 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4325 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4328 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4329 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4331 struct bgp_node
*rn
;
4332 struct bgp_info
*ri
;
4333 struct bgp_info
*new;
4334 struct bgp_info info
;
4336 struct attr
*attr_new
;
4339 int vnc_implicit_withdraw
= 0;
4346 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4348 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4350 attr
.nexthop
= bgp_static
->igpnexthop
;
4351 attr
.med
= bgp_static
->igpmetric
;
4352 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4354 if (bgp_static
->atomic
)
4355 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4357 /* Store label index, if required. */
4358 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4359 attr
.label_index
= bgp_static
->label_index
;
4360 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4363 /* Apply route-map. */
4364 if (bgp_static
->rmap
.name
) {
4365 struct attr attr_tmp
= attr
;
4367 memset(&info
, 0, sizeof(struct bgp_info
));
4368 info
.peer
= bgp
->peer_self
;
4369 info
.attr
= &attr_tmp
;
4371 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4373 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4375 bgp
->peer_self
->rmap_type
= 0;
4377 if (ret
== RMAP_DENYMATCH
) {
4378 /* Free uninterned attribute. */
4379 bgp_attr_flush(&attr_tmp
);
4381 /* Unintern original. */
4382 aspath_unintern(&attr
.aspath
);
4383 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4387 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4388 bgp_attr_add_gshut_community(&attr_tmp
);
4390 attr_new
= bgp_attr_intern(&attr_tmp
);
4393 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4394 bgp_attr_add_gshut_community(&attr
);
4396 attr_new
= bgp_attr_intern(&attr
);
4399 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4400 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4401 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4405 if (attrhash_cmp(ri
->attr
, attr_new
)
4406 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4407 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4408 bgp_unlock_node(rn
);
4409 bgp_attr_unintern(&attr_new
);
4410 aspath_unintern(&attr
.aspath
);
4413 /* The attribute is changed. */
4414 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4416 /* Rewrite BGP route information. */
4417 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4418 bgp_info_restore(rn
, ri
);
4420 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4422 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4423 && (safi
== SAFI_UNICAST
)) {
4424 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4426 * Implicit withdraw case.
4427 * We have to do this before ri is
4430 ++vnc_implicit_withdraw
;
4431 vnc_import_bgp_del_route(bgp
, p
, ri
);
4432 vnc_import_bgp_exterior_del_route(
4437 bgp_attr_unintern(&ri
->attr
);
4438 ri
->attr
= attr_new
;
4439 ri
->uptime
= bgp_clock();
4441 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4442 && (safi
== SAFI_UNICAST
)) {
4443 if (vnc_implicit_withdraw
) {
4444 vnc_import_bgp_add_route(bgp
, p
, ri
);
4445 vnc_import_bgp_exterior_add_route(
4451 /* Nexthop reachability check. */
4452 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4453 && (safi
== SAFI_UNICAST
4454 || safi
== SAFI_LABELED_UNICAST
)) {
4456 struct bgp
*bgp_nexthop
= bgp
;
4458 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4459 bgp_nexthop
= ri
->extra
->bgp_orig
;
4461 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4463 bgp_info_set_flag(rn
, ri
,
4466 if (BGP_DEBUG(nht
, NHT
)) {
4467 char buf1
[INET6_ADDRSTRLEN
];
4468 inet_ntop(p
->family
,
4472 "%s(%s): Route not in table, not advertising",
4473 __FUNCTION__
, buf1
);
4475 bgp_info_unset_flag(rn
, ri
,
4479 /* Delete the NHT structure if any, if we're
4481 * enabling/disabling import check. We
4482 * deregister the route
4483 * from NHT to avoid overloading NHT and the
4484 * process interaction
4486 bgp_unlink_nexthop(ri
);
4487 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4489 /* Process change. */
4490 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4491 bgp_process(bgp
, rn
, afi
, safi
);
4493 if (SAFI_UNICAST
== safi
4494 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4496 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4497 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4501 bgp_unlock_node(rn
);
4502 aspath_unintern(&attr
.aspath
);
4507 /* Make new BGP info. */
4508 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4510 /* Nexthop reachability check. */
4511 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4512 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4513 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4514 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4516 if (BGP_DEBUG(nht
, NHT
)) {
4517 char buf1
[INET6_ADDRSTRLEN
];
4518 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4521 "%s(%s): Route not in table, not advertising",
4522 __FUNCTION__
, buf1
);
4524 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4527 /* Delete the NHT structure if any, if we're toggling between
4528 * enabling/disabling import check. We deregister the route
4529 * from NHT to avoid overloading NHT and the process interaction
4531 bgp_unlink_nexthop(new);
4533 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4536 /* Aggregate address increment. */
4537 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4539 /* Register new BGP information. */
4540 bgp_info_add(rn
, new);
4542 /* route_node_get lock */
4543 bgp_unlock_node(rn
);
4545 /* Process change. */
4546 bgp_process(bgp
, rn
, afi
, safi
);
4548 if (SAFI_UNICAST
== safi
4549 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4550 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4551 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4554 /* Unintern original. */
4555 aspath_unintern(&attr
.aspath
);
4558 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4561 struct bgp_node
*rn
;
4562 struct bgp_info
*ri
;
4564 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4566 /* Check selected route and self inserted route. */
4567 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4568 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4569 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4572 /* Withdraw static BGP route from routing table. */
4574 if (SAFI_UNICAST
== safi
4575 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4576 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4577 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4579 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4580 bgp_unlink_nexthop(ri
);
4581 bgp_info_delete(rn
, ri
);
4582 bgp_process(bgp
, rn
, afi
, safi
);
4585 /* Unlock bgp_node_lookup. */
4586 bgp_unlock_node(rn
);
4590 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4592 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4593 afi_t afi
, safi_t safi
,
4594 struct prefix_rd
*prd
)
4596 struct bgp_node
*rn
;
4597 struct bgp_info
*ri
;
4599 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4601 /* Check selected route and self inserted route. */
4602 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4603 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4604 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4607 /* Withdraw static BGP route from routing table. */
4610 rfapiProcessWithdraw(
4611 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4612 1); /* Kill, since it is an administrative change */
4614 if (SAFI_MPLS_VPN
== safi
4615 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4616 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4618 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4619 bgp_info_delete(rn
, ri
);
4620 bgp_process(bgp
, rn
, afi
, safi
);
4623 /* Unlock bgp_node_lookup. */
4624 bgp_unlock_node(rn
);
4627 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4628 struct bgp_static
*bgp_static
, afi_t afi
,
4631 struct bgp_node
*rn
;
4632 struct bgp_info
*new;
4633 struct attr
*attr_new
;
4634 struct attr attr
= {0};
4635 struct bgp_info
*ri
;
4637 mpls_label_t label
= 0;
4639 uint32_t num_labels
= 0;
4644 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4646 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4649 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4651 attr
.nexthop
= bgp_static
->igpnexthop
;
4652 attr
.med
= bgp_static
->igpmetric
;
4653 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4655 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4656 || (safi
== SAFI_ENCAP
)) {
4657 if (afi
== AFI_IP
) {
4658 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4659 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4662 if (afi
== AFI_L2VPN
) {
4663 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4665 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4666 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4667 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4668 sizeof(struct in6_addr
));
4669 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4670 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4671 struct bgp_encap_type_vxlan bet
;
4672 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4673 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4674 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4676 if (bgp_static
->router_mac
) {
4677 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4680 /* Apply route-map. */
4681 if (bgp_static
->rmap
.name
) {
4682 struct attr attr_tmp
= attr
;
4683 struct bgp_info info
;
4686 info
.peer
= bgp
->peer_self
;
4687 info
.attr
= &attr_tmp
;
4689 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4691 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4693 bgp
->peer_self
->rmap_type
= 0;
4695 if (ret
== RMAP_DENYMATCH
) {
4696 /* Free uninterned attribute. */
4697 bgp_attr_flush(&attr_tmp
);
4699 /* Unintern original. */
4700 aspath_unintern(&attr
.aspath
);
4701 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4706 attr_new
= bgp_attr_intern(&attr_tmp
);
4708 attr_new
= bgp_attr_intern(&attr
);
4711 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4712 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4713 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4718 memset(&add
, 0, sizeof(union gw_addr
));
4719 if (attrhash_cmp(ri
->attr
, attr_new
)
4720 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4721 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4722 bgp_unlock_node(rn
);
4723 bgp_attr_unintern(&attr_new
);
4724 aspath_unintern(&attr
.aspath
);
4727 /* The attribute is changed. */
4728 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4730 /* Rewrite BGP route information. */
4731 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4732 bgp_info_restore(rn
, ri
);
4734 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4735 bgp_attr_unintern(&ri
->attr
);
4736 ri
->attr
= attr_new
;
4737 ri
->uptime
= bgp_clock();
4740 label
= decode_label(&ri
->extra
->label
[0]);
4743 /* Process change. */
4744 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4745 bgp_process(bgp
, rn
, afi
, safi
);
4747 if (SAFI_MPLS_VPN
== safi
4748 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4749 vpn_leak_to_vrf_update(bgp
, ri
);
4752 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4753 ri
->attr
, afi
, safi
, ri
->type
,
4754 ri
->sub_type
, &label
);
4756 bgp_unlock_node(rn
);
4757 aspath_unintern(&attr
.aspath
);
4763 /* Make new BGP info. */
4764 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4766 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4767 new->extra
= bgp_info_extra_new();
4769 new->extra
->label
[0] = bgp_static
->label
;
4770 new->extra
->num_labels
= num_labels
;
4773 label
= decode_label(&bgp_static
->label
);
4776 /* Aggregate address increment. */
4777 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4779 /* Register new BGP information. */
4780 bgp_info_add(rn
, new);
4781 /* route_node_get lock */
4782 bgp_unlock_node(rn
);
4784 /* Process change. */
4785 bgp_process(bgp
, rn
, afi
, safi
);
4787 if (SAFI_MPLS_VPN
== safi
4788 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4789 vpn_leak_to_vrf_update(bgp
, new);
4792 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4793 safi
, new->type
, new->sub_type
, &label
);
4796 /* Unintern original. */
4797 aspath_unintern(&attr
.aspath
);
4800 /* Configure static BGP network. When user don't run zebra, static
4801 route should be installed as valid. */
4802 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4803 const char *ip_str
, afi_t afi
, safi_t safi
,
4804 const char *rmap
, int backdoor
, uint32_t label_index
)
4806 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4809 struct bgp_static
*bgp_static
;
4810 struct bgp_node
*rn
;
4811 uint8_t need_update
= 0;
4813 /* Convert IP prefix string to struct prefix. */
4814 ret
= str2prefix(ip_str
, &p
);
4816 vty_out(vty
, "%% Malformed prefix\n");
4817 return CMD_WARNING_CONFIG_FAILED
;
4819 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4820 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4821 return CMD_WARNING_CONFIG_FAILED
;
4828 /* Set BGP static route configuration. */
4829 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4832 vty_out(vty
, "%% Can't find static route specified\n");
4833 return CMD_WARNING_CONFIG_FAILED
;
4836 bgp_static
= rn
->info
;
4838 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4839 && (label_index
!= bgp_static
->label_index
)) {
4841 "%% label-index doesn't match static route\n");
4842 return CMD_WARNING_CONFIG_FAILED
;
4845 if ((rmap
&& bgp_static
->rmap
.name
)
4846 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4848 "%% route-map name doesn't match static route\n");
4849 return CMD_WARNING_CONFIG_FAILED
;
4852 /* Update BGP RIB. */
4853 if (!bgp_static
->backdoor
)
4854 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4856 /* Clear configuration. */
4857 bgp_static_free(bgp_static
);
4859 bgp_unlock_node(rn
);
4860 bgp_unlock_node(rn
);
4863 /* Set BGP static route configuration. */
4864 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4867 /* Configuration change. */
4868 bgp_static
= rn
->info
;
4870 /* Label index cannot be changed. */
4871 if (bgp_static
->label_index
!= label_index
) {
4872 vty_out(vty
, "%% cannot change label-index\n");
4873 return CMD_WARNING_CONFIG_FAILED
;
4876 /* Check previous routes are installed into BGP. */
4877 if (bgp_static
->valid
4878 && bgp_static
->backdoor
!= backdoor
)
4881 bgp_static
->backdoor
= backdoor
;
4884 if (bgp_static
->rmap
.name
)
4885 XFREE(MTYPE_ROUTE_MAP_NAME
,
4886 bgp_static
->rmap
.name
);
4887 bgp_static
->rmap
.name
=
4888 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4889 bgp_static
->rmap
.map
=
4890 route_map_lookup_by_name(rmap
);
4892 if (bgp_static
->rmap
.name
)
4893 XFREE(MTYPE_ROUTE_MAP_NAME
,
4894 bgp_static
->rmap
.name
);
4895 bgp_static
->rmap
.name
= NULL
;
4896 bgp_static
->rmap
.map
= NULL
;
4897 bgp_static
->valid
= 0;
4899 bgp_unlock_node(rn
);
4901 /* New configuration. */
4902 bgp_static
= bgp_static_new();
4903 bgp_static
->backdoor
= backdoor
;
4904 bgp_static
->valid
= 0;
4905 bgp_static
->igpmetric
= 0;
4906 bgp_static
->igpnexthop
.s_addr
= 0;
4907 bgp_static
->label_index
= label_index
;
4910 if (bgp_static
->rmap
.name
)
4911 XFREE(MTYPE_ROUTE_MAP_NAME
,
4912 bgp_static
->rmap
.name
);
4913 bgp_static
->rmap
.name
=
4914 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4915 bgp_static
->rmap
.map
=
4916 route_map_lookup_by_name(rmap
);
4918 rn
->info
= bgp_static
;
4921 bgp_static
->valid
= 1;
4923 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4925 if (!bgp_static
->backdoor
)
4926 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4932 void bgp_static_add(struct bgp
*bgp
)
4936 struct bgp_node
*rn
;
4937 struct bgp_node
*rm
;
4938 struct bgp_table
*table
;
4939 struct bgp_static
*bgp_static
;
4941 FOREACH_AFI_SAFI (afi
, safi
)
4942 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4943 rn
= bgp_route_next(rn
)) {
4944 if (rn
->info
== NULL
)
4947 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4948 || (safi
== SAFI_EVPN
)) {
4951 for (rm
= bgp_table_top(table
); rm
;
4952 rm
= bgp_route_next(rm
)) {
4953 bgp_static
= rm
->info
;
4954 bgp_static_update_safi(bgp
, &rm
->p
,
4959 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4965 /* Called from bgp_delete(). Delete all static routes from the BGP
4967 void bgp_static_delete(struct bgp
*bgp
)
4971 struct bgp_node
*rn
;
4972 struct bgp_node
*rm
;
4973 struct bgp_table
*table
;
4974 struct bgp_static
*bgp_static
;
4976 FOREACH_AFI_SAFI (afi
, safi
)
4977 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4978 rn
= bgp_route_next(rn
)) {
4979 if (rn
->info
== NULL
)
4982 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4983 || (safi
== SAFI_EVPN
)) {
4986 for (rm
= bgp_table_top(table
); rm
;
4987 rm
= bgp_route_next(rm
)) {
4988 bgp_static
= rm
->info
;
4989 bgp_static_withdraw_safi(
4990 bgp
, &rm
->p
, AFI_IP
, safi
,
4991 (struct prefix_rd
*)&rn
->p
);
4992 bgp_static_free(bgp_static
);
4994 bgp_unlock_node(rn
);
4997 bgp_static
= rn
->info
;
4998 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4999 bgp_static_free(bgp_static
);
5001 bgp_unlock_node(rn
);
5006 void bgp_static_redo_import_check(struct bgp
*bgp
)
5010 struct bgp_node
*rn
;
5011 struct bgp_node
*rm
;
5012 struct bgp_table
*table
;
5013 struct bgp_static
*bgp_static
;
5015 /* Use this flag to force reprocessing of the route */
5016 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5017 FOREACH_AFI_SAFI (afi
, safi
) {
5018 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5019 rn
= bgp_route_next(rn
)) {
5020 if (rn
->info
== NULL
)
5023 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5024 || (safi
== SAFI_EVPN
)) {
5027 for (rm
= bgp_table_top(table
); rm
;
5028 rm
= bgp_route_next(rm
)) {
5029 bgp_static
= rm
->info
;
5030 bgp_static_update_safi(bgp
, &rm
->p
,
5035 bgp_static
= rn
->info
;
5036 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5041 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5044 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5047 struct bgp_table
*table
;
5048 struct bgp_node
*rn
;
5049 struct bgp_info
*ri
;
5051 table
= bgp
->rib
[afi
][safi
];
5052 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5053 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5054 if (ri
->peer
== bgp
->peer_self
5055 && ((ri
->type
== ZEBRA_ROUTE_BGP
5056 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5057 || (ri
->type
!= ZEBRA_ROUTE_BGP
5059 == BGP_ROUTE_REDISTRIBUTE
))) {
5060 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5062 bgp_unlink_nexthop(ri
);
5063 bgp_info_delete(rn
, ri
);
5064 bgp_process(bgp
, rn
, afi
, safi
);
5071 * Purge all networks and redistributed routes from routing table.
5072 * Invoked upon the instance going down.
5074 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5079 FOREACH_AFI_SAFI (afi
, safi
)
5080 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5085 * Currently this is used to set static routes for VPN and ENCAP.
5086 * I think it can probably be factored with bgp_static_set.
5088 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5089 const char *ip_str
, const char *rd_str
,
5090 const char *label_str
, const char *rmap_str
,
5091 int evpn_type
, const char *esi
, const char *gwip
,
5092 const char *ethtag
, const char *routermac
)
5094 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5097 struct prefix_rd prd
;
5098 struct bgp_node
*prn
;
5099 struct bgp_node
*rn
;
5100 struct bgp_table
*table
;
5101 struct bgp_static
*bgp_static
;
5102 mpls_label_t label
= MPLS_INVALID_LABEL
;
5103 struct prefix gw_ip
;
5105 /* validate ip prefix */
5106 ret
= str2prefix(ip_str
, &p
);
5108 vty_out(vty
, "%% Malformed prefix\n");
5109 return CMD_WARNING_CONFIG_FAILED
;
5112 if ((afi
== AFI_L2VPN
)
5113 && (bgp_build_evpn_prefix(evpn_type
,
5114 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5115 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5116 return CMD_WARNING_CONFIG_FAILED
;
5119 ret
= str2prefix_rd(rd_str
, &prd
);
5121 vty_out(vty
, "%% Malformed rd\n");
5122 return CMD_WARNING_CONFIG_FAILED
;
5126 unsigned long label_val
;
5127 label_val
= strtoul(label_str
, NULL
, 10);
5128 encode_label(label_val
, &label
);
5131 if (safi
== SAFI_EVPN
) {
5132 if (esi
&& str2esi(esi
, NULL
) == 0) {
5133 vty_out(vty
, "%% Malformed ESI\n");
5134 return CMD_WARNING_CONFIG_FAILED
;
5136 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5137 vty_out(vty
, "%% Malformed Router MAC\n");
5138 return CMD_WARNING_CONFIG_FAILED
;
5141 memset(&gw_ip
, 0, sizeof(struct prefix
));
5142 ret
= str2prefix(gwip
, &gw_ip
);
5144 vty_out(vty
, "%% Malformed GatewayIp\n");
5145 return CMD_WARNING_CONFIG_FAILED
;
5147 if ((gw_ip
.family
== AF_INET
5148 && is_evpn_prefix_ipaddr_v6(
5149 (struct prefix_evpn
*)&p
))
5150 || (gw_ip
.family
== AF_INET6
5151 && is_evpn_prefix_ipaddr_v4(
5152 (struct prefix_evpn
*)&p
))) {
5154 "%% GatewayIp family differs with IP prefix\n");
5155 return CMD_WARNING_CONFIG_FAILED
;
5159 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5160 if (prn
->info
== NULL
)
5161 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5163 bgp_unlock_node(prn
);
5166 rn
= bgp_node_get(table
, &p
);
5169 vty_out(vty
, "%% Same network configuration exists\n");
5170 bgp_unlock_node(rn
);
5172 /* New configuration. */
5173 bgp_static
= bgp_static_new();
5174 bgp_static
->backdoor
= 0;
5175 bgp_static
->valid
= 0;
5176 bgp_static
->igpmetric
= 0;
5177 bgp_static
->igpnexthop
.s_addr
= 0;
5178 bgp_static
->label
= label
;
5179 bgp_static
->prd
= prd
;
5182 if (bgp_static
->rmap
.name
)
5183 XFREE(MTYPE_ROUTE_MAP_NAME
,
5184 bgp_static
->rmap
.name
);
5185 bgp_static
->rmap
.name
=
5186 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5187 bgp_static
->rmap
.map
=
5188 route_map_lookup_by_name(rmap_str
);
5191 if (safi
== SAFI_EVPN
) {
5193 bgp_static
->eth_s_id
=
5195 sizeof(struct eth_segment_id
));
5196 str2esi(esi
, bgp_static
->eth_s_id
);
5199 bgp_static
->router_mac
=
5200 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5201 prefix_str2mac(routermac
,
5202 bgp_static
->router_mac
);
5205 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5207 rn
->info
= bgp_static
;
5209 bgp_static
->valid
= 1;
5210 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5216 /* Configure static BGP network. */
5217 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5218 const char *ip_str
, const char *rd_str
,
5219 const char *label_str
, int evpn_type
, const char *esi
,
5220 const char *gwip
, const char *ethtag
)
5222 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5225 struct prefix_rd prd
;
5226 struct bgp_node
*prn
;
5227 struct bgp_node
*rn
;
5228 struct bgp_table
*table
;
5229 struct bgp_static
*bgp_static
;
5230 mpls_label_t label
= MPLS_INVALID_LABEL
;
5232 /* Convert IP prefix string to struct prefix. */
5233 ret
= str2prefix(ip_str
, &p
);
5235 vty_out(vty
, "%% Malformed prefix\n");
5236 return CMD_WARNING_CONFIG_FAILED
;
5239 if ((afi
== AFI_L2VPN
)
5240 && (bgp_build_evpn_prefix(evpn_type
,
5241 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5242 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5243 return CMD_WARNING_CONFIG_FAILED
;
5245 ret
= str2prefix_rd(rd_str
, &prd
);
5247 vty_out(vty
, "%% Malformed rd\n");
5248 return CMD_WARNING_CONFIG_FAILED
;
5252 unsigned long label_val
;
5253 label_val
= strtoul(label_str
, NULL
, 10);
5254 encode_label(label_val
, &label
);
5257 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5258 if (prn
->info
== NULL
)
5259 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5261 bgp_unlock_node(prn
);
5264 rn
= bgp_node_lookup(table
, &p
);
5267 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5269 bgp_static
= rn
->info
;
5270 bgp_static_free(bgp_static
);
5272 bgp_unlock_node(rn
);
5273 bgp_unlock_node(rn
);
5275 vty_out(vty
, "%% Can't find the route\n");
5280 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5281 const char *rmap_name
)
5283 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5284 struct bgp_rmap
*rmap
;
5286 rmap
= &bgp
->table_map
[afi
][safi
];
5289 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5290 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5291 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5294 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5299 if (bgp_fibupd_safi(safi
))
5300 bgp_zebra_announce_table(bgp
, afi
, safi
);
5305 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5306 const char *rmap_name
)
5308 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5309 struct bgp_rmap
*rmap
;
5311 rmap
= &bgp
->table_map
[afi
][safi
];
5313 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5317 if (bgp_fibupd_safi(safi
))
5318 bgp_zebra_announce_table(bgp
, afi
, safi
);
5323 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5326 if (bgp
->table_map
[afi
][safi
].name
) {
5327 vty_out(vty
, " table-map %s\n",
5328 bgp
->table_map
[afi
][safi
].name
);
5332 DEFUN (bgp_table_map
,
5335 "BGP table to RIB route download filter\n"
5336 "Name of the route map\n")
5339 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5340 argv
[idx_word
]->arg
);
5342 DEFUN (no_bgp_table_map
,
5343 no_bgp_table_map_cmd
,
5344 "no table-map WORD",
5346 "BGP table to RIB route download filter\n"
5347 "Name of the route map\n")
5350 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5351 argv
[idx_word
]->arg
);
5357 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5358 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5359 backdoor$backdoor}]",
5361 "Specify a network to announce via BGP\n"
5366 "Route-map to modify the attributes\n"
5367 "Name of the route map\n"
5368 "Label index to associate with the prefix\n"
5369 "Label index value\n"
5370 "Specify a BGP backdoor route\n")
5372 char addr_prefix_str
[BUFSIZ
];
5377 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5380 vty_out(vty
, "%% Inconsistent address and mask\n");
5381 return CMD_WARNING_CONFIG_FAILED
;
5385 return bgp_static_set(
5386 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5387 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5388 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5391 DEFPY(ipv6_bgp_network
,
5392 ipv6_bgp_network_cmd
,
5393 "[no] network X:X::X:X/M$prefix \
5394 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5396 "Specify a network to announce via BGP\n"
5398 "Route-map to modify the attributes\n"
5399 "Name of the route map\n"
5400 "Label index to associate with the prefix\n"
5401 "Label index value\n")
5403 return bgp_static_set(
5404 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5405 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5408 /* Aggreagete address:
5410 advertise-map Set condition to advertise attribute
5411 as-set Generate AS set path information
5412 attribute-map Set attributes of aggregate
5413 route-map Set parameters of aggregate
5414 summary-only Filter more specific routes from updates
5415 suppress-map Conditionally filter more specific routes from updates
5418 struct bgp_aggregate
{
5419 /* Summary-only flag. */
5420 uint8_t summary_only
;
5422 /* AS set generation. */
5425 /* Route-map for aggregated route. */
5426 struct route_map
*map
;
5428 /* Suppress-count. */
5429 unsigned long count
;
5431 /* SAFI configuration. */
5435 static struct bgp_aggregate
*bgp_aggregate_new(void)
5437 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5440 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5442 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5445 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5446 struct community
*comm
)
5448 static struct aspath
*ae
= NULL
;
5451 ae
= aspath_empty();
5456 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5459 if (!community_cmp(ri
->attr
->community
, comm
))
5465 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5466 struct prefix
*p
, uint8_t origin
,
5467 struct aspath
*aspath
,
5468 struct community
*community
,
5469 uint8_t atomic_aggregate
,
5470 struct bgp_aggregate
*aggregate
)
5472 struct bgp_node
*rn
;
5473 struct bgp_table
*table
;
5474 struct bgp_info
*ri
, *new;
5476 table
= bgp
->rib
[afi
][safi
];
5478 rn
= bgp_node_get(table
, p
);
5480 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5481 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5482 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5485 if (aggregate
->count
> 0) {
5487 * If the aggregate information has not changed
5488 * no need to re-install it again.
5490 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5491 bgp_unlock_node(rn
);
5494 aspath_free(aspath
);
5496 community_free(community
);
5502 * Mark the old as unusable
5505 bgp_info_delete(rn
, ri
);
5508 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5509 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5510 community
, aggregate
->as_set
,
5513 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5515 bgp_info_add(rn
, new);
5516 bgp_process(bgp
, rn
, afi
, safi
);
5518 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5519 if (ri
->peer
== bgp
->peer_self
5520 && ri
->type
== ZEBRA_ROUTE_BGP
5521 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5524 /* Withdraw static BGP route from routing table. */
5526 bgp_info_delete(rn
, ri
);
5527 bgp_process(bgp
, rn
, afi
, safi
);
5531 bgp_unlock_node(rn
);
5534 /* Update an aggregate as routes are added/removed from the BGP table */
5535 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5536 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5537 struct bgp_info
*del
,
5538 struct bgp_aggregate
*aggregate
)
5540 struct bgp_table
*table
;
5541 struct bgp_node
*top
;
5542 struct bgp_node
*rn
;
5544 struct aspath
*aspath
= NULL
;
5545 struct aspath
*asmerge
= NULL
;
5546 struct community
*community
= NULL
;
5547 struct community
*commerge
= NULL
;
5548 struct bgp_info
*ri
;
5549 unsigned long match
= 0;
5550 uint8_t atomic_aggregate
= 0;
5552 /* ORIGIN attribute: If at least one route among routes that are
5553 aggregated has ORIGIN with the value INCOMPLETE, then the
5554 aggregated route must have the ORIGIN attribute with the value
5555 INCOMPLETE. Otherwise, if at least one route among routes that
5556 are aggregated has ORIGIN with the value EGP, then the aggregated
5557 route must have the origin attribute with the value EGP. In all
5558 other case the value of the ORIGIN attribute of the aggregated
5559 route is INTERNAL. */
5560 origin
= BGP_ORIGIN_IGP
;
5562 table
= bgp
->rib
[afi
][safi
];
5564 top
= bgp_node_get(table
, p
);
5565 for (rn
= bgp_node_get(table
, p
); rn
;
5566 rn
= bgp_route_next_until(rn
, top
)) {
5567 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5572 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5573 if (BGP_INFO_HOLDDOWN(ri
))
5576 if (del
&& ri
== del
)
5580 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5581 atomic_aggregate
= 1;
5583 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5587 * summary-only aggregate route suppress
5588 * aggregated route announcements.
5590 if (aggregate
->summary_only
) {
5591 (bgp_info_extra_get(ri
))->suppress
++;
5592 bgp_info_set_flag(rn
, ri
,
5593 BGP_INFO_ATTR_CHANGED
);
5600 * If at least one route among routes that are
5601 * aggregated has ORIGIN with the value INCOMPLETE,
5602 * then the aggregated route MUST have the ORIGIN
5603 * attribute with the value INCOMPLETE. Otherwise, if
5604 * at least one route among routes that are aggregated
5605 * has ORIGIN with the value EGP, then the aggregated
5606 * route MUST have the ORIGIN attribute with the value
5609 if (origin
< ri
->attr
->origin
)
5610 origin
= ri
->attr
->origin
;
5612 if (!aggregate
->as_set
)
5616 * as-set aggregate route generate origin, as path,
5617 * and community aggregation.
5620 asmerge
= aspath_aggregate(aspath
,
5622 aspath_free(aspath
);
5625 aspath
= aspath_dup(ri
->attr
->aspath
);
5627 if (!ri
->attr
->community
)
5631 commerge
= community_merge(community
,
5632 ri
->attr
->community
);
5633 community
= community_uniq_sort(commerge
);
5634 community_free(commerge
);
5636 community
= community_dup(ri
->attr
->community
);
5639 bgp_process(bgp
, rn
, afi
, safi
);
5641 bgp_unlock_node(top
);
5646 if (aggregate
->summary_only
)
5647 (bgp_info_extra_get(rinew
))->suppress
++;
5649 if (origin
< rinew
->attr
->origin
)
5650 origin
= rinew
->attr
->origin
;
5652 if (aggregate
->as_set
) {
5654 asmerge
= aspath_aggregate(aspath
,
5655 rinew
->attr
->aspath
);
5656 aspath_free(aspath
);
5659 aspath
= aspath_dup(rinew
->attr
->aspath
);
5661 if (rinew
->attr
->community
) {
5663 commerge
= community_merge(
5665 rinew
->attr
->community
);
5667 community_uniq_sort(commerge
);
5668 community_free(commerge
);
5670 community
= community_dup(
5671 rinew
->attr
->community
);
5676 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5677 atomic_aggregate
, aggregate
);
5679 if (aggregate
->count
== 0) {
5681 aspath_free(aspath
);
5683 community_free(community
);
5687 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5688 safi_t safi
, struct bgp_aggregate
*aggregate
)
5690 struct bgp_table
*table
;
5691 struct bgp_node
*top
;
5692 struct bgp_node
*rn
;
5693 struct bgp_info
*ri
;
5694 unsigned long match
;
5696 table
= bgp
->rib
[afi
][safi
];
5698 /* If routes exists below this node, generate aggregate routes. */
5699 top
= bgp_node_get(table
, p
);
5700 for (rn
= bgp_node_get(table
, p
); rn
;
5701 rn
= bgp_route_next_until(rn
, top
)) {
5702 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5706 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5707 if (BGP_INFO_HOLDDOWN(ri
))
5710 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5713 if (aggregate
->summary_only
&& ri
->extra
) {
5714 ri
->extra
->suppress
--;
5716 if (ri
->extra
->suppress
== 0) {
5718 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5725 /* If this node was suppressed, process the change. */
5727 bgp_process(bgp
, rn
, afi
, safi
);
5729 bgp_unlock_node(top
);
5732 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5733 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5735 struct bgp_node
*child
;
5736 struct bgp_node
*rn
;
5737 struct bgp_aggregate
*aggregate
;
5738 struct bgp_table
*table
;
5740 table
= bgp
->aggregate
[afi
][safi
];
5742 /* No aggregates configured. */
5743 if (bgp_table_top_nolock(table
) == NULL
)
5746 if (p
->prefixlen
== 0)
5749 if (BGP_INFO_HOLDDOWN(ri
))
5752 child
= bgp_node_get(table
, p
);
5754 /* Aggregate address configuration check. */
5755 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5756 if ((aggregate
= rn
->info
) != NULL
5757 && rn
->p
.prefixlen
< p
->prefixlen
) {
5758 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5759 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5762 bgp_unlock_node(child
);
5765 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5766 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5768 struct bgp_node
*child
;
5769 struct bgp_node
*rn
;
5770 struct bgp_aggregate
*aggregate
;
5771 struct bgp_table
*table
;
5773 table
= bgp
->aggregate
[afi
][safi
];
5775 /* No aggregates configured. */
5776 if (bgp_table_top_nolock(table
) == NULL
)
5779 if (p
->prefixlen
== 0)
5782 child
= bgp_node_get(table
, p
);
5784 /* Aggregate address configuration check. */
5785 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5786 if ((aggregate
= rn
->info
) != NULL
5787 && rn
->p
.prefixlen
< p
->prefixlen
) {
5788 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5789 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5792 bgp_unlock_node(child
);
5795 /* Aggregate route attribute. */
5796 #define AGGREGATE_SUMMARY_ONLY 1
5797 #define AGGREGATE_AS_SET 1
5799 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5800 afi_t afi
, safi_t safi
)
5802 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5805 struct bgp_node
*rn
;
5806 struct bgp_aggregate
*aggregate
;
5808 /* Convert string to prefix structure. */
5809 ret
= str2prefix(prefix_str
, &p
);
5811 vty_out(vty
, "Malformed prefix\n");
5812 return CMD_WARNING_CONFIG_FAILED
;
5816 /* Old configuration check. */
5817 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5820 "%% There is no aggregate-address configuration.\n");
5821 return CMD_WARNING_CONFIG_FAILED
;
5824 aggregate
= rn
->info
;
5825 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5826 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5828 /* Unlock aggregate address configuration. */
5830 bgp_aggregate_free(aggregate
);
5831 bgp_unlock_node(rn
);
5832 bgp_unlock_node(rn
);
5837 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5838 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5840 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5843 struct bgp_node
*rn
;
5844 struct bgp_aggregate
*aggregate
;
5846 /* Convert string to prefix structure. */
5847 ret
= str2prefix(prefix_str
, &p
);
5849 vty_out(vty
, "Malformed prefix\n");
5850 return CMD_WARNING_CONFIG_FAILED
;
5854 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5855 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5856 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5858 return CMD_WARNING_CONFIG_FAILED
;
5861 /* Old configuration check. */
5862 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5865 vty_out(vty
, "There is already same aggregate network.\n");
5866 /* try to remove the old entry */
5867 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5869 vty_out(vty
, "Error deleting aggregate.\n");
5870 bgp_unlock_node(rn
);
5871 return CMD_WARNING_CONFIG_FAILED
;
5875 /* Make aggregate address structure. */
5876 aggregate
= bgp_aggregate_new();
5877 aggregate
->summary_only
= summary_only
;
5878 aggregate
->as_set
= as_set
;
5879 aggregate
->safi
= safi
;
5880 rn
->info
= aggregate
;
5882 /* Aggregate address insert into BGP routing table. */
5883 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5888 DEFUN (aggregate_address
,
5889 aggregate_address_cmd
,
5890 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5891 "Configure BGP aggregate entries\n"
5892 "Aggregate prefix\n"
5893 "Generate AS set path information\n"
5894 "Filter more specific routes from updates\n"
5895 "Filter more specific routes from updates\n"
5896 "Generate AS set path information\n")
5899 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5900 char *prefix
= argv
[idx
]->arg
;
5902 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5904 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5905 ? AGGREGATE_SUMMARY_ONLY
5908 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5909 summary_only
, as_set
);
5912 DEFUN (aggregate_address_mask
,
5913 aggregate_address_mask_cmd
,
5914 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5915 "Configure BGP aggregate entries\n"
5916 "Aggregate address\n"
5918 "Generate AS set path information\n"
5919 "Filter more specific routes from updates\n"
5920 "Filter more specific routes from updates\n"
5921 "Generate AS set path information\n")
5924 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5925 char *prefix
= argv
[idx
]->arg
;
5926 char *mask
= argv
[idx
+ 1]->arg
;
5928 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5930 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5931 ? AGGREGATE_SUMMARY_ONLY
5934 char prefix_str
[BUFSIZ
];
5935 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5938 vty_out(vty
, "%% Inconsistent address and mask\n");
5939 return CMD_WARNING_CONFIG_FAILED
;
5942 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5943 summary_only
, as_set
);
5946 DEFUN (no_aggregate_address
,
5947 no_aggregate_address_cmd
,
5948 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5950 "Configure BGP aggregate entries\n"
5951 "Aggregate prefix\n"
5952 "Generate AS set path information\n"
5953 "Filter more specific routes from updates\n"
5954 "Filter more specific routes from updates\n"
5955 "Generate AS set path information\n")
5958 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5959 char *prefix
= argv
[idx
]->arg
;
5960 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5963 DEFUN (no_aggregate_address_mask
,
5964 no_aggregate_address_mask_cmd
,
5965 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5967 "Configure BGP aggregate entries\n"
5968 "Aggregate address\n"
5970 "Generate AS set path information\n"
5971 "Filter more specific routes from updates\n"
5972 "Filter more specific routes from updates\n"
5973 "Generate AS set path information\n")
5976 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5977 char *prefix
= argv
[idx
]->arg
;
5978 char *mask
= argv
[idx
+ 1]->arg
;
5980 char prefix_str
[BUFSIZ
];
5981 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5984 vty_out(vty
, "%% Inconsistent address and mask\n");
5985 return CMD_WARNING_CONFIG_FAILED
;
5988 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5991 DEFUN (ipv6_aggregate_address
,
5992 ipv6_aggregate_address_cmd
,
5993 "aggregate-address X:X::X:X/M [summary-only]",
5994 "Configure BGP aggregate entries\n"
5995 "Aggregate prefix\n"
5996 "Filter more specific routes from updates\n")
5999 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6000 char *prefix
= argv
[idx
]->arg
;
6001 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6002 ? AGGREGATE_SUMMARY_ONLY
6004 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6008 DEFUN (no_ipv6_aggregate_address
,
6009 no_ipv6_aggregate_address_cmd
,
6010 "no aggregate-address X:X::X:X/M [summary-only]",
6012 "Configure BGP aggregate entries\n"
6013 "Aggregate prefix\n"
6014 "Filter more specific routes from updates\n")
6017 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6018 char *prefix
= argv
[idx
]->arg
;
6019 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6022 /* Redistribute route treatment. */
6023 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6024 const union g_addr
*nexthop
, ifindex_t ifindex
,
6025 enum nexthop_types_t nhtype
, uint32_t metric
,
6026 uint8_t type
, unsigned short instance
,
6029 struct bgp_info
*new;
6030 struct bgp_info
*bi
;
6031 struct bgp_info info
;
6032 struct bgp_node
*bn
;
6034 struct attr
*new_attr
;
6037 struct bgp_redist
*red
;
6039 /* Make default attribute. */
6040 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6043 case NEXTHOP_TYPE_IFINDEX
:
6045 case NEXTHOP_TYPE_IPV4
:
6046 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6047 attr
.nexthop
= nexthop
->ipv4
;
6049 case NEXTHOP_TYPE_IPV6
:
6050 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6051 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6052 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6054 case NEXTHOP_TYPE_BLACKHOLE
:
6055 switch (p
->family
) {
6057 attr
.nexthop
.s_addr
= INADDR_ANY
;
6060 memset(&attr
.mp_nexthop_global
, 0,
6061 sizeof(attr
.mp_nexthop_global
));
6062 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6067 attr
.nh_ifindex
= ifindex
;
6070 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6073 afi
= family2afi(p
->family
);
6075 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6077 struct attr attr_new
;
6079 /* Copy attribute for modification. */
6080 bgp_attr_dup(&attr_new
, &attr
);
6082 if (red
->redist_metric_flag
)
6083 attr_new
.med
= red
->redist_metric
;
6085 /* Apply route-map. */
6086 if (red
->rmap
.name
) {
6087 memset(&info
, 0, sizeof(struct bgp_info
));
6088 info
.peer
= bgp
->peer_self
;
6089 info
.attr
= &attr_new
;
6091 SET_FLAG(bgp
->peer_self
->rmap_type
,
6092 PEER_RMAP_TYPE_REDISTRIBUTE
);
6094 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6097 bgp
->peer_self
->rmap_type
= 0;
6099 if (ret
== RMAP_DENYMATCH
) {
6100 /* Free uninterned attribute. */
6101 bgp_attr_flush(&attr_new
);
6103 /* Unintern original. */
6104 aspath_unintern(&attr
.aspath
);
6105 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6110 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6111 bgp_attr_add_gshut_community(&attr_new
);
6113 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6114 SAFI_UNICAST
, p
, NULL
);
6116 new_attr
= bgp_attr_intern(&attr_new
);
6118 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6119 if (bi
->peer
== bgp
->peer_self
6120 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6124 /* Ensure the (source route) type is updated. */
6126 if (attrhash_cmp(bi
->attr
, new_attr
)
6127 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6128 bgp_attr_unintern(&new_attr
);
6129 aspath_unintern(&attr
.aspath
);
6130 bgp_unlock_node(bn
);
6133 /* The attribute is changed. */
6134 bgp_info_set_flag(bn
, bi
,
6135 BGP_INFO_ATTR_CHANGED
);
6137 /* Rewrite BGP route information. */
6138 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6139 bgp_info_restore(bn
, bi
);
6141 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6143 bgp_attr_unintern(&bi
->attr
);
6144 bi
->attr
= new_attr
;
6145 bi
->uptime
= bgp_clock();
6147 /* Process change. */
6148 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6150 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6151 bgp_unlock_node(bn
);
6152 aspath_unintern(&attr
.aspath
);
6154 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6156 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6158 vpn_leak_from_vrf_update(
6159 bgp_get_default(), bgp
, bi
);
6165 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6166 bgp
->peer_self
, new_attr
, bn
);
6167 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6169 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6170 bgp_info_add(bn
, new);
6171 bgp_unlock_node(bn
);
6172 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6174 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6175 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6177 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6181 /* Unintern original. */
6182 aspath_unintern(&attr
.aspath
);
6185 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6186 unsigned short instance
)
6189 struct bgp_node
*rn
;
6190 struct bgp_info
*ri
;
6191 struct bgp_redist
*red
;
6193 afi
= family2afi(p
->family
);
6195 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6197 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6198 SAFI_UNICAST
, p
, NULL
);
6200 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6201 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6205 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6206 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6208 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6211 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6212 bgp_info_delete(rn
, ri
);
6213 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6215 bgp_unlock_node(rn
);
6219 /* Withdraw specified route type's route. */
6220 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6221 unsigned short instance
)
6223 struct bgp_node
*rn
;
6224 struct bgp_info
*ri
;
6225 struct bgp_table
*table
;
6227 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6229 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6230 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6231 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6232 && ri
->instance
== instance
)
6236 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6237 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6239 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6242 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6244 bgp_info_delete(rn
, ri
);
6245 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6250 /* Static function to display route. */
6251 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6255 uint32_t destination
;
6258 if (p
->family
== AF_INET
) {
6260 len
= vty_out(vty
, "%s",
6261 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6263 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6265 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6266 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6267 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6268 || p
->u
.prefix4
.s_addr
== 0) {
6269 /* When mask is natural,
6270 mask is not displayed. */
6272 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6274 json_object_string_add(json
, "prefix",
6275 inet_ntop(p
->family
,
6278 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6280 } else if (p
->family
== AF_ETHERNET
) {
6281 prefix2str(p
, buf
, PREFIX_STRLEN
);
6282 len
= vty_out(vty
, "%s", buf
);
6283 } else if (p
->family
== AF_EVPN
) {
6287 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6290 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6291 } else if (p
->family
== AF_FLOWSPEC
) {
6292 route_vty_out_flowspec(vty
, p
, NULL
,
6294 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6295 NLRI_STRING_FORMAT_MIN
, json
);
6300 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6307 vty_out(vty
, "\n%*s", 20, " ");
6309 vty_out(vty
, "%*s", len
, " ");
6313 enum bgp_display_type
{
6317 /* Print the short form route status for a bgp_info */
6318 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6319 json_object
*json_path
)
6323 /* Route status display. */
6324 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6325 json_object_boolean_true_add(json_path
, "removed");
6327 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6328 json_object_boolean_true_add(json_path
, "stale");
6330 if (binfo
->extra
&& binfo
->extra
->suppress
)
6331 json_object_boolean_true_add(json_path
, "suppressed");
6333 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6334 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6335 json_object_boolean_true_add(json_path
, "valid");
6338 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6339 json_object_boolean_true_add(json_path
, "history");
6341 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6342 json_object_boolean_true_add(json_path
, "damped");
6344 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6345 json_object_boolean_true_add(json_path
, "bestpath");
6347 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6348 json_object_boolean_true_add(json_path
, "multipath");
6350 /* Internal route. */
6351 if ((binfo
->peer
->as
)
6352 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6353 json_object_string_add(json_path
, "pathFrom",
6356 json_object_string_add(json_path
, "pathFrom",
6362 /* Route status display. */
6363 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6365 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6367 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6369 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6370 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6376 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6378 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6380 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6382 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6387 /* Internal route. */
6388 if (binfo
->peer
&& (binfo
->peer
->as
)
6389 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6395 /* called from terminal list command */
6396 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6397 int display
, safi_t safi
, json_object
*json_paths
)
6400 json_object
*json_path
= NULL
;
6401 json_object
*json_nexthops
= NULL
;
6402 json_object
*json_nexthop_global
= NULL
;
6403 json_object
*json_nexthop_ll
= NULL
;
6404 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6405 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6408 bool nexthop_othervrf
= false;
6409 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6410 const char *nexthop_vrfname
= "Default";
6413 json_path
= json_object_new_object();
6415 /* short status lead text */
6416 route_vty_short_status_out(vty
, binfo
, json_path
);
6419 /* print prefix and mask */
6421 route_vty_out_route(p
, vty
, json_path
);
6423 vty_out(vty
, "%*s", 17, " ");
6425 route_vty_out_route(p
, vty
, json_path
);
6428 /* Print attribute */
6432 json_object_array_add(json_paths
, json_path
);
6440 * If vrf id of nexthop is different from that of prefix,
6441 * set up printable string to append
6443 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6444 const char *self
= "";
6449 nexthop_othervrf
= true;
6450 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6452 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6453 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6454 "@%s%s", VRFID_NONE_STR
, self
);
6456 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6457 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6459 if (binfo
->extra
->bgp_orig
->inst_type
!=
6460 BGP_INSTANCE_TYPE_DEFAULT
)
6462 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6464 const char *self
= "";
6469 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6473 * For ENCAP and EVPN routes, nexthop address family is not
6474 * neccessarily the same as the prefix address family.
6475 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6476 * EVPN routes are also exchanged with a MP nexthop. Currently,
6478 * is only IPv4, the value will be present in either
6480 * attr->mp_nexthop_global_in
6482 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6485 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6489 sprintf(nexthop
, "%s",
6490 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6494 sprintf(nexthop
, "%s",
6495 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6499 sprintf(nexthop
, "?");
6504 json_nexthop_global
= json_object_new_object();
6506 json_object_string_add(json_nexthop_global
, "afi",
6507 (af
== AF_INET
) ? "ip" : "ipv6");
6508 json_object_string_add(json_nexthop_global
,
6509 (af
== AF_INET
) ? "ip" : "ipv6",
6511 json_object_boolean_true_add(json_nexthop_global
,
6514 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6515 } else if (safi
== SAFI_EVPN
) {
6517 json_nexthop_global
= json_object_new_object();
6519 json_object_string_add(json_nexthop_global
, "ip",
6520 inet_ntoa(attr
->nexthop
));
6521 json_object_string_add(json_nexthop_global
, "afi",
6523 json_object_boolean_true_add(json_nexthop_global
,
6526 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6528 } else if (safi
== SAFI_FLOWSPEC
) {
6529 if (attr
->nexthop
.s_addr
!= 0) {
6531 json_nexthop_global
= json_object_new_object();
6532 json_object_string_add(
6533 json_nexthop_global
, "ip",
6534 inet_ntoa(attr
->nexthop
));
6535 json_object_string_add(json_nexthop_global
,
6537 json_object_boolean_true_add(json_nexthop_global
,
6540 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6543 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6545 json_nexthop_global
= json_object_new_object();
6547 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6548 json_object_string_add(
6549 json_nexthop_global
, "ip",
6550 inet_ntoa(attr
->mp_nexthop_global_in
));
6552 json_object_string_add(
6553 json_nexthop_global
, "ip",
6554 inet_ntoa(attr
->nexthop
));
6556 json_object_string_add(json_nexthop_global
, "afi",
6558 json_object_boolean_true_add(json_nexthop_global
,
6563 snprintf(buf
, sizeof(buf
), "%s%s",
6564 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6565 vty_out(vty
, "%-16s", buf
);
6570 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6575 json_nexthop_global
= json_object_new_object();
6576 json_object_string_add(
6577 json_nexthop_global
, "ip",
6578 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6580 json_object_string_add(json_nexthop_global
, "afi",
6582 json_object_string_add(json_nexthop_global
, "scope",
6585 /* We display both LL & GL if both have been
6587 if ((attr
->mp_nexthop_len
== 32)
6588 || (binfo
->peer
->conf_if
)) {
6589 json_nexthop_ll
= json_object_new_object();
6590 json_object_string_add(
6591 json_nexthop_ll
, "ip",
6593 &attr
->mp_nexthop_local
, buf
,
6595 json_object_string_add(json_nexthop_ll
, "afi",
6597 json_object_string_add(json_nexthop_ll
, "scope",
6600 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6601 &attr
->mp_nexthop_local
)
6603 && !attr
->mp_nexthop_prefer_global
)
6604 json_object_boolean_true_add(
6605 json_nexthop_ll
, "used");
6607 json_object_boolean_true_add(
6608 json_nexthop_global
, "used");
6610 json_object_boolean_true_add(
6611 json_nexthop_global
, "used");
6613 /* Display LL if LL/Global both in table unless
6614 * prefer-global is set */
6615 if (((attr
->mp_nexthop_len
== 32)
6616 && !attr
->mp_nexthop_prefer_global
)
6617 || (binfo
->peer
->conf_if
)) {
6618 if (binfo
->peer
->conf_if
) {
6619 len
= vty_out(vty
, "%s",
6620 binfo
->peer
->conf_if
);
6621 len
= 16 - len
; /* len of IPv6
6627 vty_out(vty
, "\n%*s", 36, " ");
6629 vty_out(vty
, "%*s", len
, " ");
6635 &attr
->mp_nexthop_local
,
6641 vty_out(vty
, "\n%*s", 36, " ");
6643 vty_out(vty
, "%*s", len
, " ");
6649 &attr
->mp_nexthop_global
, buf
,
6655 vty_out(vty
, "\n%*s", 36, " ");
6657 vty_out(vty
, "%*s", len
, " ");
6663 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6665 json_object_int_add(json_path
, "med", attr
->med
);
6667 vty_out(vty
, "%10u", attr
->med
);
6668 else if (!json_paths
)
6672 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6674 json_object_int_add(json_path
, "localpref",
6677 vty_out(vty
, "%7u", attr
->local_pref
);
6678 else if (!json_paths
)
6682 json_object_int_add(json_path
, "weight", attr
->weight
);
6684 vty_out(vty
, "%7u ", attr
->weight
);
6688 json_object_string_add(
6689 json_path
, "peerId",
6690 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6696 json_object_string_add(json_path
, "aspath",
6699 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6704 json_object_string_add(json_path
, "origin",
6705 bgp_origin_long_str
[attr
->origin
]);
6707 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6711 json_object_boolean_true_add(json_path
,
6712 "announceNexthopSelf");
6713 if (nexthop_othervrf
) {
6714 json_object_string_add(json_path
, "nhVrfName",
6717 json_object_int_add(json_path
, "nhVrfId",
6718 ((nexthop_vrfid
== VRF_UNKNOWN
)
6720 : (int)nexthop_vrfid
));
6725 if (json_nexthop_global
|| json_nexthop_ll
) {
6726 json_nexthops
= json_object_new_array();
6728 if (json_nexthop_global
)
6729 json_object_array_add(json_nexthops
,
6730 json_nexthop_global
);
6732 if (json_nexthop_ll
)
6733 json_object_array_add(json_nexthops
,
6736 json_object_object_add(json_path
, "nexthops",
6740 json_object_array_add(json_paths
, json_path
);
6744 /* prints an additional line, indented, with VNC info, if
6746 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6747 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6752 /* called from terminal list command */
6753 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6754 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6756 json_object
*json_status
= NULL
;
6757 json_object
*json_net
= NULL
;
6759 /* Route status display. */
6761 json_status
= json_object_new_object();
6762 json_net
= json_object_new_object();
6769 /* print prefix and mask */
6771 json_object_string_add(
6772 json_net
, "addrPrefix",
6773 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6775 route_vty_out_route(p
, vty
, NULL
);
6777 /* Print attribute */
6780 if (p
->family
== AF_INET
6781 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6782 || safi
== SAFI_EVPN
6783 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6784 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6785 || safi
== SAFI_EVPN
)
6786 json_object_string_add(
6787 json_net
, "nextHop",
6789 attr
->mp_nexthop_global_in
));
6791 json_object_string_add(
6792 json_net
, "nextHop",
6793 inet_ntoa(attr
->nexthop
));
6794 } else if (p
->family
== AF_INET6
6795 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6798 json_object_string_add(
6799 json_net
, "netHopGloabal",
6801 &attr
->mp_nexthop_global
, buf
,
6806 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6807 json_object_int_add(json_net
, "metric",
6810 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6811 json_object_int_add(json_net
, "localPref",
6814 json_object_int_add(json_net
, "weight", attr
->weight
);
6818 json_object_string_add(json_net
, "asPath",
6822 json_object_string_add(json_net
, "bgpOriginCode",
6823 bgp_origin_str
[attr
->origin
]);
6825 if (p
->family
== AF_INET
6826 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6827 || safi
== SAFI_EVPN
6828 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6829 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6830 || safi
== SAFI_EVPN
)
6831 vty_out(vty
, "%-16s",
6833 attr
->mp_nexthop_global_in
));
6835 vty_out(vty
, "%-16s",
6836 inet_ntoa(attr
->nexthop
));
6837 } else if (p
->family
== AF_INET6
6838 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6845 &attr
->mp_nexthop_global
, buf
,
6849 vty_out(vty
, "\n%*s", 36, " ");
6851 vty_out(vty
, "%*s", len
, " ");
6854 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6855 vty_out(vty
, "%10u", attr
->med
);
6859 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6860 vty_out(vty
, "%7u", attr
->local_pref
);
6864 vty_out(vty
, "%7u ", attr
->weight
);
6868 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6871 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6875 json_object_boolean_true_add(json_status
, "*");
6876 json_object_boolean_true_add(json_status
, ">");
6877 json_object_object_add(json_net
, "appliedStatusSymbols",
6879 char buf_cut
[BUFSIZ
];
6880 json_object_object_add(
6882 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6888 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6889 struct bgp_info
*binfo
, int display
, safi_t safi
,
6892 json_object
*json_out
= NULL
;
6894 mpls_label_t label
= MPLS_INVALID_LABEL
;
6900 json_out
= json_object_new_object();
6902 /* short status lead text */
6903 route_vty_short_status_out(vty
, binfo
, json_out
);
6905 /* print prefix and mask */
6908 route_vty_out_route(p
, vty
, NULL
);
6910 vty_out(vty
, "%*s", 17, " ");
6913 /* Print attribute */
6916 if (((p
->family
== AF_INET
)
6917 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6918 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6919 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6920 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6921 || safi
== SAFI_EVPN
) {
6923 json_object_string_add(
6924 json_out
, "mpNexthopGlobalIn",
6926 attr
->mp_nexthop_global_in
));
6928 vty_out(vty
, "%-16s",
6930 attr
->mp_nexthop_global_in
));
6933 json_object_string_add(
6934 json_out
, "nexthop",
6935 inet_ntoa(attr
->nexthop
));
6937 vty_out(vty
, "%-16s",
6938 inet_ntoa(attr
->nexthop
));
6940 } else if (((p
->family
== AF_INET6
)
6941 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6942 || (safi
== SAFI_EVPN
6943 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6944 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6948 if (attr
->mp_nexthop_len
6949 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6951 json_object_string_add(
6952 json_out
, "mpNexthopGlobalIn",
6955 &attr
->mp_nexthop_global
,
6956 buf_a
, sizeof(buf_a
)));
6961 &attr
->mp_nexthop_global
,
6962 buf_a
, sizeof(buf_a
)));
6963 } else if (attr
->mp_nexthop_len
6964 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6967 &attr
->mp_nexthop_global
,
6968 buf_a
, sizeof(buf_a
));
6970 &attr
->mp_nexthop_local
,
6971 buf_b
, sizeof(buf_b
));
6972 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6973 json_object_string_add(
6975 "mpNexthopGlobalLocal", buf_c
);
6977 vty_out(vty
, "%s(%s)",
6980 &attr
->mp_nexthop_global
,
6981 buf_a
, sizeof(buf_a
)),
6984 &attr
->mp_nexthop_local
,
6985 buf_b
, sizeof(buf_b
)));
6990 label
= decode_label(&binfo
->extra
->label
[0]);
6992 if (bgp_is_valid_label(&label
)) {
6994 json_object_int_add(json_out
, "notag", label
);
6995 json_object_array_add(json
, json_out
);
6997 vty_out(vty
, "notag/%d", label
);
7003 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7004 struct bgp_info
*binfo
, int display
,
7005 json_object
*json_paths
)
7009 json_object
*json_path
= NULL
;
7012 json_path
= json_object_new_object();
7017 /* short status lead text */
7018 route_vty_short_status_out(vty
, binfo
, json_path
);
7020 /* print prefix and mask */
7022 route_vty_out_route(p
, vty
, NULL
);
7024 vty_out(vty
, "%*s", 17, " ");
7026 /* Print attribute */
7030 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7034 vty_out(vty
, "%-16s",
7035 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7039 vty_out(vty
, "%s(%s)",
7040 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7042 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7049 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7051 vty_out(vty
, "%s", str
);
7052 XFREE(MTYPE_TMP
, str
);
7054 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7056 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7057 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7060 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7063 if (attr
->ecommunity
) {
7065 struct ecommunity_val
*routermac
= ecommunity_lookup(
7066 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7067 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7069 mac
= ecom_mac2str((char *)routermac
->val
);
7071 vty_out(vty
, "/%s", (char *)mac
);
7072 XFREE(MTYPE_TMP
, mac
);
7080 /* dampening route */
7081 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7082 struct bgp_info
*binfo
, int display
, safi_t safi
,
7083 uint8_t use_json
, json_object
*json
)
7087 char timebuf
[BGP_UPTIME_LEN
];
7089 /* short status lead text */
7090 route_vty_short_status_out(vty
, binfo
, json
);
7092 /* print prefix and mask */
7095 route_vty_out_route(p
, vty
, NULL
);
7097 vty_out(vty
, "%*s", 17, " ");
7100 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7104 vty_out(vty
, "\n%*s", 34, " ");
7107 json_object_int_add(json
, "peerHost", len
);
7109 vty_out(vty
, "%*s", len
, " ");
7113 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7116 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7120 /* Print attribute */
7126 json_object_string_add(json
, "asPath",
7129 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7134 json_object_string_add(json
, "origin",
7135 bgp_origin_str
[attr
->origin
]);
7137 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7144 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7145 struct bgp_info
*binfo
, int display
, safi_t safi
,
7146 uint8_t use_json
, json_object
*json
)
7149 struct bgp_damp_info
*bdi
;
7150 char timebuf
[BGP_UPTIME_LEN
];
7156 bdi
= binfo
->extra
->damp_info
;
7158 /* short status lead text */
7159 route_vty_short_status_out(vty
, binfo
, json
);
7161 /* print prefix and mask */
7164 route_vty_out_route(p
, vty
, NULL
);
7166 vty_out(vty
, "%*s", 17, " ");
7169 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7173 vty_out(vty
, "\n%*s", 33, " ");
7176 json_object_int_add(json
, "peerHost", len
);
7178 vty_out(vty
, "%*s", len
, " ");
7181 len
= vty_out(vty
, "%d", bdi
->flap
);
7188 json_object_int_add(json
, "bdiFlap", len
);
7190 vty_out(vty
, "%*s", len
, " ");
7194 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7197 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7198 BGP_UPTIME_LEN
, 0, NULL
));
7200 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7201 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7203 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7204 BGP_UPTIME_LEN
, use_json
, json
);
7207 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7212 vty_out(vty
, "%*s ", 8, " ");
7215 /* Print attribute */
7221 json_object_string_add(json
, "asPath",
7224 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7229 json_object_string_add(json
, "origin",
7230 bgp_origin_str
[attr
->origin
]);
7232 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7238 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7239 int *first
, const char *header
,
7240 json_object
*json_adv_to
)
7242 char buf1
[INET6_ADDRSTRLEN
];
7243 json_object
*json_peer
= NULL
;
7246 /* 'advertised-to' is a dictionary of peers we have advertised
7248 * prefix too. The key is the peer's IP or swpX, the value is
7250 * hostname if we know it and "" if not.
7252 json_peer
= json_object_new_object();
7255 json_object_string_add(json_peer
, "hostname",
7259 json_object_object_add(json_adv_to
, peer
->conf_if
,
7262 json_object_object_add(
7264 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7268 vty_out(vty
, "%s", header
);
7273 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7275 vty_out(vty
, " %s(%s)", peer
->hostname
,
7278 vty_out(vty
, " %s(%s)", peer
->hostname
,
7279 sockunion2str(&peer
->su
, buf1
,
7283 vty_out(vty
, " %s", peer
->conf_if
);
7286 sockunion2str(&peer
->su
, buf1
,
7292 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7293 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7294 json_object
*json_paths
)
7296 char buf
[INET6_ADDRSTRLEN
];
7298 char buf2
[EVPN_ROUTE_STRLEN
];
7300 int sockunion_vty_out(struct vty
*, union sockunion
*);
7302 json_object
*json_bestpath
= NULL
;
7303 json_object
*json_cluster_list
= NULL
;
7304 json_object
*json_cluster_list_list
= NULL
;
7305 json_object
*json_ext_community
= NULL
;
7306 json_object
*json_last_update
= NULL
;
7307 json_object
*json_pmsi
= NULL
;
7308 json_object
*json_nexthop_global
= NULL
;
7309 json_object
*json_nexthop_ll
= NULL
;
7310 json_object
*json_nexthops
= NULL
;
7311 json_object
*json_path
= NULL
;
7312 json_object
*json_peer
= NULL
;
7313 json_object
*json_string
= NULL
;
7314 json_object
*json_adv_to
= NULL
;
7316 struct listnode
*node
, *nnode
;
7318 int addpath_capable
;
7320 unsigned int first_as
;
7321 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7326 json_path
= json_object_new_object();
7327 json_peer
= json_object_new_object();
7328 json_nexthop_global
= json_object_new_object();
7331 if (!json_paths
&& safi
== SAFI_EVPN
) {
7334 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7335 vty_out(vty
, " Route %s", buf2
);
7337 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7338 bgp_evpn_label2str(binfo
->extra
->label
,
7339 binfo
->extra
->num_labels
, tag_buf
,
7341 vty_out(vty
, " VNI %s", tag_buf
);
7344 if (binfo
->extra
&& binfo
->extra
->parent
) {
7345 struct bgp_info
*parent_ri
;
7346 struct bgp_node
*rn
, *prn
;
7348 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7349 rn
= parent_ri
->net
;
7350 if (rn
&& rn
->prn
) {
7352 vty_out(vty
, " Imported from %s:%s\n",
7354 (struct prefix_rd
*)&prn
->p
,
7355 buf1
, sizeof(buf1
)),
7364 /* Line1 display AS-path, Aggregator */
7367 if (!attr
->aspath
->json
)
7368 aspath_str_update(attr
->aspath
, true);
7369 json_object_lock(attr
->aspath
->json
);
7370 json_object_object_add(json_path
, "aspath",
7371 attr
->aspath
->json
);
7373 if (attr
->aspath
->segments
)
7374 aspath_print_vty(vty
, " %s",
7377 vty_out(vty
, " Local");
7381 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7383 json_object_boolean_true_add(json_path
,
7386 vty_out(vty
, ", (removed)");
7389 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7391 json_object_boolean_true_add(json_path
,
7394 vty_out(vty
, ", (stale)");
7397 if (CHECK_FLAG(attr
->flag
,
7398 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7400 json_object_int_add(json_path
, "aggregatorAs",
7401 attr
->aggregator_as
);
7402 json_object_string_add(
7403 json_path
, "aggregatorId",
7404 inet_ntoa(attr
->aggregator_addr
));
7406 vty_out(vty
, ", (aggregated by %u %s)",
7407 attr
->aggregator_as
,
7408 inet_ntoa(attr
->aggregator_addr
));
7412 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7413 PEER_FLAG_REFLECTOR_CLIENT
)) {
7415 json_object_boolean_true_add(
7416 json_path
, "rxedFromRrClient");
7418 vty_out(vty
, ", (Received from a RR-client)");
7421 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7422 PEER_FLAG_RSERVER_CLIENT
)) {
7424 json_object_boolean_true_add(
7425 json_path
, "rxedFromRsClient");
7427 vty_out(vty
, ", (Received from a RS-client)");
7430 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7432 json_object_boolean_true_add(
7433 json_path
, "dampeningHistoryEntry");
7435 vty_out(vty
, ", (history entry)");
7436 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7438 json_object_boolean_true_add(
7439 json_path
, "dampeningSuppressed");
7441 vty_out(vty
, ", (suppressed due to dampening)");
7447 /* Line2 display Next-hop, Neighbor, Router-id */
7448 /* Display the nexthop */
7449 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7450 || p
->family
== AF_EVPN
)
7451 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7452 || safi
== SAFI_EVPN
7453 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7454 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7455 || safi
== SAFI_EVPN
) {
7457 json_object_string_add(
7458 json_nexthop_global
, "ip",
7460 attr
->mp_nexthop_global_in
));
7464 attr
->mp_nexthop_global_in
));
7467 json_object_string_add(
7468 json_nexthop_global
, "ip",
7469 inet_ntoa(attr
->nexthop
));
7472 inet_ntoa(attr
->nexthop
));
7476 json_object_string_add(json_nexthop_global
,
7480 json_object_string_add(
7481 json_nexthop_global
, "ip",
7483 &attr
->mp_nexthop_global
, buf
,
7485 json_object_string_add(json_nexthop_global
,
7487 json_object_string_add(json_nexthop_global
,
7492 &attr
->mp_nexthop_global
, buf
,
7497 /* Display the IGP cost or 'inaccessible' */
7498 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7500 json_object_boolean_false_add(
7501 json_nexthop_global
, "accessible");
7503 vty_out(vty
, " (inaccessible)");
7505 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7507 json_object_int_add(
7508 json_nexthop_global
, "metric",
7509 binfo
->extra
->igpmetric
);
7511 vty_out(vty
, " (metric %u)",
7512 binfo
->extra
->igpmetric
);
7515 /* IGP cost is 0, display this only for json */
7518 json_object_int_add(json_nexthop_global
,
7523 json_object_boolean_true_add(
7524 json_nexthop_global
, "accessible");
7527 /* Display peer "from" output */
7528 /* This path was originated locally */
7529 if (binfo
->peer
== bgp
->peer_self
) {
7531 if (safi
== SAFI_EVPN
7532 || (p
->family
== AF_INET
7533 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7535 json_object_string_add(
7536 json_peer
, "peerId", "0.0.0.0");
7538 vty_out(vty
, " from 0.0.0.0 ");
7541 json_object_string_add(json_peer
,
7544 vty_out(vty
, " from :: ");
7548 json_object_string_add(
7549 json_peer
, "routerId",
7550 inet_ntoa(bgp
->router_id
));
7552 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7555 /* We RXed this path from one of our peers */
7559 json_object_string_add(
7560 json_peer
, "peerId",
7561 sockunion2str(&binfo
->peer
->su
, buf
,
7563 json_object_string_add(
7564 json_peer
, "routerId",
7566 &binfo
->peer
->remote_id
, buf1
,
7569 if (binfo
->peer
->hostname
)
7570 json_object_string_add(
7571 json_peer
, "hostname",
7572 binfo
->peer
->hostname
);
7574 if (binfo
->peer
->domainname
)
7575 json_object_string_add(
7576 json_peer
, "domainname",
7577 binfo
->peer
->domainname
);
7579 if (binfo
->peer
->conf_if
)
7580 json_object_string_add(
7581 json_peer
, "interface",
7582 binfo
->peer
->conf_if
);
7584 if (binfo
->peer
->conf_if
) {
7585 if (binfo
->peer
->hostname
7588 BGP_FLAG_SHOW_HOSTNAME
))
7589 vty_out(vty
, " from %s(%s)",
7590 binfo
->peer
->hostname
,
7591 binfo
->peer
->conf_if
);
7593 vty_out(vty
, " from %s",
7594 binfo
->peer
->conf_if
);
7596 if (binfo
->peer
->hostname
7599 BGP_FLAG_SHOW_HOSTNAME
))
7600 vty_out(vty
, " from %s(%s)",
7601 binfo
->peer
->hostname
,
7604 vty_out(vty
, " from %s",
7613 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7614 vty_out(vty
, " (%s)",
7615 inet_ntoa(attr
->originator_id
));
7617 vty_out(vty
, " (%s)",
7620 &binfo
->peer
->remote_id
,
7621 buf1
, sizeof(buf1
)));
7626 * Note when vrfid of nexthop is different from that of prefix
7628 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7629 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7634 if (binfo
->extra
->bgp_orig
->inst_type
==
7635 BGP_INSTANCE_TYPE_DEFAULT
)
7639 vn
= binfo
->extra
->bgp_orig
->name
;
7641 json_object_string_add(json_path
, "nhVrfName",
7644 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7645 json_object_int_add(json_path
,
7648 json_object_int_add(json_path
,
7649 "nhVrfId", (int)nexthop_vrfid
);
7652 if (nexthop_vrfid
== VRF_UNKNOWN
)
7653 vty_out(vty
, " vrf ?");
7655 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7661 json_object_boolean_true_add(json_path
,
7662 "announceNexthopSelf");
7664 vty_out(vty
, " announce-nh-self");
7671 /* display the link-local nexthop */
7672 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7674 json_nexthop_ll
= json_object_new_object();
7675 json_object_string_add(
7676 json_nexthop_ll
, "ip",
7678 &attr
->mp_nexthop_local
, buf
,
7680 json_object_string_add(json_nexthop_ll
, "afi",
7682 json_object_string_add(json_nexthop_ll
, "scope",
7685 json_object_boolean_true_add(json_nexthop_ll
,
7688 if (!attr
->mp_nexthop_prefer_global
)
7689 json_object_boolean_true_add(
7690 json_nexthop_ll
, "used");
7692 json_object_boolean_true_add(
7693 json_nexthop_global
, "used");
7695 vty_out(vty
, " (%s) %s\n",
7697 &attr
->mp_nexthop_local
, buf
,
7699 attr
->mp_nexthop_prefer_global
7704 /* If we do not have a link-local nexthop then we must flag the
7708 json_object_boolean_true_add(
7709 json_nexthop_global
, "used");
7712 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7713 * Int/Ext/Local, Atomic, best */
7715 json_object_string_add(
7716 json_path
, "origin",
7717 bgp_origin_long_str
[attr
->origin
]);
7719 vty_out(vty
, " Origin %s",
7720 bgp_origin_long_str
[attr
->origin
]);
7722 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7724 json_object_int_add(json_path
, "med",
7727 vty_out(vty
, ", metric %u", attr
->med
);
7730 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7732 json_object_int_add(json_path
, "localpref",
7735 vty_out(vty
, ", localpref %u",
7739 json_object_int_add(json_path
, "localpref",
7740 bgp
->default_local_pref
);
7742 vty_out(vty
, ", localpref %u",
7743 bgp
->default_local_pref
);
7746 if (attr
->weight
!= 0) {
7748 json_object_int_add(json_path
, "weight",
7751 vty_out(vty
, ", weight %u", attr
->weight
);
7754 if (attr
->tag
!= 0) {
7756 json_object_int_add(json_path
, "tag",
7759 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7763 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7765 json_object_boolean_false_add(json_path
,
7768 vty_out(vty
, ", invalid");
7769 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7771 json_object_boolean_true_add(json_path
,
7774 vty_out(vty
, ", valid");
7777 if (binfo
->peer
!= bgp
->peer_self
) {
7778 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7779 if (CHECK_FLAG(bgp
->config
,
7780 BGP_CONFIG_CONFEDERATION
)) {
7782 json_object_string_add(
7787 ", confed-internal");
7790 json_object_string_add(
7794 vty_out(vty
, ", internal");
7797 if (bgp_confederation_peers_check(
7798 bgp
, binfo
->peer
->as
)) {
7800 json_object_string_add(
7805 ", confed-external");
7808 json_object_string_add(
7812 vty_out(vty
, ", external");
7815 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7817 json_object_boolean_true_add(json_path
,
7819 json_object_boolean_true_add(json_path
,
7822 vty_out(vty
, ", aggregated, local");
7824 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7826 json_object_boolean_true_add(json_path
,
7829 vty_out(vty
, ", sourced");
7832 json_object_boolean_true_add(json_path
,
7834 json_object_boolean_true_add(json_path
,
7837 vty_out(vty
, ", sourced, local");
7841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7843 json_object_boolean_true_add(json_path
,
7846 vty_out(vty
, ", atomic-aggregate");
7849 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7850 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7851 && bgp_info_mpath_count(binfo
))) {
7853 json_object_boolean_true_add(json_path
,
7856 vty_out(vty
, ", multipath");
7859 // Mark the bestpath(s)
7860 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7861 first_as
= aspath_get_first_as(attr
->aspath
);
7866 json_object_new_object();
7867 json_object_int_add(json_bestpath
,
7868 "bestpathFromAs", first_as
);
7871 vty_out(vty
, ", bestpath-from-AS %u",
7875 ", bestpath-from-AS Local");
7879 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7883 json_object_new_object();
7884 json_object_boolean_true_add(json_bestpath
,
7887 vty_out(vty
, ", best");
7891 json_object_object_add(json_path
, "bestpath",
7897 /* Line 4 display Community */
7898 if (attr
->community
) {
7900 if (!attr
->community
->json
)
7901 community_str(attr
->community
, true);
7902 json_object_lock(attr
->community
->json
);
7903 json_object_object_add(json_path
, "community",
7904 attr
->community
->json
);
7906 vty_out(vty
, " Community: %s\n",
7907 attr
->community
->str
);
7911 /* Line 5 display Extended-community */
7912 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7914 json_ext_community
= json_object_new_object();
7915 json_object_string_add(json_ext_community
,
7917 attr
->ecommunity
->str
);
7918 json_object_object_add(json_path
,
7919 "extendedCommunity",
7920 json_ext_community
);
7922 vty_out(vty
, " Extended Community: %s\n",
7923 attr
->ecommunity
->str
);
7927 /* Line 6 display Large community */
7928 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7930 if (!attr
->lcommunity
->json
)
7931 lcommunity_str(attr
->lcommunity
, true);
7932 json_object_lock(attr
->lcommunity
->json
);
7933 json_object_object_add(json_path
,
7935 attr
->lcommunity
->json
);
7937 vty_out(vty
, " Large Community: %s\n",
7938 attr
->lcommunity
->str
);
7942 /* Line 7 display Originator, Cluster-id */
7943 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7944 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7946 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7948 json_object_string_add(
7949 json_path
, "originatorId",
7950 inet_ntoa(attr
->originator_id
));
7952 vty_out(vty
, " Originator: %s",
7953 inet_ntoa(attr
->originator_id
));
7956 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7961 json_object_new_object();
7962 json_cluster_list_list
=
7963 json_object_new_array();
7966 i
< attr
->cluster
->length
/ 4;
7968 json_string
= json_object_new_string(
7972 json_object_array_add(
7973 json_cluster_list_list
,
7977 /* struct cluster_list does not have
7979 * aspath and community do. Add this
7982 json_object_string_add(json_cluster_list,
7983 "string", attr->cluster->str);
7985 json_object_object_add(
7986 json_cluster_list
, "list",
7987 json_cluster_list_list
);
7988 json_object_object_add(
7989 json_path
, "clusterList",
7992 vty_out(vty
, ", Cluster list: ");
7995 i
< attr
->cluster
->length
/ 4;
8009 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8010 bgp_damp_info_vty(vty
, binfo
, json_path
);
8013 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8014 && safi
!= SAFI_EVPN
) {
8015 mpls_label_t label
=
8016 label_pton(&binfo
->extra
->label
[0]);
8018 json_object_int_add(json_path
, "remoteLabel",
8021 vty_out(vty
, " Remote label: %d\n", label
);
8025 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8027 json_object_int_add(json_path
, "labelIndex",
8030 vty_out(vty
, " Label Index: %d\n",
8034 /* Line 8 display Addpath IDs */
8035 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8037 json_object_int_add(json_path
, "addpathRxId",
8038 binfo
->addpath_rx_id
);
8039 json_object_int_add(json_path
, "addpathTxId",
8040 binfo
->addpath_tx_id
);
8042 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8043 binfo
->addpath_rx_id
,
8044 binfo
->addpath_tx_id
);
8048 /* If we used addpath to TX a non-bestpath we need to display
8049 * "Advertised to" on a path-by-path basis */
8050 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8053 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8055 bgp_addpath_encode_tx(peer
, afi
, safi
);
8056 has_adj
= bgp_adj_out_lookup(
8057 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8059 if ((addpath_capable
&& has_adj
)
8060 || (!addpath_capable
&& has_adj
8061 && CHECK_FLAG(binfo
->flags
,
8062 BGP_INFO_SELECTED
))) {
8063 if (json_path
&& !json_adv_to
)
8065 json_object_new_object();
8067 route_vty_out_advertised_to(
8076 json_object_object_add(json_path
,
8087 /* Line 9 display Uptime */
8088 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8090 json_last_update
= json_object_new_object();
8091 json_object_int_add(json_last_update
, "epoch", tbuf
);
8092 json_object_string_add(json_last_update
, "string",
8094 json_object_object_add(json_path
, "lastUpdate",
8097 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8099 /* Line 10 display PMSI tunnel attribute, if present */
8100 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8101 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8102 attr
->pmsi_tnl_type
,
8103 PMSI_TNLTYPE_STR_DEFAULT
);
8106 json_pmsi
= json_object_new_object();
8107 json_object_string_add(json_pmsi
,
8109 json_object_object_add(json_path
, "pmsi",
8112 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8118 /* We've constructed the json object for this path, add it to the json
8122 if (json_nexthop_global
|| json_nexthop_ll
) {
8123 json_nexthops
= json_object_new_array();
8125 if (json_nexthop_global
)
8126 json_object_array_add(json_nexthops
,
8127 json_nexthop_global
);
8129 if (json_nexthop_ll
)
8130 json_object_array_add(json_nexthops
,
8133 json_object_object_add(json_path
, "nexthops",
8137 json_object_object_add(json_path
, "peer", json_peer
);
8138 json_object_array_add(json_paths
, json_path
);
8143 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8144 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8145 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8147 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8148 const char *prefix_list_str
, afi_t afi
,
8149 safi_t safi
, enum bgp_show_type type
);
8150 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8151 const char *filter
, afi_t afi
, safi_t safi
,
8152 enum bgp_show_type type
);
8153 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8154 const char *rmap_str
, afi_t afi
, safi_t safi
,
8155 enum bgp_show_type type
);
8156 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8157 const char *com
, int exact
, afi_t afi
,
8159 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8160 const char *prefix
, afi_t afi
, safi_t safi
,
8161 enum bgp_show_type type
);
8162 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8163 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8164 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8165 const char *comstr
, int exact
, afi_t afi
,
8166 safi_t safi
, uint8_t use_json
);
8169 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8170 struct bgp_table
*table
, enum bgp_show_type type
,
8171 void *output_arg
, uint8_t use_json
, char *rd
,
8172 int is_last
, unsigned long *output_cum
,
8173 unsigned long *total_cum
,
8174 unsigned long *json_header_depth
)
8176 struct bgp_info
*ri
;
8177 struct bgp_node
*rn
;
8180 unsigned long output_count
= 0;
8181 unsigned long total_count
= 0;
8185 json_object
*json_paths
= NULL
;
8188 if (output_cum
&& *output_cum
!= 0)
8191 if (use_json
&& !*json_header_depth
) {
8193 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8194 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8195 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8196 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8198 table
->version
, inet_ntoa(bgp
->router_id
));
8199 *json_header_depth
= 2;
8201 vty_out(vty
, " \"routeDistinguishers\" : {");
8202 ++*json_header_depth
;
8204 json_paths
= json_object_new_object();
8207 if (use_json
&& rd
) {
8208 vty_out(vty
, " \"%s\" : { ", rd
);
8211 /* Start processing of routes. */
8212 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8213 if (rn
->info
== NULL
)
8218 json_paths
= json_object_new_array();
8222 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8224 if (type
== bgp_show_type_flap_statistics
8225 || type
== bgp_show_type_flap_neighbor
8226 || type
== bgp_show_type_dampend_paths
8227 || type
== bgp_show_type_damp_neighbor
) {
8228 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8231 if (type
== bgp_show_type_regexp
) {
8232 regex_t
*regex
= output_arg
;
8234 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8238 if (type
== bgp_show_type_prefix_list
) {
8239 struct prefix_list
*plist
= output_arg
;
8241 if (prefix_list_apply(plist
, &rn
->p
)
8245 if (type
== bgp_show_type_filter_list
) {
8246 struct as_list
*as_list
= output_arg
;
8248 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8249 != AS_FILTER_PERMIT
)
8252 if (type
== bgp_show_type_route_map
) {
8253 struct route_map
*rmap
= output_arg
;
8254 struct bgp_info binfo
;
8255 struct attr dummy_attr
;
8258 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8260 binfo
.peer
= ri
->peer
;
8261 binfo
.attr
= &dummy_attr
;
8263 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8265 if (ret
== RMAP_DENYMATCH
)
8268 if (type
== bgp_show_type_neighbor
8269 || type
== bgp_show_type_flap_neighbor
8270 || type
== bgp_show_type_damp_neighbor
) {
8271 union sockunion
*su
= output_arg
;
8273 if (ri
->peer
== NULL
8274 || ri
->peer
->su_remote
== NULL
8275 || !sockunion_same(ri
->peer
->su_remote
, su
))
8278 if (type
== bgp_show_type_cidr_only
) {
8279 uint32_t destination
;
8281 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8282 if (IN_CLASSC(destination
)
8283 && rn
->p
.prefixlen
== 24)
8285 if (IN_CLASSB(destination
)
8286 && rn
->p
.prefixlen
== 16)
8288 if (IN_CLASSA(destination
)
8289 && rn
->p
.prefixlen
== 8)
8292 if (type
== bgp_show_type_prefix_longer
) {
8293 struct prefix
*p
= output_arg
;
8295 if (!prefix_match(p
, &rn
->p
))
8298 if (type
== bgp_show_type_community_all
) {
8299 if (!ri
->attr
->community
)
8302 if (type
== bgp_show_type_community
) {
8303 struct community
*com
= output_arg
;
8305 if (!ri
->attr
->community
8306 || !community_match(ri
->attr
->community
,
8310 if (type
== bgp_show_type_community_exact
) {
8311 struct community
*com
= output_arg
;
8313 if (!ri
->attr
->community
8314 || !community_cmp(ri
->attr
->community
, com
))
8317 if (type
== bgp_show_type_community_list
) {
8318 struct community_list
*list
= output_arg
;
8320 if (!community_list_match(ri
->attr
->community
,
8324 if (type
== bgp_show_type_community_list_exact
) {
8325 struct community_list
*list
= output_arg
;
8327 if (!community_list_exact_match(
8328 ri
->attr
->community
, list
))
8331 if (type
== bgp_show_type_lcommunity
) {
8332 struct lcommunity
*lcom
= output_arg
;
8334 if (!ri
->attr
->lcommunity
8335 || !lcommunity_match(ri
->attr
->lcommunity
,
8339 if (type
== bgp_show_type_lcommunity_list
) {
8340 struct community_list
*list
= output_arg
;
8342 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8346 if (type
== bgp_show_type_lcommunity_all
) {
8347 if (!ri
->attr
->lcommunity
)
8350 if (type
== bgp_show_type_dampend_paths
8351 || type
== bgp_show_type_damp_neighbor
) {
8352 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8353 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8357 if (!use_json
&& header
) {
8358 vty_out(vty
, "BGP table version is %" PRIu64
8359 ", local router ID is %s, vrf id ",
8361 inet_ntoa(bgp
->router_id
));
8362 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8363 vty_out(vty
, "%s", VRFID_NONE_STR
);
8365 vty_out(vty
, "%u", bgp
->vrf_id
);
8367 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8368 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8369 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8370 if (type
== bgp_show_type_dampend_paths
8371 || type
== bgp_show_type_damp_neighbor
)
8372 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8373 else if (type
== bgp_show_type_flap_statistics
8374 || type
== bgp_show_type_flap_neighbor
)
8375 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8377 vty_out(vty
, BGP_SHOW_HEADER
);
8380 if (rd
!= NULL
&& !display
&& !output_count
) {
8383 "Route Distinguisher: %s\n",
8386 if (type
== bgp_show_type_dampend_paths
8387 || type
== bgp_show_type_damp_neighbor
)
8388 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8389 safi
, use_json
, json_paths
);
8390 else if (type
== bgp_show_type_flap_statistics
8391 || type
== bgp_show_type_flap_neighbor
)
8392 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8393 safi
, use_json
, json_paths
);
8395 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8406 sprintf(buf2
, "%s/%d",
8407 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8410 vty_out(vty
, "\"%s\": ", buf2
);
8412 vty_out(vty
, ",\"%s\": ", buf2
);
8415 json_object_to_json_string(json_paths
));
8416 json_object_free(json_paths
);
8423 output_count
+= *output_cum
;
8424 *output_cum
= output_count
;
8427 total_count
+= *total_cum
;
8428 *total_cum
= total_count
;
8432 json_object_free(json_paths
);
8434 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8438 for (i
= 0; i
< *json_header_depth
; ++i
)
8439 vty_out(vty
, " } ");
8443 /* No route is displayed */
8444 if (output_count
== 0) {
8445 if (type
== bgp_show_type_normal
)
8447 "No BGP prefixes displayed, %ld exist\n",
8451 "\nDisplayed %ld routes and %ld total paths\n",
8452 output_count
, total_count
);
8459 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8460 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8461 enum bgp_show_type type
, void *output_arg
,
8464 struct bgp_node
*rn
, *next
;
8465 unsigned long output_cum
= 0;
8466 unsigned long total_cum
= 0;
8467 unsigned long json_header_depth
= 0;
8470 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8472 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8473 next
= bgp_route_next(rn
);
8474 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8476 if (rn
->info
!= NULL
) {
8477 struct prefix_rd prd
;
8478 char rd
[RD_ADDRSTRLEN
];
8480 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8481 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8482 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8483 output_arg
, use_json
, rd
, next
== NULL
,
8484 &output_cum
, &total_cum
,
8485 &json_header_depth
);
8491 if (output_cum
== 0)
8492 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8496 "\nDisplayed %ld routes and %ld total paths\n",
8497 output_cum
, total_cum
);
8501 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8502 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8504 struct bgp_table
*table
;
8505 unsigned long json_header_depth
= 0;
8508 bgp
= bgp_get_default();
8513 vty_out(vty
, "No BGP process is configured\n");
8515 vty_out(vty
, "{}\n");
8519 table
= bgp
->rib
[afi
][safi
];
8520 /* use MPLS and ENCAP specific shows until they are merged */
8521 if (safi
== SAFI_MPLS_VPN
) {
8522 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8523 output_arg
, use_json
);
8526 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8527 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8528 output_arg
, use_json
,
8531 /* labeled-unicast routes live in the unicast table */
8532 else if (safi
== SAFI_LABELED_UNICAST
)
8533 safi
= SAFI_UNICAST
;
8535 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8536 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8539 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8540 safi_t safi
, uint8_t use_json
)
8542 struct listnode
*node
, *nnode
;
8547 vty_out(vty
, "{\n");
8549 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8552 vty_out(vty
, ",\n");
8556 vty_out(vty
, "\"%s\":",
8557 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8561 vty_out(vty
, "\nInstance %s:\n",
8562 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8566 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8571 vty_out(vty
, "}\n");
8574 /* Header of detailed BGP route information */
8575 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8576 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8577 afi_t afi
, safi_t safi
, json_object
*json
)
8579 struct bgp_info
*ri
;
8582 struct listnode
*node
, *nnode
;
8583 char buf1
[RD_ADDRSTRLEN
];
8584 char buf2
[INET6_ADDRSTRLEN
];
8585 char buf3
[EVPN_ROUTE_STRLEN
];
8586 char prefix_str
[BUFSIZ
];
8591 int no_advertise
= 0;
8594 int has_valid_label
= 0;
8595 mpls_label_t label
= 0;
8596 json_object
*json_adv_to
= NULL
;
8599 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8601 if (has_valid_label
)
8602 label
= label_pton(&rn
->local_label
);
8605 if (has_valid_label
)
8606 json_object_int_add(json
, "localLabel", label
);
8608 json_object_string_add(
8610 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8612 if (safi
== SAFI_EVPN
)
8613 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8614 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8617 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8618 buf3
, sizeof(buf3
)));
8620 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8621 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8622 ? prefix_rd2str(prd
, buf1
,
8625 safi
== SAFI_MPLS_VPN
? ":" : "",
8626 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8630 if (has_valid_label
)
8631 vty_out(vty
, "Local label: %d\n", label
);
8632 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8633 vty_out(vty
, "not allocated\n");
8636 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8638 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8640 if (ri
->extra
&& ri
->extra
->suppress
)
8642 if (ri
->attr
->community
!= NULL
) {
8643 if (community_include(ri
->attr
->community
,
8644 COMMUNITY_NO_ADVERTISE
))
8646 if (community_include(ri
->attr
->community
,
8647 COMMUNITY_NO_EXPORT
))
8649 if (community_include(ri
->attr
->community
,
8650 COMMUNITY_LOCAL_AS
))
8657 vty_out(vty
, "Paths: (%d available", count
);
8659 vty_out(vty
, ", best #%d", best
);
8660 if (safi
== SAFI_UNICAST
)
8661 vty_out(vty
, ", table %s",
8663 == BGP_INSTANCE_TYPE_DEFAULT
)
8664 ? "Default-IP-Routing-Table"
8667 vty_out(vty
, ", no best path");
8670 vty_out(vty
, ", not advertised to any peer");
8672 vty_out(vty
, ", not advertised to EBGP peer");
8674 vty_out(vty
, ", not advertised outside local AS");
8678 ", Advertisements suppressed by an aggregate.");
8679 vty_out(vty
, ")\n");
8682 /* If we are not using addpath then we can display Advertised to and
8684 * show what peers we advertised the bestpath to. If we are using
8686 * though then we must display Advertised to on a path-by-path basis. */
8687 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8688 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8689 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8690 if (json
&& !json_adv_to
)
8691 json_adv_to
= json_object_new_object();
8693 route_vty_out_advertised_to(
8695 " Advertised to non peer-group peers:\n ",
8702 json_object_object_add(json
, "advertisedTo",
8707 vty_out(vty
, " Not advertised to any peer");
8713 /* Display specified route of BGP table. */
8714 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8715 struct bgp_table
*rib
, const char *ip_str
,
8716 afi_t afi
, safi_t safi
,
8717 struct prefix_rd
*prd
, int prefix_check
,
8718 enum bgp_path_type pathtype
,
8724 struct prefix match
;
8725 struct bgp_node
*rn
;
8726 struct bgp_node
*rm
;
8727 struct bgp_info
*ri
;
8728 struct bgp_table
*table
;
8729 json_object
*json
= NULL
;
8730 json_object
*json_paths
= NULL
;
8732 /* Check IP address argument. */
8733 ret
= str2prefix(ip_str
, &match
);
8735 vty_out(vty
, "address is malformed\n");
8739 match
.family
= afi2family(afi
);
8742 json
= json_object_new_object();
8743 json_paths
= json_object_new_array();
8746 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8747 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8748 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8751 if ((table
= rn
->info
) == NULL
)
8756 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8760 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8761 bgp_unlock_node(rm
);
8765 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8767 route_vty_out_detail_header(
8769 (struct prefix_rd
*)&rn
->p
,
8770 AFI_IP
, safi
, json
);
8775 if (pathtype
== BGP_PATH_ALL
8776 || (pathtype
== BGP_PATH_BESTPATH
8777 && CHECK_FLAG(ri
->flags
,
8779 || (pathtype
== BGP_PATH_MULTIPATH
8780 && (CHECK_FLAG(ri
->flags
,
8782 || CHECK_FLAG(ri
->flags
,
8783 BGP_INFO_SELECTED
))))
8784 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8789 bgp_unlock_node(rm
);
8791 } else if (safi
== SAFI_FLOWSPEC
) {
8792 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8793 &match
, prefix_check
);
8795 route_vty_out_flowspec(vty
, &rn
->p
,
8796 rn
->info
, use_json
?
8797 NLRI_STRING_FORMAT_JSON
:
8798 NLRI_STRING_FORMAT_LARGE
,
8801 bgp_unlock_node(rn
);
8806 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8808 || rn
->p
.prefixlen
== match
.prefixlen
) {
8809 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8811 route_vty_out_detail_header(
8812 vty
, bgp
, rn
, NULL
, afi
,
8818 if (pathtype
== BGP_PATH_ALL
8819 || (pathtype
== BGP_PATH_BESTPATH
8823 || (pathtype
== BGP_PATH_MULTIPATH
8829 BGP_INFO_SELECTED
))))
8830 route_vty_out_detail(
8831 vty
, bgp
, &rn
->p
, ri
,
8832 afi
, safi
, json_paths
);
8836 bgp_unlock_node(rn
);
8842 json_object_object_add(json
, "paths", json_paths
);
8844 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8845 json
, JSON_C_TO_STRING_PRETTY
));
8846 json_object_free(json
);
8849 vty_out(vty
, "%% Network not in table\n");
8857 /* Display specified route of Main RIB */
8858 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8859 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8860 int prefix_check
, enum bgp_path_type pathtype
,
8864 bgp
= bgp_get_default();
8867 vty_out(vty
, "No BGP process is configured\n");
8869 vty_out(vty
, "{}\n");
8874 /* labeled-unicast routes live in the unicast table */
8875 if (safi
== SAFI_LABELED_UNICAST
)
8876 safi
= SAFI_UNICAST
;
8878 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8879 afi
, safi
, prd
, prefix_check
, pathtype
,
8883 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8884 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8887 struct lcommunity
*lcom
;
8893 b
= buffer_new(1024);
8894 for (i
= 0; i
< argc
; i
++) {
8896 buffer_putc(b
, ' ');
8898 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8900 buffer_putstr(b
, argv
[i
]->arg
);
8904 buffer_putc(b
, '\0');
8906 str
= buffer_getstr(b
);
8909 lcom
= lcommunity_str2com(str
);
8910 XFREE(MTYPE_TMP
, str
);
8912 vty_out(vty
, "%% Large-community malformed\n");
8916 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8920 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8921 const char *lcom
, afi_t afi
, safi_t safi
,
8924 struct community_list
*list
;
8926 list
= community_list_lookup(bgp_clist
, lcom
,
8927 LARGE_COMMUNITY_LIST_MASTER
);
8929 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8934 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8938 DEFUN (show_ip_bgp_large_community_list
,
8939 show_ip_bgp_large_community_list_cmd
,
8940 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8944 BGP_INSTANCE_HELP_STR
8946 BGP_SAFI_WITH_LABEL_HELP_STR
8947 "Display routes matching the large-community-list\n"
8948 "large-community-list number\n"
8949 "large-community-list name\n"
8953 afi_t afi
= AFI_IP6
;
8954 safi_t safi
= SAFI_UNICAST
;
8957 if (argv_find(argv
, argc
, "ip", &idx
))
8959 if (argv_find(argv
, argc
, "view", &idx
)
8960 || argv_find(argv
, argc
, "vrf", &idx
))
8961 vrf
= argv
[++idx
]->arg
;
8962 if (argv_find(argv
, argc
, "ipv4", &idx
)
8963 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8964 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8965 if (argv_find(argv
, argc
, "unicast", &idx
)
8966 || argv_find(argv
, argc
, "multicast", &idx
))
8967 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8970 int uj
= use_json(argc
, argv
);
8972 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8974 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8978 argv_find(argv
, argc
, "large-community-list", &idx
);
8979 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8982 DEFUN (show_ip_bgp_large_community
,
8983 show_ip_bgp_large_community_cmd
,
8984 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8988 BGP_INSTANCE_HELP_STR
8990 BGP_SAFI_WITH_LABEL_HELP_STR
8991 "Display routes matching the large-communities\n"
8992 "List of large-community numbers\n"
8996 afi_t afi
= AFI_IP6
;
8997 safi_t safi
= SAFI_UNICAST
;
9000 if (argv_find(argv
, argc
, "ip", &idx
))
9002 if (argv_find(argv
, argc
, "view", &idx
)
9003 || argv_find(argv
, argc
, "vrf", &idx
))
9004 vrf
= argv
[++idx
]->arg
;
9005 if (argv_find(argv
, argc
, "ipv4", &idx
)
9006 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9007 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9008 if (argv_find(argv
, argc
, "unicast", &idx
)
9009 || argv_find(argv
, argc
, "multicast", &idx
))
9010 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9013 int uj
= use_json(argc
, argv
);
9015 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9017 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9021 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9022 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9024 return bgp_show(vty
, bgp
, afi
, safi
,
9025 bgp_show_type_lcommunity_all
, NULL
, uj
);
9028 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9032 /* BGP route print out function without JSON */
9035 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9036 <dampening <parameters>\
9041 |community-list <(1-500)|WORD> [exact-match]\
9042 |A.B.C.D/M longer-prefixes\
9043 |X:X::X:X/M longer-prefixes\
9048 BGP_INSTANCE_HELP_STR
9050 BGP_SAFI_WITH_LABEL_HELP_STR
9051 "Display detailed information about dampening\n"
9052 "Display detail of configured dampening parameters\n"
9053 "Display routes matching the route-map\n"
9054 "A route-map to match on\n"
9055 "Display routes conforming to the prefix-list\n"
9056 "Prefix-list name\n"
9057 "Display routes conforming to the filter-list\n"
9058 "Regular expression access list name\n"
9059 "BGP RIB advertisement statistics\n"
9060 "Display routes matching the community-list\n"
9061 "community-list number\n"
9062 "community-list name\n"
9063 "Exact match of the communities\n"
9065 "Display route and more specific routes\n"
9067 "Display route and more specific routes\n")
9069 afi_t afi
= AFI_IP6
;
9070 safi_t safi
= SAFI_UNICAST
;
9071 int exact_match
= 0;
9072 struct bgp
*bgp
= NULL
;
9075 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9080 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9081 if (argv_find(argv
, argc
, "parameters", &idx
))
9082 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9085 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9086 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9087 safi
, bgp_show_type_prefix_list
);
9089 if (argv_find(argv
, argc
, "filter-list", &idx
))
9090 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9091 safi
, bgp_show_type_filter_list
);
9093 if (argv_find(argv
, argc
, "statistics", &idx
))
9094 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9096 if (argv_find(argv
, argc
, "route-map", &idx
))
9097 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9098 safi
, bgp_show_type_route_map
);
9100 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9101 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9102 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9104 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9105 exact_match
, afi
, safi
);
9108 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9109 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9110 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9112 bgp_show_type_prefix_longer
);
9117 /* BGP route print out function with JSON */
9118 DEFUN (show_ip_bgp_json
,
9119 show_ip_bgp_json_cmd
,
9120 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9123 |dampening <flap-statistics|dampened-paths>\
9124 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9129 BGP_INSTANCE_HELP_STR
9131 BGP_SAFI_WITH_LABEL_HELP_STR
9132 "Display only routes with non-natural netmasks\n"
9133 "Display detailed information about dampening\n"
9134 "Display flap statistics of routes\n"
9135 "Display paths suppressed due to dampening\n"
9136 "Display routes matching the communities\n"
9138 "Do not send outside local AS (well-known community)\n"
9139 "Do not advertise to any peer (well-known community)\n"
9140 "Do not export to next AS (well-known community)\n"
9141 "Graceful shutdown (well-known community)\n"
9142 "Exact match of the communities\n"
9145 afi_t afi
= AFI_IP6
;
9146 safi_t safi
= SAFI_UNICAST
;
9147 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9148 struct bgp
*bgp
= NULL
;
9150 int idx_community_type
= 0;
9151 int exact_match
= 0;
9153 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9158 int uj
= use_json(argc
, argv
);
9162 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9163 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9166 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9167 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9168 return bgp_show(vty
, bgp
, afi
, safi
,
9169 bgp_show_type_dampend_paths
, NULL
, uj
);
9170 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9171 return bgp_show(vty
, bgp
, afi
, safi
,
9172 bgp_show_type_flap_statistics
, NULL
,
9176 if (argv_find(argv
, argc
, "community", &idx
)) {
9178 /* show a specific community */
9179 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9180 argv_find(argv
, argc
, "no-advertise",
9181 &idx_community_type
) ||
9182 argv_find(argv
, argc
, "no-export",
9183 &idx_community_type
) ||
9184 argv_find(argv
, argc
, "graceful-shutdown",
9185 &idx_community_type
) ||
9186 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9187 if (argv_find(argv
, argc
, "exact-match", &idx
))
9190 return (bgp_show_community(vty
, bgp
,
9191 argv
[idx_community_type
]->arg
,
9192 exact_match
, afi
, safi
, uj
));
9195 /* show all communities */
9196 return (bgp_show(vty
, bgp
, afi
, safi
,
9197 bgp_show_type_community_all
, NULL
,
9202 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9205 DEFUN (show_ip_bgp_route
,
9206 show_ip_bgp_route_cmd
,
9207 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9208 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9212 BGP_INSTANCE_HELP_STR
9214 BGP_SAFI_WITH_LABEL_HELP_STR
9215 "Network in the BGP routing table to display\n"
9217 "Network in the BGP routing table to display\n"
9219 "Display only the bestpath\n"
9220 "Display only multipaths\n"
9223 int prefix_check
= 0;
9225 afi_t afi
= AFI_IP6
;
9226 safi_t safi
= SAFI_UNICAST
;
9227 char *prefix
= NULL
;
9228 struct bgp
*bgp
= NULL
;
9229 enum bgp_path_type path_type
;
9230 uint8_t uj
= use_json(argc
, argv
);
9234 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9241 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9245 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9246 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9247 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9249 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9250 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9253 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9254 && afi
!= AFI_IP6
) {
9256 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9259 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9262 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9266 prefix
= argv
[idx
]->arg
;
9268 /* [<bestpath|multipath>] */
9269 if (argv_find(argv
, argc
, "bestpath", &idx
))
9270 path_type
= BGP_PATH_BESTPATH
;
9271 else if (argv_find(argv
, argc
, "multipath", &idx
))
9272 path_type
= BGP_PATH_MULTIPATH
;
9274 path_type
= BGP_PATH_ALL
;
9276 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9280 DEFUN (show_ip_bgp_regexp
,
9281 show_ip_bgp_regexp_cmd
,
9282 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9286 BGP_INSTANCE_HELP_STR
9288 BGP_SAFI_WITH_LABEL_HELP_STR
9289 "Display routes matching the AS path regular expression\n"
9290 "A regular-expression to match the BGP AS paths\n")
9292 afi_t afi
= AFI_IP6
;
9293 safi_t safi
= SAFI_UNICAST
;
9294 struct bgp
*bgp
= NULL
;
9297 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9302 // get index of regex
9303 argv_find(argv
, argc
, "regexp", &idx
);
9306 char *regstr
= argv_concat(argv
, argc
, idx
);
9307 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9308 bgp_show_type_regexp
);
9309 XFREE(MTYPE_TMP
, regstr
);
9313 DEFUN (show_ip_bgp_instance_all
,
9314 show_ip_bgp_instance_all_cmd
,
9315 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9319 BGP_INSTANCE_ALL_HELP_STR
9321 BGP_SAFI_WITH_LABEL_HELP_STR
9325 safi_t safi
= SAFI_UNICAST
;
9326 struct bgp
*bgp
= NULL
;
9329 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9334 int uj
= use_json(argc
, argv
);
9338 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9342 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9343 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9348 regex
= bgp_regcomp(regstr
);
9350 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9354 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9355 bgp_regex_free(regex
);
9359 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9360 const char *prefix_list_str
, afi_t afi
,
9361 safi_t safi
, enum bgp_show_type type
)
9363 struct prefix_list
*plist
;
9365 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9366 if (plist
== NULL
) {
9367 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9372 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9375 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9376 const char *filter
, afi_t afi
, safi_t safi
,
9377 enum bgp_show_type type
)
9379 struct as_list
*as_list
;
9381 as_list
= as_list_lookup(filter
);
9382 if (as_list
== NULL
) {
9383 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9388 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9391 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9392 const char *rmap_str
, afi_t afi
, safi_t safi
,
9393 enum bgp_show_type type
)
9395 struct route_map
*rmap
;
9397 rmap
= route_map_lookup_by_name(rmap_str
);
9399 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9403 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9406 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9407 const char *comstr
, int exact
, afi_t afi
,
9408 safi_t safi
, uint8_t use_json
)
9410 struct community
*com
;
9413 com
= community_str2com(comstr
);
9415 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9419 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9420 (exact
? bgp_show_type_community_exact
9421 : bgp_show_type_community
),
9423 community_free(com
);
9428 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9429 const char *com
, int exact
, afi_t afi
,
9432 struct community_list
*list
;
9434 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9436 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9440 return bgp_show(vty
, bgp
, afi
, safi
,
9441 (exact
? bgp_show_type_community_list_exact
9442 : bgp_show_type_community_list
),
9446 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9447 const char *prefix
, afi_t afi
, safi_t safi
,
9448 enum bgp_show_type type
)
9455 ret
= str2prefix(prefix
, p
);
9457 vty_out(vty
, "%% Malformed Prefix\n");
9461 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9466 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9467 const char *ip_str
, uint8_t use_json
)
9473 /* Get peer sockunion. */
9474 ret
= str2sockunion(ip_str
, &su
);
9476 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9478 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9482 json_object
*json_no
= NULL
;
9483 json_no
= json_object_new_object();
9484 json_object_string_add(
9486 "malformedAddressOrName",
9488 vty_out(vty
, "%s\n",
9489 json_object_to_json_string_ext(
9491 JSON_C_TO_STRING_PRETTY
));
9492 json_object_free(json_no
);
9495 "%% Malformed address or name: %s\n",
9503 /* Peer structure lookup. */
9504 peer
= peer_lookup(bgp
, &su
);
9507 json_object
*json_no
= NULL
;
9508 json_no
= json_object_new_object();
9509 json_object_string_add(json_no
, "warning",
9510 "No such neighbor in this view/vrf");
9511 vty_out(vty
, "%s\n",
9512 json_object_to_json_string_ext(
9513 json_no
, JSON_C_TO_STRING_PRETTY
));
9514 json_object_free(json_no
);
9516 vty_out(vty
, "No such neighbor in this view/vrf\n");
9524 BGP_STATS_MAXBITLEN
= 0,
9528 BGP_STATS_UNAGGREGATEABLE
,
9529 BGP_STATS_MAX_AGGREGATEABLE
,
9530 BGP_STATS_AGGREGATES
,
9532 BGP_STATS_ASPATH_COUNT
,
9533 BGP_STATS_ASPATH_MAXHOPS
,
9534 BGP_STATS_ASPATH_TOTHOPS
,
9535 BGP_STATS_ASPATH_MAXSIZE
,
9536 BGP_STATS_ASPATH_TOTSIZE
,
9537 BGP_STATS_ASN_HIGHEST
,
9541 static const char *table_stats_strs
[] = {
9542 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9543 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9544 [BGP_STATS_RIB
] = "Total Advertisements",
9545 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9546 [BGP_STATS_MAX_AGGREGATEABLE
] =
9547 "Maximum aggregateable prefixes",
9548 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9549 [BGP_STATS_SPACE
] = "Address space advertised",
9550 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9551 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9552 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9553 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9554 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9555 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9556 [BGP_STATS_MAX
] = NULL
,
9559 struct bgp_table_stats
{
9560 struct bgp_table
*table
;
9561 unsigned long long counts
[BGP_STATS_MAX
];
9566 #define TALLY_SIGFIG 100000
9567 static unsigned long
9568 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9570 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9571 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9572 unsigned long ret
= newtot
/ count
;
9574 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9581 static int bgp_table_stats_walker(struct thread
*t
)
9583 struct bgp_node
*rn
;
9584 struct bgp_node
*top
;
9585 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9586 unsigned int space
= 0;
9588 if (!(top
= bgp_table_top(ts
->table
)))
9591 switch (top
->p
.family
) {
9593 space
= IPV4_MAX_BITLEN
;
9596 space
= IPV6_MAX_BITLEN
;
9600 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9602 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9603 struct bgp_info
*ri
;
9604 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9605 unsigned int rinum
= 0;
9613 ts
->counts
[BGP_STATS_PREFIXES
]++;
9614 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9617 ts
->counts
[BGP_STATS_AVGPLEN
]
9618 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9619 ts
->counts
[BGP_STATS_AVGPLEN
],
9623 /* check if the prefix is included by any other announcements */
9624 while (prn
&& !prn
->info
)
9625 prn
= bgp_node_parent_nolock(prn
);
9627 if (prn
== NULL
|| prn
== top
) {
9628 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9629 /* announced address space */
9632 pow(2.0, space
- rn
->p
.prefixlen
);
9633 } else if (prn
->info
)
9634 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9636 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9638 ts
->counts
[BGP_STATS_RIB
]++;
9641 && (CHECK_FLAG(ri
->attr
->flag
,
9643 BGP_ATTR_ATOMIC_AGGREGATE
))))
9644 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9647 if (ri
->attr
&& ri
->attr
->aspath
) {
9649 aspath_count_hops(ri
->attr
->aspath
);
9651 aspath_size(ri
->attr
->aspath
);
9652 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9654 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9656 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9657 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9660 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9661 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9664 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9665 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9667 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9668 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9669 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9671 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9672 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9673 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9676 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9677 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9685 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9688 struct bgp_table_stats ts
;
9691 if (!bgp
->rib
[afi
][safi
]) {
9692 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9697 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9699 /* labeled-unicast routes live in the unicast table */
9700 if (safi
== SAFI_LABELED_UNICAST
)
9701 safi
= SAFI_UNICAST
;
9703 memset(&ts
, 0, sizeof(ts
));
9704 ts
.table
= bgp
->rib
[afi
][safi
];
9705 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9707 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9708 if (!table_stats_strs
[i
])
9713 case BGP_STATS_ASPATH_AVGHOPS
:
9714 case BGP_STATS_ASPATH_AVGSIZE
:
9715 case BGP_STATS_AVGPLEN
:
9716 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9717 vty_out (vty
, "%12.2f",
9718 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9721 case BGP_STATS_ASPATH_TOTHOPS
:
9722 case BGP_STATS_ASPATH_TOTSIZE
:
9723 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9724 vty_out(vty
, "%12.2f",
9726 ? (float)ts
.counts
[i
]
9728 [BGP_STATS_ASPATH_COUNT
]
9731 case BGP_STATS_TOTPLEN
:
9732 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9733 vty_out(vty
, "%12.2f",
9735 ? (float)ts
.counts
[i
]
9737 [BGP_STATS_PREFIXES
]
9740 case BGP_STATS_SPACE
:
9741 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9742 vty_out(vty
, "%12g\n", ts
.total_space
);
9744 if (afi
== AFI_IP6
) {
9745 vty_out(vty
, "%30s: ", "/32 equivalent ");
9746 vty_out(vty
, "%12g\n",
9747 ts
.total_space
* pow(2.0, -128 + 32));
9748 vty_out(vty
, "%30s: ", "/48 equivalent ");
9749 vty_out(vty
, "%12g\n",
9750 ts
.total_space
* pow(2.0, -128 + 48));
9752 vty_out(vty
, "%30s: ", "% announced ");
9753 vty_out(vty
, "%12.2f\n",
9754 ts
.total_space
* 100. * pow(2.0, -32));
9755 vty_out(vty
, "%30s: ", "/8 equivalent ");
9756 vty_out(vty
, "%12.2f\n",
9757 ts
.total_space
* pow(2.0, -32 + 8));
9758 vty_out(vty
, "%30s: ", "/24 equivalent ");
9759 vty_out(vty
, "%12.2f\n",
9760 ts
.total_space
* pow(2.0, -32 + 24));
9764 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9765 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9782 PCOUNT_PFCNT
, /* the figure we display to users */
9786 static const char *pcount_strs
[] = {
9787 [PCOUNT_ADJ_IN
] = "Adj-in",
9788 [PCOUNT_DAMPED
] = "Damped",
9789 [PCOUNT_REMOVED
] = "Removed",
9790 [PCOUNT_HISTORY
] = "History",
9791 [PCOUNT_STALE
] = "Stale",
9792 [PCOUNT_VALID
] = "Valid",
9793 [PCOUNT_ALL
] = "All RIB",
9794 [PCOUNT_COUNTED
] = "PfxCt counted",
9795 [PCOUNT_PFCNT
] = "Useable",
9796 [PCOUNT_MAX
] = NULL
,
9799 struct peer_pcounts
{
9800 unsigned int count
[PCOUNT_MAX
];
9801 const struct peer
*peer
;
9802 const struct bgp_table
*table
;
9805 static int bgp_peer_count_walker(struct thread
*t
)
9807 struct bgp_node
*rn
;
9808 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9809 const struct peer
*peer
= pc
->peer
;
9811 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9812 struct bgp_adj_in
*ain
;
9813 struct bgp_info
*ri
;
9815 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9816 if (ain
->peer
== peer
)
9817 pc
->count
[PCOUNT_ADJ_IN
]++;
9819 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9820 char buf
[SU_ADDRSTRLEN
];
9822 if (ri
->peer
!= peer
)
9825 pc
->count
[PCOUNT_ALL
]++;
9827 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9828 pc
->count
[PCOUNT_DAMPED
]++;
9829 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9830 pc
->count
[PCOUNT_HISTORY
]++;
9831 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9832 pc
->count
[PCOUNT_REMOVED
]++;
9833 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9834 pc
->count
[PCOUNT_STALE
]++;
9835 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9836 pc
->count
[PCOUNT_VALID
]++;
9837 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9838 pc
->count
[PCOUNT_PFCNT
]++;
9840 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9841 pc
->count
[PCOUNT_COUNTED
]++;
9842 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9844 "%s [pcount] %s/%d is counted but flags 0x%x",
9846 inet_ntop(rn
->p
.family
,
9847 &rn
->p
.u
.prefix
, buf
,
9849 rn
->p
.prefixlen
, ri
->flags
);
9851 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9853 "%s [pcount] %s/%d not counted but flags 0x%x",
9855 inet_ntop(rn
->p
.family
,
9856 &rn
->p
.u
.prefix
, buf
,
9858 rn
->p
.prefixlen
, ri
->flags
);
9865 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9866 safi_t safi
, uint8_t use_json
)
9868 struct peer_pcounts pcounts
= {.peer
= peer
};
9870 json_object
*json
= NULL
;
9871 json_object
*json_loop
= NULL
;
9874 json
= json_object_new_object();
9875 json_loop
= json_object_new_object();
9878 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9879 || !peer
->bgp
->rib
[afi
][safi
]) {
9881 json_object_string_add(
9883 "No such neighbor or address family");
9884 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9885 json_object_free(json
);
9887 vty_out(vty
, "%% No such neighbor or address family\n");
9892 memset(&pcounts
, 0, sizeof(pcounts
));
9893 pcounts
.peer
= peer
;
9894 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9896 /* in-place call via thread subsystem so as to record execution time
9897 * stats for the thread-walk (i.e. ensure this can't be blamed on
9898 * on just vty_read()).
9900 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9903 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9904 json_object_string_add(json
, "multiProtocol",
9905 afi_safi_print(afi
, safi
));
9906 json_object_int_add(json
, "pfxCounter",
9907 peer
->pcount
[afi
][safi
]);
9909 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9910 json_object_int_add(json_loop
, pcount_strs
[i
],
9913 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9915 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9916 json_object_string_add(json
, "pfxctDriftFor",
9918 json_object_string_add(
9919 json
, "recommended",
9920 "Please report this bug, with the above command output");
9922 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9923 json
, JSON_C_TO_STRING_PRETTY
));
9924 json_object_free(json
);
9928 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9929 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9930 peer
->hostname
, peer
->host
,
9931 afi_safi_print(afi
, safi
));
9933 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9934 afi_safi_print(afi
, safi
));
9937 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9938 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9940 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9941 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9944 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9945 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9947 "Please report this bug, with the above command output\n");
9954 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9955 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9957 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9961 BGP_INSTANCE_HELP_STR
9964 "Detailed information on TCP and BGP neighbor connections\n"
9965 "Neighbor to display information about\n"
9966 "Neighbor to display information about\n"
9967 "Neighbor on BGP configured interface\n"
9968 "Display detailed prefix count information\n"
9971 afi_t afi
= AFI_IP6
;
9972 safi_t safi
= SAFI_UNICAST
;
9975 struct bgp
*bgp
= NULL
;
9977 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9982 int uj
= use_json(argc
, argv
);
9986 argv_find(argv
, argc
, "neighbors", &idx
);
9987 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9991 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9994 #ifdef KEEP_OLD_VPN_COMMANDS
9995 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9996 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9997 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10002 "Display information about all VPNv4 NLRIs\n"
10003 "Detailed information on TCP and BGP neighbor connections\n"
10004 "Neighbor to display information about\n"
10005 "Neighbor to display information about\n"
10006 "Neighbor on BGP configured interface\n"
10007 "Display detailed prefix count information\n"
10012 uint8_t uj
= use_json(argc
, argv
);
10014 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10016 return CMD_WARNING
;
10018 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10021 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10022 show_ip_bgp_vpn_all_route_prefix_cmd
,
10023 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10028 "Display information about all VPNv4 NLRIs\n"
10029 "Network in the BGP routing table to display\n"
10030 "Network in the BGP routing table to display\n"
10034 char *network
= NULL
;
10035 struct bgp
*bgp
= bgp_get_default();
10037 vty_out(vty
, "Can't find default instance\n");
10038 return CMD_WARNING
;
10041 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10042 network
= argv
[idx
]->arg
;
10043 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10044 network
= argv
[idx
]->arg
;
10046 vty_out(vty
, "Unable to figure out Network\n");
10047 return CMD_WARNING
;
10050 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10051 BGP_PATH_ALL
, use_json(argc
, argv
));
10053 #endif /* KEEP_OLD_VPN_COMMANDS */
10055 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10056 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10057 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10063 "Display information about all EVPN NLRIs\n"
10064 "Network in the BGP routing table to display\n"
10065 "Network in the BGP routing table to display\n"
10069 char *network
= NULL
;
10071 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10072 network
= argv
[idx
]->arg
;
10073 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10074 network
= argv
[idx
]->arg
;
10076 vty_out(vty
, "Unable to figure out Network\n");
10077 return CMD_WARNING
;
10079 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10080 BGP_PATH_ALL
, use_json(argc
, argv
));
10083 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10084 safi_t safi
, enum bgp_show_adj_route_type type
,
10085 const char *rmap_name
, uint8_t use_json
,
10088 struct bgp_table
*table
;
10089 struct bgp_adj_in
*ain
;
10090 struct bgp_adj_out
*adj
;
10091 unsigned long output_count
;
10092 unsigned long filtered_count
;
10093 struct bgp_node
*rn
;
10099 struct update_subgroup
*subgrp
;
10100 json_object
*json_scode
= NULL
;
10101 json_object
*json_ocode
= NULL
;
10102 json_object
*json_ar
= NULL
;
10103 struct peer_af
*paf
;
10106 json_scode
= json_object_new_object();
10107 json_ocode
= json_object_new_object();
10108 json_ar
= json_object_new_object();
10110 json_object_string_add(json_scode
, "suppressed", "s");
10111 json_object_string_add(json_scode
, "damped", "d");
10112 json_object_string_add(json_scode
, "history", "h");
10113 json_object_string_add(json_scode
, "valid", "*");
10114 json_object_string_add(json_scode
, "best", ">");
10115 json_object_string_add(json_scode
, "multipath", "=");
10116 json_object_string_add(json_scode
, "internal", "i");
10117 json_object_string_add(json_scode
, "ribFailure", "r");
10118 json_object_string_add(json_scode
, "stale", "S");
10119 json_object_string_add(json_scode
, "removed", "R");
10121 json_object_string_add(json_ocode
, "igp", "i");
10122 json_object_string_add(json_ocode
, "egp", "e");
10123 json_object_string_add(json_ocode
, "incomplete", "?");
10130 json_object_string_add(json
, "alert", "no BGP");
10131 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10132 json_object_free(json
);
10134 vty_out(vty
, "%% No bgp\n");
10138 table
= bgp
->rib
[afi
][safi
];
10140 output_count
= filtered_count
= 0;
10141 subgrp
= peer_subgroup(peer
, afi
, safi
);
10143 if (type
== bgp_show_adj_route_advertised
&& subgrp
10144 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10146 json_object_int_add(json
, "bgpTableVersion",
10148 json_object_string_add(json
, "bgpLocalRouterId",
10149 inet_ntoa(bgp
->router_id
));
10150 json_object_object_add(json
, "bgpStatusCodes",
10152 json_object_object_add(json
, "bgpOriginCodes",
10154 json_object_string_add(json
,
10155 "bgpOriginatingDefaultNetwork",
10158 vty_out(vty
, "BGP table version is %" PRIu64
10159 ", local router ID is %s, vrf id ",
10160 table
->version
, inet_ntoa(bgp
->router_id
));
10161 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10162 vty_out(vty
, "%s", VRFID_NONE_STR
);
10164 vty_out(vty
, "%u", bgp
->vrf_id
);
10165 vty_out(vty
, "\n");
10166 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10167 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10168 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10170 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10175 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10176 if (type
== bgp_show_adj_route_received
10177 || type
== bgp_show_adj_route_filtered
) {
10178 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10179 if (ain
->peer
!= peer
|| !ain
->attr
)
10184 json_object_int_add(
10185 json
, "bgpTableVersion",
10187 json_object_string_add(
10189 "bgpLocalRouterId",
10192 json_object_object_add(
10193 json
, "bgpStatusCodes",
10195 json_object_object_add(
10196 json
, "bgpOriginCodes",
10200 "BGP table version is 0, local router ID is %s, vrf id ",
10203 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10209 vty_out(vty
, "\n");
10211 BGP_SHOW_SCODE_HEADER
);
10213 BGP_SHOW_NCODE_HEADER
);
10215 BGP_SHOW_OCODE_HEADER
);
10221 vty_out(vty
, BGP_SHOW_HEADER
);
10225 bgp_attr_dup(&attr
, ain
->attr
);
10226 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10227 afi
, safi
, rmap_name
);
10229 if (type
== bgp_show_adj_route_filtered
10230 && ret
!= RMAP_DENY
) {
10231 bgp_attr_undup(&attr
, ain
->attr
);
10235 if (type
== bgp_show_adj_route_received
10236 && ret
== RMAP_DENY
)
10239 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10240 use_json
, json_ar
);
10241 bgp_attr_undup(&attr
, ain
->attr
);
10244 } else if (type
== bgp_show_adj_route_advertised
) {
10245 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10246 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10247 if (paf
->peer
!= peer
|| !adj
->attr
)
10252 json_object_int_add(
10256 json_object_string_add(
10258 "bgpLocalRouterId",
10261 json_object_object_add(
10265 json_object_object_add(
10271 "BGP table version is %" PRIu64
10272 ", local router ID is %s, vrf id ",
10285 vty_out(vty
, "\n");
10287 BGP_SHOW_SCODE_HEADER
);
10289 BGP_SHOW_NCODE_HEADER
);
10291 BGP_SHOW_OCODE_HEADER
);
10302 bgp_attr_dup(&attr
, adj
->attr
);
10303 ret
= bgp_output_modifier(
10304 peer
, &rn
->p
, &attr
, afi
, safi
,
10307 if (ret
!= RMAP_DENY
) {
10308 route_vty_out_tmp(vty
, &rn
->p
,
10317 bgp_attr_undup(&attr
, adj
->attr
);
10323 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10324 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10325 json_object_int_add(json
, "filteredPrefixCounter",
10328 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10329 json
, JSON_C_TO_STRING_PRETTY
));
10330 json_object_free(json
);
10331 } else if (output_count
> 0) {
10332 if (filtered_count
> 0)
10334 "\nTotal number of prefixes %ld (%ld filtered)\n",
10335 output_count
, filtered_count
);
10337 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10342 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10343 safi_t safi
, enum bgp_show_adj_route_type type
,
10344 const char *rmap_name
, uint8_t use_json
)
10346 json_object
*json
= NULL
;
10349 json
= json_object_new_object();
10351 /* labeled-unicast routes live in the unicast table */
10352 if (safi
== SAFI_LABELED_UNICAST
)
10353 safi
= SAFI_UNICAST
;
10355 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10357 json_object_string_add(
10359 "No such neighbor or address family");
10360 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10361 json_object_free(json
);
10363 vty_out(vty
, "%% No such neighbor or address family\n");
10365 return CMD_WARNING
;
10368 if ((type
== bgp_show_adj_route_received
10369 || type
== bgp_show_adj_route_filtered
)
10370 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10371 PEER_FLAG_SOFT_RECONFIG
)) {
10373 json_object_string_add(
10375 "Inbound soft reconfiguration not enabled");
10376 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10377 json_object_free(json
);
10380 "%% Inbound soft reconfiguration not enabled\n");
10382 return CMD_WARNING
;
10385 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10387 return CMD_SUCCESS
;
10390 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10391 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10392 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10393 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10397 BGP_INSTANCE_HELP_STR
10399 BGP_SAFI_WITH_LABEL_HELP_STR
10400 "Detailed information on TCP and BGP neighbor connections\n"
10401 "Neighbor to display information about\n"
10402 "Neighbor to display information about\n"
10403 "Neighbor on BGP configured interface\n"
10404 "Display the routes advertised to a BGP neighbor\n"
10405 "Display the received routes from neighbor\n"
10406 "Display the filtered routes received from neighbor\n"
10407 "Route-map to modify the attributes\n"
10408 "Name of the route map\n"
10411 afi_t afi
= AFI_IP6
;
10412 safi_t safi
= SAFI_UNICAST
;
10413 char *rmap_name
= NULL
;
10414 char *peerstr
= NULL
;
10415 struct bgp
*bgp
= NULL
;
10417 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10420 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10423 return CMD_WARNING
;
10425 int uj
= use_json(argc
, argv
);
10430 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10431 argv_find(argv
, argc
, "neighbors", &idx
);
10432 peerstr
= argv
[++idx
]->arg
;
10434 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10436 return CMD_WARNING
;
10438 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10439 type
= bgp_show_adj_route_advertised
;
10440 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10441 type
= bgp_show_adj_route_received
;
10442 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10443 type
= bgp_show_adj_route_filtered
;
10445 if (argv_find(argv
, argc
, "route-map", &idx
))
10446 rmap_name
= argv
[++idx
]->arg
;
10448 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10451 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10452 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10453 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10459 "Address Family modifier\n"
10460 "Detailed information on TCP and BGP neighbor connections\n"
10461 "Neighbor to display information about\n"
10462 "Neighbor to display information about\n"
10463 "Neighbor on BGP configured interface\n"
10464 "Display information received from a BGP neighbor\n"
10465 "Display the prefixlist filter\n"
10468 afi_t afi
= AFI_IP6
;
10469 safi_t safi
= SAFI_UNICAST
;
10470 char *peerstr
= NULL
;
10473 union sockunion su
;
10479 /* show [ip] bgp */
10480 if (argv_find(argv
, argc
, "ip", &idx
))
10482 /* [<ipv4|ipv6> [unicast]] */
10483 if (argv_find(argv
, argc
, "ipv4", &idx
))
10485 if (argv_find(argv
, argc
, "ipv6", &idx
))
10487 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10488 argv_find(argv
, argc
, "neighbors", &idx
);
10489 peerstr
= argv
[++idx
]->arg
;
10491 uint8_t uj
= use_json(argc
, argv
);
10493 ret
= str2sockunion(peerstr
, &su
);
10495 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10498 vty_out(vty
, "{}\n");
10501 "%% Malformed address or name: %s\n",
10503 return CMD_WARNING
;
10506 peer
= peer_lookup(NULL
, &su
);
10509 vty_out(vty
, "{}\n");
10511 vty_out(vty
, "No peer\n");
10512 return CMD_WARNING
;
10516 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10517 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10520 vty_out(vty
, "Address Family: %s\n",
10521 afi_safi_print(afi
, safi
));
10522 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10525 vty_out(vty
, "{}\n");
10527 vty_out(vty
, "No functional output\n");
10530 return CMD_SUCCESS
;
10533 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10534 afi_t afi
, safi_t safi
,
10535 enum bgp_show_type type
, uint8_t use_json
)
10537 /* labeled-unicast routes live in the unicast table */
10538 if (safi
== SAFI_LABELED_UNICAST
)
10539 safi
= SAFI_UNICAST
;
10541 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10543 json_object
*json_no
= NULL
;
10544 json_no
= json_object_new_object();
10545 json_object_string_add(
10546 json_no
, "warning",
10547 "No such neighbor or address family");
10548 vty_out(vty
, "%s\n",
10549 json_object_to_json_string(json_no
));
10550 json_object_free(json_no
);
10552 vty_out(vty
, "%% No such neighbor or address family\n");
10553 return CMD_WARNING
;
10556 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10559 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10560 show_ip_bgp_flowspec_routes_detailed_cmd
,
10561 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10565 BGP_INSTANCE_HELP_STR
10568 "Detailed information on flowspec entries\n"
10571 afi_t afi
= AFI_IP
;
10572 safi_t safi
= SAFI_UNICAST
;
10573 struct bgp
*bgp
= NULL
;
10576 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10579 return CMD_WARNING
;
10581 return bgp_show(vty
, bgp
, afi
, safi
,
10582 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10585 DEFUN (show_ip_bgp_neighbor_routes
,
10586 show_ip_bgp_neighbor_routes_cmd
,
10587 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10588 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10592 BGP_INSTANCE_HELP_STR
10594 BGP_SAFI_WITH_LABEL_HELP_STR
10595 "Detailed information on TCP and BGP neighbor connections\n"
10596 "Neighbor to display information about\n"
10597 "Neighbor to display information about\n"
10598 "Neighbor on BGP configured interface\n"
10599 "Display flap statistics of the routes learned from neighbor\n"
10600 "Display the dampened routes received from neighbor\n"
10601 "Display routes learned from neighbor\n"
10604 char *peerstr
= NULL
;
10605 struct bgp
*bgp
= NULL
;
10606 afi_t afi
= AFI_IP6
;
10607 safi_t safi
= SAFI_UNICAST
;
10609 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10613 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10616 return CMD_WARNING
;
10618 int uj
= use_json(argc
, argv
);
10622 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10623 argv_find(argv
, argc
, "neighbors", &idx
);
10624 peerstr
= argv
[++idx
]->arg
;
10626 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10628 return CMD_WARNING
;
10630 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10631 sh_type
= bgp_show_type_flap_neighbor
;
10632 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10633 sh_type
= bgp_show_type_damp_neighbor
;
10634 else if (argv_find(argv
, argc
, "routes", &idx
))
10635 sh_type
= bgp_show_type_neighbor
;
10637 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10640 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10642 struct bgp_distance
{
10643 /* Distance value for the IP source prefix. */
10646 /* Name of the access-list to be matched. */
10650 DEFUN (show_bgp_afi_vpn_rd_route
,
10651 show_bgp_afi_vpn_rd_route_cmd
,
10652 "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]",
10656 "Address Family modifier\n"
10657 "Display information for a route distinguisher\n"
10658 "Route Distinguisher\n"
10659 "Network in the BGP routing table to display\n"
10660 "Network in the BGP routing table to display\n"
10664 struct prefix_rd prd
;
10665 afi_t afi
= AFI_MAX
;
10668 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10669 vty_out(vty
, "%% Malformed Address Family\n");
10670 return CMD_WARNING
;
10673 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10675 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10676 return CMD_WARNING
;
10679 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10680 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10683 static struct bgp_distance
*bgp_distance_new(void)
10685 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10688 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10690 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10693 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10694 const char *ip_str
, const char *access_list_str
)
10701 struct bgp_node
*rn
;
10702 struct bgp_distance
*bdistance
;
10704 afi
= bgp_node_afi(vty
);
10705 safi
= bgp_node_safi(vty
);
10707 ret
= str2prefix(ip_str
, &p
);
10709 vty_out(vty
, "Malformed prefix\n");
10710 return CMD_WARNING_CONFIG_FAILED
;
10713 distance
= atoi(distance_str
);
10715 /* Get BGP distance node. */
10716 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10718 bdistance
= rn
->info
;
10719 bgp_unlock_node(rn
);
10721 bdistance
= bgp_distance_new();
10722 rn
->info
= bdistance
;
10725 /* Set distance value. */
10726 bdistance
->distance
= distance
;
10728 /* Reset access-list configuration. */
10729 if (bdistance
->access_list
) {
10730 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10731 bdistance
->access_list
= NULL
;
10733 if (access_list_str
)
10734 bdistance
->access_list
=
10735 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10737 return CMD_SUCCESS
;
10740 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10741 const char *ip_str
, const char *access_list_str
)
10748 struct bgp_node
*rn
;
10749 struct bgp_distance
*bdistance
;
10751 afi
= bgp_node_afi(vty
);
10752 safi
= bgp_node_safi(vty
);
10754 ret
= str2prefix(ip_str
, &p
);
10756 vty_out(vty
, "Malformed prefix\n");
10757 return CMD_WARNING_CONFIG_FAILED
;
10760 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10761 (struct prefix
*)&p
);
10763 vty_out(vty
, "Can't find specified prefix\n");
10764 return CMD_WARNING_CONFIG_FAILED
;
10767 bdistance
= rn
->info
;
10768 distance
= atoi(distance_str
);
10770 if (bdistance
->distance
!= distance
) {
10771 vty_out(vty
, "Distance does not match configured\n");
10772 return CMD_WARNING_CONFIG_FAILED
;
10775 if (bdistance
->access_list
)
10776 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10777 bgp_distance_free(bdistance
);
10780 bgp_unlock_node(rn
);
10781 bgp_unlock_node(rn
);
10783 return CMD_SUCCESS
;
10786 /* Apply BGP information to distance method. */
10787 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10788 safi_t safi
, struct bgp
*bgp
)
10790 struct bgp_node
*rn
;
10793 struct bgp_distance
*bdistance
;
10794 struct access_list
*alist
;
10795 struct bgp_static
*bgp_static
;
10800 peer
= rinfo
->peer
;
10802 /* Check source address. */
10803 sockunion2hostprefix(&peer
->su
, &q
);
10804 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10806 bdistance
= rn
->info
;
10807 bgp_unlock_node(rn
);
10809 if (bdistance
->access_list
) {
10810 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10812 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10813 return bdistance
->distance
;
10815 return bdistance
->distance
;
10818 /* Backdoor check. */
10819 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10821 bgp_static
= rn
->info
;
10822 bgp_unlock_node(rn
);
10824 if (bgp_static
->backdoor
) {
10825 if (bgp
->distance_local
[afi
][safi
])
10826 return bgp
->distance_local
[afi
][safi
];
10828 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10832 if (peer
->sort
== BGP_PEER_EBGP
) {
10833 if (bgp
->distance_ebgp
[afi
][safi
])
10834 return bgp
->distance_ebgp
[afi
][safi
];
10835 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10837 if (bgp
->distance_ibgp
[afi
][safi
])
10838 return bgp
->distance_ibgp
[afi
][safi
];
10839 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10843 DEFUN (bgp_distance
,
10845 "distance bgp (1-255) (1-255) (1-255)",
10846 "Define an administrative distance\n"
10848 "Distance for routes external to the AS\n"
10849 "Distance for routes internal to the AS\n"
10850 "Distance for local routes\n")
10852 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10853 int idx_number
= 2;
10854 int idx_number_2
= 3;
10855 int idx_number_3
= 4;
10859 afi
= bgp_node_afi(vty
);
10860 safi
= bgp_node_safi(vty
);
10862 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10863 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10864 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10865 return CMD_SUCCESS
;
10868 DEFUN (no_bgp_distance
,
10869 no_bgp_distance_cmd
,
10870 "no distance bgp [(1-255) (1-255) (1-255)]",
10872 "Define an administrative distance\n"
10874 "Distance for routes external to the AS\n"
10875 "Distance for routes internal to the AS\n"
10876 "Distance for local routes\n")
10878 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10882 afi
= bgp_node_afi(vty
);
10883 safi
= bgp_node_safi(vty
);
10885 bgp
->distance_ebgp
[afi
][safi
] = 0;
10886 bgp
->distance_ibgp
[afi
][safi
] = 0;
10887 bgp
->distance_local
[afi
][safi
] = 0;
10888 return CMD_SUCCESS
;
10892 DEFUN (bgp_distance_source
,
10893 bgp_distance_source_cmd
,
10894 "distance (1-255) A.B.C.D/M",
10895 "Define an administrative distance\n"
10896 "Administrative distance\n"
10897 "IP source prefix\n")
10899 int idx_number
= 1;
10900 int idx_ipv4_prefixlen
= 2;
10901 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10902 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10903 return CMD_SUCCESS
;
10906 DEFUN (no_bgp_distance_source
,
10907 no_bgp_distance_source_cmd
,
10908 "no distance (1-255) A.B.C.D/M",
10910 "Define an administrative distance\n"
10911 "Administrative distance\n"
10912 "IP source prefix\n")
10914 int idx_number
= 2;
10915 int idx_ipv4_prefixlen
= 3;
10916 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10917 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10918 return CMD_SUCCESS
;
10921 DEFUN (bgp_distance_source_access_list
,
10922 bgp_distance_source_access_list_cmd
,
10923 "distance (1-255) A.B.C.D/M WORD",
10924 "Define an administrative distance\n"
10925 "Administrative distance\n"
10926 "IP source prefix\n"
10927 "Access list name\n")
10929 int idx_number
= 1;
10930 int idx_ipv4_prefixlen
= 2;
10932 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10933 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10934 return CMD_SUCCESS
;
10937 DEFUN (no_bgp_distance_source_access_list
,
10938 no_bgp_distance_source_access_list_cmd
,
10939 "no distance (1-255) A.B.C.D/M WORD",
10941 "Define an administrative distance\n"
10942 "Administrative distance\n"
10943 "IP source prefix\n"
10944 "Access list name\n")
10946 int idx_number
= 2;
10947 int idx_ipv4_prefixlen
= 3;
10949 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10950 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10951 return CMD_SUCCESS
;
10954 DEFUN (ipv6_bgp_distance_source
,
10955 ipv6_bgp_distance_source_cmd
,
10956 "distance (1-255) X:X::X:X/M",
10957 "Define an administrative distance\n"
10958 "Administrative distance\n"
10959 "IP source prefix\n")
10961 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10962 return CMD_SUCCESS
;
10965 DEFUN (no_ipv6_bgp_distance_source
,
10966 no_ipv6_bgp_distance_source_cmd
,
10967 "no distance (1-255) X:X::X:X/M",
10969 "Define an administrative distance\n"
10970 "Administrative distance\n"
10971 "IP source prefix\n")
10973 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10974 return CMD_SUCCESS
;
10977 DEFUN (ipv6_bgp_distance_source_access_list
,
10978 ipv6_bgp_distance_source_access_list_cmd
,
10979 "distance (1-255) X:X::X:X/M WORD",
10980 "Define an administrative distance\n"
10981 "Administrative distance\n"
10982 "IP source prefix\n"
10983 "Access list name\n")
10985 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10986 return CMD_SUCCESS
;
10989 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10990 no_ipv6_bgp_distance_source_access_list_cmd
,
10991 "no distance (1-255) X:X::X:X/M WORD",
10993 "Define an administrative distance\n"
10994 "Administrative distance\n"
10995 "IP source prefix\n"
10996 "Access list name\n")
10998 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10999 return CMD_SUCCESS
;
11002 DEFUN (bgp_damp_set
,
11004 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11005 "BGP Specific commands\n"
11006 "Enable route-flap dampening\n"
11007 "Half-life time for the penalty\n"
11008 "Value to start reusing a route\n"
11009 "Value to start suppressing a route\n"
11010 "Maximum duration to suppress a stable route\n")
11012 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11013 int idx_half_life
= 2;
11015 int idx_suppress
= 4;
11016 int idx_max_suppress
= 5;
11017 int half
= DEFAULT_HALF_LIFE
* 60;
11018 int reuse
= DEFAULT_REUSE
;
11019 int suppress
= DEFAULT_SUPPRESS
;
11020 int max
= 4 * half
;
11023 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11024 reuse
= atoi(argv
[idx_reuse
]->arg
);
11025 suppress
= atoi(argv
[idx_suppress
]->arg
);
11026 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11027 } else if (argc
== 3) {
11028 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11032 if (suppress
< reuse
) {
11034 "Suppress value cannot be less than reuse value \n");
11038 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11039 reuse
, suppress
, max
);
11042 DEFUN (bgp_damp_unset
,
11043 bgp_damp_unset_cmd
,
11044 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11046 "BGP Specific commands\n"
11047 "Enable route-flap dampening\n"
11048 "Half-life time for the penalty\n"
11049 "Value to start reusing a route\n"
11050 "Value to start suppressing a route\n"
11051 "Maximum duration to suppress a stable route\n")
11053 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11054 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11057 /* Display specified route of BGP table. */
11058 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11059 const char *ip_str
, afi_t afi
, safi_t safi
,
11060 struct prefix_rd
*prd
, int prefix_check
)
11063 struct prefix match
;
11064 struct bgp_node
*rn
;
11065 struct bgp_node
*rm
;
11066 struct bgp_info
*ri
;
11067 struct bgp_info
*ri_temp
;
11069 struct bgp_table
*table
;
11071 /* BGP structure lookup. */
11073 bgp
= bgp_lookup_by_name(view_name
);
11075 vty_out(vty
, "%% Can't find BGP instance %s\n",
11077 return CMD_WARNING
;
11080 bgp
= bgp_get_default();
11082 vty_out(vty
, "%% No BGP process is configured\n");
11083 return CMD_WARNING
;
11087 /* Check IP address argument. */
11088 ret
= str2prefix(ip_str
, &match
);
11090 vty_out(vty
, "%% address is malformed\n");
11091 return CMD_WARNING
;
11094 match
.family
= afi2family(afi
);
11096 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11097 || (safi
== SAFI_EVPN
)) {
11098 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11099 rn
= bgp_route_next(rn
)) {
11100 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11102 if ((table
= rn
->info
) == NULL
)
11104 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11108 || rm
->p
.prefixlen
== match
.prefixlen
) {
11111 if (ri
->extra
&& ri
->extra
->damp_info
) {
11112 ri_temp
= ri
->next
;
11113 bgp_damp_info_free(
11114 ri
->extra
->damp_info
,
11122 bgp_unlock_node(rm
);
11125 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11128 || rn
->p
.prefixlen
== match
.prefixlen
) {
11131 if (ri
->extra
&& ri
->extra
->damp_info
) {
11132 ri_temp
= ri
->next
;
11133 bgp_damp_info_free(
11134 ri
->extra
->damp_info
,
11142 bgp_unlock_node(rn
);
11146 return CMD_SUCCESS
;
11149 DEFUN (clear_ip_bgp_dampening
,
11150 clear_ip_bgp_dampening_cmd
,
11151 "clear ip bgp dampening",
11155 "Clear route flap dampening information\n")
11157 bgp_damp_info_clean();
11158 return CMD_SUCCESS
;
11161 DEFUN (clear_ip_bgp_dampening_prefix
,
11162 clear_ip_bgp_dampening_prefix_cmd
,
11163 "clear ip bgp dampening A.B.C.D/M",
11167 "Clear route flap dampening information\n"
11170 int idx_ipv4_prefixlen
= 4;
11171 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11172 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11175 DEFUN (clear_ip_bgp_dampening_address
,
11176 clear_ip_bgp_dampening_address_cmd
,
11177 "clear ip bgp dampening A.B.C.D",
11181 "Clear route flap dampening information\n"
11182 "Network to clear damping information\n")
11185 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11186 SAFI_UNICAST
, NULL
, 0);
11189 DEFUN (clear_ip_bgp_dampening_address_mask
,
11190 clear_ip_bgp_dampening_address_mask_cmd
,
11191 "clear ip bgp dampening A.B.C.D A.B.C.D",
11195 "Clear route flap dampening information\n"
11196 "Network to clear damping information\n"
11200 int idx_ipv4_2
= 5;
11202 char prefix_str
[BUFSIZ
];
11204 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11207 vty_out(vty
, "%% Inconsistent address and mask\n");
11208 return CMD_WARNING
;
11211 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11215 /* also used for encap safi */
11216 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11217 afi_t afi
, safi_t safi
)
11219 struct bgp_node
*prn
;
11220 struct bgp_node
*rn
;
11221 struct bgp_table
*table
;
11223 struct prefix_rd
*prd
;
11224 struct bgp_static
*bgp_static
;
11225 mpls_label_t label
;
11226 char buf
[SU_ADDRSTRLEN
];
11227 char rdbuf
[RD_ADDRSTRLEN
];
11229 /* Network configuration. */
11230 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11231 prn
= bgp_route_next(prn
)) {
11232 if ((table
= prn
->info
) == NULL
)
11235 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11236 if ((bgp_static
= rn
->info
) == NULL
)
11240 prd
= (struct prefix_rd
*)&prn
->p
;
11242 /* "network" configuration display. */
11243 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11244 label
= decode_label(&bgp_static
->label
);
11246 vty_out(vty
, " network %s/%d rd %s",
11247 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11249 p
->prefixlen
, rdbuf
);
11250 if (safi
== SAFI_MPLS_VPN
)
11251 vty_out(vty
, " label %u", label
);
11253 if (bgp_static
->rmap
.name
)
11254 vty_out(vty
, " route-map %s",
11255 bgp_static
->rmap
.name
);
11257 if (bgp_static
->backdoor
)
11258 vty_out(vty
, " backdoor");
11260 vty_out(vty
, "\n");
11265 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11266 afi_t afi
, safi_t safi
)
11268 struct bgp_node
*prn
;
11269 struct bgp_node
*rn
;
11270 struct bgp_table
*table
;
11272 struct prefix_rd
*prd
;
11273 struct bgp_static
*bgp_static
;
11274 char buf
[PREFIX_STRLEN
* 2];
11275 char buf2
[SU_ADDRSTRLEN
];
11276 char rdbuf
[RD_ADDRSTRLEN
];
11278 /* Network configuration. */
11279 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11280 prn
= bgp_route_next(prn
)) {
11281 if ((table
= prn
->info
) == NULL
)
11284 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11285 if ((bgp_static
= rn
->info
) == NULL
)
11288 char *macrouter
= NULL
;
11291 if (bgp_static
->router_mac
)
11292 macrouter
= prefix_mac2str(
11293 bgp_static
->router_mac
, NULL
, 0);
11294 if (bgp_static
->eth_s_id
)
11295 esi
= esi2str(bgp_static
->eth_s_id
);
11297 prd
= (struct prefix_rd
*)&prn
->p
;
11299 /* "network" configuration display. */
11300 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11301 if (p
->u
.prefix_evpn
.route_type
== 5) {
11302 char local_buf
[PREFIX_STRLEN
];
11303 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11304 struct prefix_evpn
*)p
)
11308 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11309 local_buf
, PREFIX_STRLEN
);
11310 sprintf(buf
, "%s/%u", local_buf
,
11311 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11313 prefix2str(p
, buf
, sizeof(buf
));
11316 if (bgp_static
->gatewayIp
.family
== AF_INET
11317 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11318 inet_ntop(bgp_static
->gatewayIp
.family
,
11319 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11322 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11324 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11325 decode_label(&bgp_static
->label
), esi
, buf2
,
11329 XFREE(MTYPE_TMP
, macrouter
);
11331 XFREE(MTYPE_TMP
, esi
);
11336 /* Configuration of static route announcement and aggregate
11338 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11341 struct bgp_node
*rn
;
11343 struct bgp_static
*bgp_static
;
11344 struct bgp_aggregate
*bgp_aggregate
;
11345 char buf
[SU_ADDRSTRLEN
];
11347 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11348 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11352 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11353 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11357 /* Network configuration. */
11358 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11359 rn
= bgp_route_next(rn
)) {
11360 if ((bgp_static
= rn
->info
) == NULL
)
11365 /* "network" configuration display. */
11366 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11367 uint32_t destination
;
11368 struct in_addr netmask
;
11370 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11371 masklen2ip(p
->prefixlen
, &netmask
);
11372 vty_out(vty
, " network %s",
11373 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11376 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11377 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11378 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11379 || p
->u
.prefix4
.s_addr
== 0) {
11380 /* Natural mask is not display. */
11382 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11384 vty_out(vty
, " network %s/%d",
11385 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11390 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11391 vty_out(vty
, " label-index %u",
11392 bgp_static
->label_index
);
11394 if (bgp_static
->rmap
.name
)
11395 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11397 if (bgp_static
->backdoor
)
11398 vty_out(vty
, " backdoor");
11400 vty_out(vty
, "\n");
11403 /* Aggregate-address configuration. */
11404 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11405 rn
= bgp_route_next(rn
)) {
11406 if ((bgp_aggregate
= rn
->info
) == NULL
)
11411 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11412 struct in_addr netmask
;
11414 masklen2ip(p
->prefixlen
, &netmask
);
11415 vty_out(vty
, " aggregate-address %s %s",
11416 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11418 inet_ntoa(netmask
));
11420 vty_out(vty
, " aggregate-address %s/%d",
11421 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11426 if (bgp_aggregate
->as_set
)
11427 vty_out(vty
, " as-set");
11429 if (bgp_aggregate
->summary_only
)
11430 vty_out(vty
, " summary-only");
11432 vty_out(vty
, "\n");
11436 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11439 struct bgp_node
*rn
;
11440 struct bgp_distance
*bdistance
;
11442 /* Distance configuration. */
11443 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11444 && bgp
->distance_local
[afi
][safi
]
11445 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11446 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11447 || bgp
->distance_local
[afi
][safi
]
11448 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11449 vty_out(vty
, " distance bgp %d %d %d\n",
11450 bgp
->distance_ebgp
[afi
][safi
],
11451 bgp
->distance_ibgp
[afi
][safi
],
11452 bgp
->distance_local
[afi
][safi
]);
11455 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11456 rn
= bgp_route_next(rn
))
11457 if ((bdistance
= rn
->info
) != NULL
) {
11458 char buf
[PREFIX_STRLEN
];
11460 vty_out(vty
, " distance %d %s %s\n",
11461 bdistance
->distance
,
11462 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11463 bdistance
->access_list
? bdistance
->access_list
11468 /* Allocate routing table structure and install commands. */
11469 void bgp_route_init(void)
11474 /* Init BGP distance table. */
11475 FOREACH_AFI_SAFI (afi
, safi
)
11476 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11478 /* IPv4 BGP commands. */
11479 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11480 install_element(BGP_NODE
, &bgp_network_cmd
);
11481 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11483 install_element(BGP_NODE
, &aggregate_address_cmd
);
11484 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11485 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11486 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11488 /* IPv4 unicast configuration. */
11489 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11490 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11491 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11493 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11494 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11495 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11496 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11498 /* IPv4 multicast configuration. */
11499 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11500 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11501 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11502 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11503 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11504 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11505 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11507 /* IPv4 labeled-unicast configuration. */
11508 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11509 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11510 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11511 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11512 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11514 install_element(VIEW_NODE
,
11515 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11516 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11517 install_element(VIEW_NODE
,
11518 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11519 #ifdef KEEP_OLD_VPN_COMMANDS
11520 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11521 #endif /* KEEP_OLD_VPN_COMMANDS */
11522 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11523 install_element(VIEW_NODE
,
11524 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11526 /* BGP dampening clear commands */
11527 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11528 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11530 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11531 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11534 install_element(ENABLE_NODE
,
11535 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11536 #ifdef KEEP_OLD_VPN_COMMANDS
11537 install_element(ENABLE_NODE
,
11538 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11539 #endif /* KEEP_OLD_VPN_COMMANDS */
11541 /* New config IPv6 BGP commands. */
11542 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11543 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11544 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11546 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11547 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11549 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11551 install_element(BGP_NODE
, &bgp_distance_cmd
);
11552 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11553 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11554 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11555 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11556 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11557 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11558 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11559 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11560 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11561 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11562 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11563 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11564 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11565 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11566 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11567 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11568 install_element(BGP_IPV4M_NODE
,
11569 &no_bgp_distance_source_access_list_cmd
);
11570 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11571 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11572 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11573 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11574 install_element(BGP_IPV6_NODE
,
11575 &ipv6_bgp_distance_source_access_list_cmd
);
11576 install_element(BGP_IPV6_NODE
,
11577 &no_ipv6_bgp_distance_source_access_list_cmd
);
11578 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11579 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11580 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11581 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11582 install_element(BGP_IPV6M_NODE
,
11583 &ipv6_bgp_distance_source_access_list_cmd
);
11584 install_element(BGP_IPV6M_NODE
,
11585 &no_ipv6_bgp_distance_source_access_list_cmd
);
11587 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11588 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11589 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11590 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11592 /* IPv4 Multicast Mode */
11593 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11594 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11596 /* Large Communities */
11597 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11598 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11600 /* show bgp ipv4 flowspec detailed */
11601 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11605 void bgp_route_finish(void)
11610 FOREACH_AFI_SAFI (afi
, safi
) {
11611 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11612 bgp_distance_table
[afi
][safi
] = NULL
;