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 int status
= BGP_DAMP_NONE
;
2678 /* apply dampening, if result is suppressed, we'll be retaining
2679 * the bgp_info in the RIB for historical reference.
2681 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2682 && peer
->sort
== BGP_PEER_EBGP
)
2683 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2684 == BGP_DAMP_SUPPRESSED
) {
2685 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2691 if (safi
== SAFI_MPLS_VPN
) {
2692 struct bgp_node
*prn
= NULL
;
2693 struct bgp_table
*table
= NULL
;
2695 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2696 (struct prefix
*)prd
);
2698 table
= (struct bgp_table
*)(prn
->info
);
2700 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2701 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2703 bgp_unlock_node(prn
);
2705 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2706 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2708 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2709 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2715 /* If this is an EVPN route, process for un-import. */
2716 if (safi
== SAFI_EVPN
)
2717 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2719 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2722 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2723 struct peer
*peer
, struct attr
*attr
,
2724 struct bgp_node
*rn
)
2726 struct bgp_info
*new;
2728 /* Make new BGP info. */
2729 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2731 new->instance
= instance
;
2732 new->sub_type
= sub_type
;
2735 new->uptime
= bgp_clock();
2737 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2741 static void overlay_index_update(struct attr
*attr
,
2742 struct eth_segment_id
*eth_s_id
,
2743 union gw_addr
*gw_ip
)
2748 if (eth_s_id
== NULL
) {
2749 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2750 sizeof(struct eth_segment_id
));
2752 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2753 sizeof(struct eth_segment_id
));
2755 if (gw_ip
== NULL
) {
2756 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2758 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2759 sizeof(union gw_addr
));
2763 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2764 struct eth_segment_id
*eth_s_id
,
2765 union gw_addr
*gw_ip
)
2767 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2768 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2771 if (afi
!= AFI_L2VPN
)
2774 memset(&temp
, 0, 16);
2775 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2776 info_gw_ip
= (union gw_addr
*)&temp
;
2777 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2780 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2781 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2784 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2786 info_gw_ip_remote
= gw_ip
;
2787 if (eth_s_id
== NULL
)
2788 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2790 info_eth_s_id_remote
= eth_s_id
;
2791 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2793 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2794 sizeof(struct eth_segment_id
));
2797 /* Check if received nexthop is valid or not. */
2798 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2803 /* Only validated for unicast and multicast currently. */
2804 /* Also valid for EVPN where the nexthop is an IP address. */
2805 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2808 /* If NEXT_HOP is present, validate it. */
2809 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2810 if (attr
->nexthop
.s_addr
== 0
2811 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2812 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2816 /* If MP_NEXTHOP is present, validate it. */
2817 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2818 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2819 * it is not an IPv6 link-local address.
2821 if (attr
->mp_nexthop_len
) {
2822 switch (attr
->mp_nexthop_len
) {
2823 case BGP_ATTR_NHLEN_IPV4
:
2824 case BGP_ATTR_NHLEN_VPNV4
:
2825 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2826 || IPV4_CLASS_DE(ntohl(
2827 attr
->mp_nexthop_global_in
.s_addr
))
2828 || bgp_nexthop_self(bgp
,
2829 attr
->mp_nexthop_global_in
));
2832 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2833 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2834 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2835 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2836 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2837 || IN6_IS_ADDR_MULTICAST(
2838 &attr
->mp_nexthop_global
));
2850 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2851 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2852 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2853 uint32_t num_labels
, int soft_reconfig
,
2854 struct bgp_route_evpn
*evpn
)
2857 int aspath_loop_count
= 0;
2858 struct bgp_node
*rn
;
2860 struct attr new_attr
;
2861 struct attr
*attr_new
;
2862 struct bgp_info
*ri
;
2863 struct bgp_info
*new;
2864 struct bgp_info_extra
*extra
;
2866 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2868 int do_loop_check
= 1;
2869 int has_valid_label
= 0;
2871 int vnc_implicit_withdraw
= 0;
2875 memset(&new_attr
, 0, sizeof(struct attr
));
2876 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2877 new_attr
.label
= MPLS_INVALID_LABEL
;
2880 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2881 /* TODO: Check to see if we can get rid of "is_valid_label" */
2882 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2883 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2885 has_valid_label
= bgp_is_valid_label(label
);
2887 /* When peer's soft reconfiguration enabled. Record input packet in
2890 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2891 && peer
!= bgp
->peer_self
)
2892 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2894 /* Check previously received route. */
2895 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2896 if (ri
->peer
== peer
&& ri
->type
== type
2897 && ri
->sub_type
== sub_type
2898 && ri
->addpath_rx_id
== addpath_id
)
2901 /* AS path local-as loop check. */
2902 if (peer
->change_local_as
) {
2903 if (peer
->allowas_in
[afi
][safi
])
2904 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2905 else if (!CHECK_FLAG(peer
->flags
,
2906 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2907 aspath_loop_count
= 1;
2909 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2910 > aspath_loop_count
) {
2911 reason
= "as-path contains our own AS;";
2916 /* If the peer is configured for "allowas-in origin" and the last ASN in
2918 * as-path is our ASN then we do not need to call aspath_loop_check
2920 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2921 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2924 /* AS path loop check. */
2925 if (do_loop_check
) {
2926 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2927 > peer
->allowas_in
[afi
][safi
]
2928 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2929 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2930 > peer
->allowas_in
[afi
][safi
])) {
2931 reason
= "as-path contains our own AS;";
2936 /* Route reflector originator ID check. */
2937 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2938 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2939 reason
= "originator is us;";
2943 /* Route reflector cluster ID check. */
2944 if (bgp_cluster_filter(peer
, attr
)) {
2945 reason
= "reflected from the same cluster;";
2949 /* Apply incoming filter. */
2950 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2955 bgp_attr_dup(&new_attr
, attr
);
2957 /* Apply incoming route-map.
2958 * NB: new_attr may now contain newly allocated values from route-map
2960 * commands, so we need bgp_attr_flush in the error paths, until we
2962 * the attr (which takes over the memory references) */
2963 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2965 reason
= "route-map;";
2966 bgp_attr_flush(&new_attr
);
2970 if (peer
->sort
== BGP_PEER_EBGP
) {
2972 /* If we receive the graceful-shutdown community from an eBGP
2973 * peer we must lower local-preference */
2974 if (new_attr
.community
2975 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2976 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2977 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2979 /* If graceful-shutdown is configured then add the GSHUT
2980 * community to all paths received from eBGP peers */
2981 } else if (bgp_flag_check(peer
->bgp
,
2982 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2983 bgp_attr_add_gshut_community(&new_attr
);
2987 /* next hop check. */
2988 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2989 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2990 reason
= "martian or self next-hop;";
2991 bgp_attr_flush(&new_attr
);
2995 attr_new
= bgp_attr_intern(&new_attr
);
2997 /* If the update is implicit withdraw. */
2999 ri
->uptime
= bgp_clock();
3000 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3002 /* Same attribute comes in. */
3003 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3004 && attrhash_cmp(ri
->attr
, attr_new
)
3005 && (!has_valid_label
3006 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3007 num_labels
* sizeof(mpls_label_t
))
3009 && (overlay_index_equal(
3010 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3011 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3012 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3013 BGP_CONFIG_DAMPENING
)
3014 && peer
->sort
== BGP_PEER_EBGP
3015 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3016 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3017 bgp_debug_rdpfxpath2str(
3018 afi
, safi
, prd
, p
, label
,
3019 num_labels
, addpath_id
? 1 : 0,
3020 addpath_id
, pfx_buf
,
3022 zlog_debug("%s rcvd %s", peer
->host
,
3026 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3027 != BGP_DAMP_SUPPRESSED
) {
3028 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3030 bgp_process(bgp
, rn
, afi
, safi
);
3032 } else /* Duplicate - odd */
3034 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3035 if (!peer
->rcvd_attr_printed
) {
3037 "%s rcvd UPDATE w/ attr: %s",
3039 peer
->rcvd_attr_str
);
3040 peer
->rcvd_attr_printed
= 1;
3043 bgp_debug_rdpfxpath2str(
3044 afi
, safi
, prd
, p
, label
,
3045 num_labels
, addpath_id
? 1 : 0,
3046 addpath_id
, pfx_buf
,
3049 "%s rcvd %s...duplicate ignored",
3050 peer
->host
, pfx_buf
);
3053 /* graceful restart STALE flag unset. */
3054 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3055 bgp_info_unset_flag(rn
, ri
,
3057 bgp_process(bgp
, rn
, afi
, safi
);
3061 bgp_unlock_node(rn
);
3062 bgp_attr_unintern(&attr_new
);
3067 /* Withdraw/Announce before we fully processed the withdraw */
3068 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3069 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3070 bgp_debug_rdpfxpath2str(
3071 afi
, safi
, prd
, p
, label
, num_labels
,
3072 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3075 "%s rcvd %s, flapped quicker than processing",
3076 peer
->host
, pfx_buf
);
3079 bgp_info_restore(rn
, ri
);
3082 /* Received Logging. */
3083 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3084 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3085 num_labels
, addpath_id
? 1 : 0,
3086 addpath_id
, pfx_buf
,
3088 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3091 /* graceful restart STALE flag unset. */
3092 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3093 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3095 /* The attribute is changed. */
3096 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3098 /* implicit withdraw, decrement aggregate and pcount here.
3099 * only if update is accepted, they'll increment below.
3101 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3103 /* Update bgp route dampening information. */
3104 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3105 && peer
->sort
== BGP_PEER_EBGP
) {
3106 /* This is implicit withdraw so we should update
3109 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3110 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3113 if (safi
== SAFI_MPLS_VPN
) {
3114 struct bgp_node
*prn
= NULL
;
3115 struct bgp_table
*table
= NULL
;
3117 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3118 (struct prefix
*)prd
);
3120 table
= (struct bgp_table
*)(prn
->info
);
3122 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3123 bgp
, prd
, table
, p
, ri
);
3125 bgp_unlock_node(prn
);
3127 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3128 && (safi
== SAFI_UNICAST
)) {
3129 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3131 * Implicit withdraw case.
3133 ++vnc_implicit_withdraw
;
3134 vnc_import_bgp_del_route(bgp
, p
, ri
);
3135 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3140 /* Special handling for EVPN update of an existing route. If the
3141 * extended community attribute has changed, we need to
3143 * the route using its existing extended community. It will be
3144 * subsequently processed for import with the new extended
3147 if (safi
== SAFI_EVPN
&& !same_attr
) {
3149 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3151 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3154 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3155 attr_new
->ecommunity
);
3157 if (bgp_debug_update(peer
, p
, NULL
, 1))
3159 "Change in EXT-COMM, existing %s new %s",
3161 ri
->attr
->ecommunity
),
3163 attr_new
->ecommunity
));
3164 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3170 /* Update to new attribute. */
3171 bgp_attr_unintern(&ri
->attr
);
3172 ri
->attr
= attr_new
;
3174 /* Update MPLS label */
3175 if (has_valid_label
) {
3176 extra
= bgp_info_extra_get(ri
);
3177 memcpy(&extra
->label
, label
,
3178 num_labels
* sizeof(mpls_label_t
));
3179 extra
->num_labels
= num_labels
;
3180 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3181 bgp_set_valid_label(&extra
->label
[0]);
3185 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3186 && (safi
== SAFI_UNICAST
)) {
3187 if (vnc_implicit_withdraw
) {
3189 * Add back the route with its new attributes
3191 * The route is still selected, until the route
3193 * queued by bgp_process actually runs. We have
3195 * update to the VNC side immediately to avoid
3197 * configuration changes (e.g., route-map
3199 * trigger re-importation of the entire RIB.
3201 vnc_import_bgp_add_route(bgp
, p
, ri
);
3202 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3206 /* Update Overlay Index */
3207 if (afi
== AFI_L2VPN
) {
3208 overlay_index_update(
3209 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3210 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3213 /* Update bgp route dampening information. */
3214 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3215 && peer
->sort
== BGP_PEER_EBGP
) {
3216 /* Now we do normal update dampening. */
3217 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3218 if (ret
== BGP_DAMP_SUPPRESSED
) {
3219 bgp_unlock_node(rn
);
3224 /* Nexthop reachability check - for unicast and
3225 * labeled-unicast.. */
3226 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3227 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3228 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3229 && !CHECK_FLAG(peer
->flags
,
3230 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3232 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3237 struct bgp
*bgp_nexthop
= bgp
;
3239 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3240 bgp_nexthop
= ri
->extra
->bgp_orig
;
3242 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3243 ri
, NULL
, connected
)
3244 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3245 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3247 if (BGP_DEBUG(nht
, NHT
)) {
3248 char buf1
[INET6_ADDRSTRLEN
];
3250 (const void *)&attr_new
3252 buf1
, INET6_ADDRSTRLEN
);
3253 zlog_debug("%s(%s): NH unresolved",
3254 __FUNCTION__
, buf1
);
3256 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3259 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3262 if (safi
== SAFI_MPLS_VPN
) {
3263 struct bgp_node
*prn
= NULL
;
3264 struct bgp_table
*table
= NULL
;
3266 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3267 (struct prefix
*)prd
);
3269 table
= (struct bgp_table
*)(prn
->info
);
3271 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3272 bgp
, prd
, table
, p
, ri
);
3274 bgp_unlock_node(prn
);
3278 /* If this is an EVPN route and some attribute has changed,
3280 * route for import. If the extended community has changed, we
3282 * have done the un-import earlier and the import would result
3284 * route getting injected into appropriate L2 VNIs. If it is
3286 * some other attribute change, the import will result in
3288 * the attributes for the route in the VNI(s).
3290 if (safi
== SAFI_EVPN
&& !same_attr
)
3291 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3293 /* Process change. */
3294 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3296 bgp_process(bgp
, rn
, afi
, safi
);
3297 bgp_unlock_node(rn
);
3299 if (SAFI_UNICAST
== safi
3300 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3301 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3303 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3305 if ((SAFI_MPLS_VPN
== safi
)
3306 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3308 vpn_leak_to_vrf_update(bgp
, ri
);
3312 if (SAFI_MPLS_VPN
== safi
) {
3313 mpls_label_t label_decoded
= decode_label(label
);
3315 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3316 type
, sub_type
, &label_decoded
);
3318 if (SAFI_ENCAP
== safi
) {
3319 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3320 type
, sub_type
, NULL
);
3325 } // End of implicit withdraw
3327 /* Received Logging. */
3328 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3329 if (!peer
->rcvd_attr_printed
) {
3330 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3331 peer
->rcvd_attr_str
);
3332 peer
->rcvd_attr_printed
= 1;
3335 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3336 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3338 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3341 /* Make new BGP info. */
3342 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3344 /* Update MPLS label */
3345 if (has_valid_label
) {
3346 extra
= bgp_info_extra_get(new);
3347 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3348 extra
->num_labels
= num_labels
;
3349 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3350 bgp_set_valid_label(&extra
->label
[0]);
3353 /* Update Overlay Index */
3354 if (afi
== AFI_L2VPN
) {
3355 overlay_index_update(new->attr
,
3356 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3357 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3359 /* Nexthop reachability check. */
3360 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3361 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3362 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3363 && !CHECK_FLAG(peer
->flags
,
3364 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3365 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3370 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3371 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3372 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3374 if (BGP_DEBUG(nht
, NHT
)) {
3375 char buf1
[INET6_ADDRSTRLEN
];
3377 (const void *)&attr_new
->nexthop
,
3378 buf1
, INET6_ADDRSTRLEN
);
3379 zlog_debug("%s(%s): NH unresolved",
3380 __FUNCTION__
, buf1
);
3382 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3385 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3388 new->addpath_rx_id
= addpath_id
;
3390 /* Increment prefix */
3391 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3393 /* Register new BGP information. */
3394 bgp_info_add(rn
, new);
3396 /* route_node_get lock */
3397 bgp_unlock_node(rn
);
3400 if (safi
== SAFI_MPLS_VPN
) {
3401 struct bgp_node
*prn
= NULL
;
3402 struct bgp_table
*table
= NULL
;
3404 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3406 table
= (struct bgp_table
*)(prn
->info
);
3408 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3409 bgp
, prd
, table
, p
, new);
3411 bgp_unlock_node(prn
);
3415 /* If maximum prefix count is configured and current prefix
3417 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3420 /* If this is an EVPN route, process for import. */
3421 if (safi
== SAFI_EVPN
)
3422 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3424 /* Process change. */
3425 bgp_process(bgp
, rn
, afi
, safi
);
3427 if (SAFI_UNICAST
== safi
3428 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3429 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3430 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3432 if ((SAFI_MPLS_VPN
== safi
)
3433 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3435 vpn_leak_to_vrf_update(bgp
, new);
3438 if (SAFI_MPLS_VPN
== safi
) {
3439 mpls_label_t label_decoded
= decode_label(label
);
3441 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3442 sub_type
, &label_decoded
);
3444 if (SAFI_ENCAP
== safi
) {
3445 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3452 /* This BGP update is filtered. Log the reason then update BGP
3455 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3456 if (!peer
->rcvd_attr_printed
) {
3457 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3458 peer
->rcvd_attr_str
);
3459 peer
->rcvd_attr_printed
= 1;
3462 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3463 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3465 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3466 peer
->host
, pfx_buf
, reason
);
3470 /* If this is an EVPN route, un-import it as it is now filtered.
3472 if (safi
== SAFI_EVPN
)
3473 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3475 if (SAFI_UNICAST
== safi
3476 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3477 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3479 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3481 if ((SAFI_MPLS_VPN
== safi
)
3482 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3484 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3487 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3490 bgp_unlock_node(rn
);
3494 * Filtered update is treated as an implicit withdrawal (see
3496 * a few lines above)
3498 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3499 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3507 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3508 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3509 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3510 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3513 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3514 struct bgp_node
*rn
;
3515 struct bgp_info
*ri
;
3518 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3519 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3527 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3529 /* If peer is soft reconfiguration enabled. Record input packet for
3530 * further calculation.
3532 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3533 * routes that are filtered. This tanks out Quagga RS pretty badly due
3535 * the iteration over all RS clients.
3536 * Since we need to remove the entry from adj_in anyway, do that first
3538 * if there was no entry, we don't need to do anything more.
3540 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3541 && peer
!= bgp
->peer_self
)
3542 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3543 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3544 bgp_debug_rdpfxpath2str(
3545 afi
, safi
, prd
, p
, label
, num_labels
,
3546 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3549 "%s withdrawing route %s not in adj-in",
3550 peer
->host
, pfx_buf
);
3552 bgp_unlock_node(rn
);
3556 /* Lookup withdrawn route. */
3557 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3558 if (ri
->peer
== peer
&& ri
->type
== type
3559 && ri
->sub_type
== sub_type
3560 && ri
->addpath_rx_id
== addpath_id
)
3564 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3565 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3566 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3568 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3572 /* Withdraw specified route from routing table. */
3573 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3574 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3575 if (SAFI_UNICAST
== safi
3576 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3577 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3578 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3580 if ((SAFI_MPLS_VPN
== safi
)
3581 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3583 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3585 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3586 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3587 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3589 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3592 /* Unlock bgp_node_get() lock. */
3593 bgp_unlock_node(rn
);
3598 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3601 struct update_subgroup
*subgrp
;
3602 subgrp
= peer_subgroup(peer
, afi
, safi
);
3603 subgroup_default_originate(subgrp
, withdraw
);
3608 * bgp_stop_announce_route_timer
3610 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3612 if (!paf
->t_announce_route
)
3615 THREAD_TIMER_OFF(paf
->t_announce_route
);
3619 * bgp_announce_route_timer_expired
3621 * Callback that is invoked when the route announcement timer for a
3624 static int bgp_announce_route_timer_expired(struct thread
*t
)
3626 struct peer_af
*paf
;
3629 paf
= THREAD_ARG(t
);
3632 if (peer
->status
!= Established
)
3635 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3638 peer_af_announce_route(paf
, 1);
3643 * bgp_announce_route
3645 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3647 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3649 struct peer_af
*paf
;
3650 struct update_subgroup
*subgrp
;
3652 paf
= peer_af_find(peer
, afi
, safi
);
3655 subgrp
= PAF_SUBGRP(paf
);
3658 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3659 * or a refresh has already been triggered.
3661 if (!subgrp
|| paf
->t_announce_route
)
3665 * Start a timer to stagger/delay the announce. This serves
3666 * two purposes - announcement can potentially be combined for
3667 * multiple peers and the announcement doesn't happen in the
3670 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3671 (subgrp
->peer_count
== 1)
3672 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3673 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3674 &paf
->t_announce_route
);
3678 * Announce routes from all AF tables to a peer.
3680 * This should ONLY be called when there is a need to refresh the
3681 * routes to the peer based on a policy change for this peer alone
3682 * or a route refresh request received from the peer.
3683 * The operation will result in splitting the peer from its existing
3684 * subgroups and putting it in new subgroups.
3686 void bgp_announce_route_all(struct peer
*peer
)
3691 FOREACH_AFI_SAFI (afi
, safi
)
3692 bgp_announce_route(peer
, afi
, safi
);
3695 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3696 struct bgp_table
*table
,
3697 struct prefix_rd
*prd
)
3700 struct bgp_node
*rn
;
3701 struct bgp_adj_in
*ain
;
3704 table
= peer
->bgp
->rib
[afi
][safi
];
3706 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3707 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3708 if (ain
->peer
!= peer
)
3711 struct bgp_info
*ri
= rn
->info
;
3712 uint32_t num_labels
= 0;
3713 mpls_label_t
*label_pnt
= NULL
;
3715 if (ri
&& ri
->extra
)
3716 num_labels
= ri
->extra
->num_labels
;
3718 label_pnt
= &ri
->extra
->label
[0];
3720 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3721 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3722 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3723 num_labels
, 1, NULL
);
3726 bgp_unlock_node(rn
);
3732 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3734 struct bgp_node
*rn
;
3735 struct bgp_table
*table
;
3737 if (peer
->status
!= Established
)
3740 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3741 && (safi
!= SAFI_EVPN
))
3742 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3744 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3745 rn
= bgp_route_next(rn
))
3746 if ((table
= rn
->info
) != NULL
) {
3747 struct prefix_rd prd
;
3748 prd
.family
= AF_UNSPEC
;
3750 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3752 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3758 struct bgp_clear_node_queue
{
3759 struct bgp_node
*rn
;
3762 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3764 struct bgp_clear_node_queue
*cnq
= data
;
3765 struct bgp_node
*rn
= cnq
->rn
;
3766 struct peer
*peer
= wq
->spec
.data
;
3767 struct bgp_info
*ri
;
3769 afi_t afi
= bgp_node_table(rn
)->afi
;
3770 safi_t safi
= bgp_node_table(rn
)->safi
;
3775 /* It is possible that we have multiple paths for a prefix from a peer
3776 * if that peer is using AddPath.
3778 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3779 if (ri
->peer
!= peer
)
3782 /* graceful restart STALE flag set. */
3783 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3784 && peer
->nsf
[afi
][safi
]
3785 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3786 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3787 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3789 /* If this is an EVPN route, process for
3791 if (safi
== SAFI_EVPN
)
3792 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3794 /* Handle withdraw for VRF route-leaking and L3VPN */
3795 if (SAFI_UNICAST
== safi
3796 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3797 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3798 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3801 if (SAFI_MPLS_VPN
== safi
&&
3802 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3803 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3806 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3812 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3814 struct bgp_clear_node_queue
*cnq
= data
;
3815 struct bgp_node
*rn
= cnq
->rn
;
3816 struct bgp_table
*table
= bgp_node_table(rn
);
3818 bgp_unlock_node(rn
);
3819 bgp_table_unlock(table
);
3820 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3823 static void bgp_clear_node_complete(struct work_queue
*wq
)
3825 struct peer
*peer
= wq
->spec
.data
;
3827 /* Tickle FSM to start moving again */
3828 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3830 peer_unlock(peer
); /* bgp_clear_route */
3833 static void bgp_clear_node_queue_init(struct peer
*peer
)
3835 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3837 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3838 #undef CLEAR_QUEUE_NAME_LEN
3840 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3842 zlog_err("%s: Failed to allocate work queue", __func__
);
3845 peer
->clear_node_queue
->spec
.hold
= 10;
3846 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3847 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3848 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3849 peer
->clear_node_queue
->spec
.max_retries
= 0;
3851 /* we only 'lock' this peer reference when the queue is actually active
3853 peer
->clear_node_queue
->spec
.data
= peer
;
3856 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3857 struct bgp_table
*table
)
3859 struct bgp_node
*rn
;
3860 int force
= bm
->process_main_queue
? 0 : 1;
3863 table
= peer
->bgp
->rib
[afi
][safi
];
3865 /* If still no table => afi/safi isn't configured at all or smth. */
3869 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3870 struct bgp_info
*ri
, *next
;
3871 struct bgp_adj_in
*ain
;
3872 struct bgp_adj_in
*ain_next
;
3874 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3875 * queued for every clearing peer, regardless of whether it is
3876 * relevant to the peer at hand.
3878 * Overview: There are 3 different indices which need to be
3879 * scrubbed, potentially, when a peer is removed:
3881 * 1 peer's routes visible via the RIB (ie accepted routes)
3882 * 2 peer's routes visible by the (optional) peer's adj-in index
3883 * 3 other routes visible by the peer's adj-out index
3885 * 3 there is no hurry in scrubbing, once the struct peer is
3886 * removed from bgp->peer, we could just GC such deleted peer's
3887 * adj-outs at our leisure.
3889 * 1 and 2 must be 'scrubbed' in some way, at least made
3890 * invisible via RIB index before peer session is allowed to be
3891 * brought back up. So one needs to know when such a 'search' is
3896 * - there'd be a single global queue or a single RIB walker
3897 * - rather than tracking which route_nodes still need to be
3898 * examined on a peer basis, we'd track which peers still
3901 * Given that our per-peer prefix-counts now should be reliable,
3902 * this may actually be achievable. It doesn't seem to be a huge
3903 * problem at this time,
3905 * It is possible that we have multiple paths for a prefix from
3907 * if that peer is using AddPath.
3911 ain_next
= ain
->next
;
3913 if (ain
->peer
== peer
) {
3914 bgp_adj_in_remove(rn
, ain
);
3915 bgp_unlock_node(rn
);
3921 for (ri
= rn
->info
; ri
; ri
= next
) {
3923 if (ri
->peer
!= peer
)
3927 bgp_info_reap(rn
, ri
);
3929 struct bgp_clear_node_queue
*cnq
;
3931 /* both unlocked in bgp_clear_node_queue_del */
3932 bgp_table_lock(bgp_node_table(rn
));
3935 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3936 sizeof(struct bgp_clear_node_queue
));
3938 work_queue_add(peer
->clear_node_queue
, cnq
);
3946 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3948 struct bgp_node
*rn
;
3949 struct bgp_table
*table
;
3951 if (peer
->clear_node_queue
== NULL
)
3952 bgp_clear_node_queue_init(peer
);
3954 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3955 * Idle until it receives a Clearing_Completed event. This protects
3956 * against peers which flap faster than we can we clear, which could
3959 * a) race with routes from the new session being installed before
3960 * clear_route_node visits the node (to delete the route of that
3962 * b) resource exhaustion, clear_route_node likely leads to an entry
3963 * on the process_main queue. Fast-flapping could cause that queue
3967 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3968 * the unlock will happen upon work-queue completion; other wise, the
3969 * unlock happens at the end of this function.
3971 if (!peer
->clear_node_queue
->thread
)
3974 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3975 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3977 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3978 rn
= bgp_route_next(rn
))
3979 if ((table
= rn
->info
) != NULL
)
3980 bgp_clear_route_table(peer
, afi
, safi
, table
);
3982 /* unlock if no nodes got added to the clear-node-queue. */
3983 if (!peer
->clear_node_queue
->thread
)
3987 void bgp_clear_route_all(struct peer
*peer
)
3992 FOREACH_AFI_SAFI (afi
, safi
)
3993 bgp_clear_route(peer
, afi
, safi
);
3996 rfapiProcessPeerDown(peer
);
4000 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4002 struct bgp_table
*table
;
4003 struct bgp_node
*rn
;
4004 struct bgp_adj_in
*ain
;
4005 struct bgp_adj_in
*ain_next
;
4007 table
= peer
->bgp
->rib
[afi
][safi
];
4009 /* It is possible that we have multiple paths for a prefix from a peer
4010 * if that peer is using AddPath.
4012 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4016 ain_next
= ain
->next
;
4018 if (ain
->peer
== peer
) {
4019 bgp_adj_in_remove(rn
, ain
);
4020 bgp_unlock_node(rn
);
4028 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4030 struct bgp_node
*rn
;
4031 struct bgp_info
*ri
;
4032 struct bgp_table
*table
;
4034 if (safi
== SAFI_MPLS_VPN
) {
4035 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4036 rn
= bgp_route_next(rn
)) {
4037 struct bgp_node
*rm
;
4038 struct bgp_info
*ri
;
4040 /* look for neighbor in tables */
4041 if ((table
= rn
->info
) == NULL
)
4044 for (rm
= bgp_table_top(table
); rm
;
4045 rm
= bgp_route_next(rm
))
4046 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4047 if (ri
->peer
!= peer
)
4049 if (!CHECK_FLAG(ri
->flags
,
4053 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4058 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4059 rn
= bgp_route_next(rn
))
4060 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4061 if (ri
->peer
!= peer
)
4063 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4065 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4071 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4074 struct bgp_node
*rn
;
4075 struct bgp_info
*ri
;
4076 struct bgp_info
*next
;
4078 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4079 for (ri
= rn
->info
; ri
; ri
= next
) {
4081 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4082 && ri
->type
== ZEBRA_ROUTE_BGP
4083 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4084 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4085 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4087 if (bgp_fibupd_safi(safi
))
4088 bgp_zebra_withdraw(&rn
->p
, ri
,
4090 bgp_info_reap(rn
, ri
);
4095 /* Delete all kernel routes. */
4096 void bgp_cleanup_routes(struct bgp
*bgp
)
4099 struct bgp_node
*rn
;
4101 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4102 if (afi
== AFI_L2VPN
)
4104 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4107 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4109 if (afi
!= AFI_L2VPN
) {
4111 safi
= SAFI_MPLS_VPN
;
4112 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4113 rn
= bgp_route_next(rn
)) {
4115 bgp_cleanup_table(bgp
,
4116 (struct bgp_table
*)(rn
->info
),
4118 bgp_table_finish((struct bgp_table
**)&(
4121 bgp_unlock_node(rn
);
4125 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4126 rn
= bgp_route_next(rn
)) {
4128 bgp_cleanup_table(bgp
,
4129 (struct bgp_table
*)(rn
->info
),
4131 bgp_table_finish((struct bgp_table
**)&(
4134 bgp_unlock_node(rn
);
4139 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4140 rn
= bgp_route_next(rn
)) {
4142 bgp_cleanup_table(bgp
,
4143 (struct bgp_table
*)(rn
->info
),
4145 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4147 bgp_unlock_node(rn
);
4152 void bgp_reset(void)
4155 bgp_zclient_reset();
4156 access_list_reset();
4157 prefix_list_reset();
4160 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4162 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4163 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4164 PEER_CAP_ADDPATH_AF_TX_RCV
));
4167 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4169 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4170 struct bgp_nlri
*packet
)
4179 int addpath_encoded
;
4180 uint32_t addpath_id
;
4183 lim
= pnt
+ packet
->length
;
4185 safi
= packet
->safi
;
4187 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4189 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4190 syntactic validity. If the field is syntactically incorrect,
4191 then the Error Subcode is set to Invalid Network Field. */
4192 for (; pnt
< lim
; pnt
+= psize
) {
4193 /* Clear prefix structure. */
4194 memset(&p
, 0, sizeof(struct prefix
));
4196 if (addpath_encoded
) {
4198 /* When packet overflow occurs return immediately. */
4199 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4202 addpath_id
= ntohl(*((uint32_t *)pnt
));
4203 pnt
+= BGP_ADDPATH_ID_LEN
;
4206 /* Fetch prefix length. */
4207 p
.prefixlen
= *pnt
++;
4208 /* afi/safi validity already verified by caller,
4209 * bgp_update_receive */
4210 p
.family
= afi2family(afi
);
4212 /* Prefix length check. */
4213 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4215 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4216 peer
->host
, p
.prefixlen
, packet
->afi
);
4220 /* Packet size overflow check. */
4221 psize
= PSIZE(p
.prefixlen
);
4223 /* When packet overflow occur return immediately. */
4224 if (pnt
+ psize
> lim
) {
4226 "%s [Error] Update packet error (prefix length %d overflows packet)",
4227 peer
->host
, p
.prefixlen
);
4231 /* Defensive coding, double-check the psize fits in a struct
4233 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4235 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4236 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4240 /* Fetch prefix from NLRI packet. */
4241 memcpy(&p
.u
.prefix
, pnt
, psize
);
4243 /* Check address. */
4244 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4245 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4246 /* From RFC4271 Section 6.3:
4248 * If a prefix in the NLRI field is semantically
4250 * (e.g., an unexpected multicast IP address),
4252 * be logged locally, and the prefix SHOULD be
4256 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4257 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4262 /* Check address. */
4263 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4264 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4268 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4270 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4275 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4279 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4281 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4288 /* Normal process. */
4290 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4291 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4292 NULL
, NULL
, 0, 0, NULL
);
4294 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4295 safi
, ZEBRA_ROUTE_BGP
,
4296 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4299 /* Address family configuration mismatch or maximum-prefix count
4305 /* Packet length consistency check. */
4308 "%s [Error] Update packet error (prefix length mismatch with total length)",
4316 static struct bgp_static
*bgp_static_new(void)
4318 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4321 static void bgp_static_free(struct bgp_static
*bgp_static
)
4323 if (bgp_static
->rmap
.name
)
4324 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4325 if (bgp_static
->eth_s_id
)
4326 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4327 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4330 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4331 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4333 struct bgp_node
*rn
;
4334 struct bgp_info
*ri
;
4335 struct bgp_info
*new;
4336 struct bgp_info info
;
4338 struct attr
*attr_new
;
4341 int vnc_implicit_withdraw
= 0;
4348 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4350 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4352 attr
.nexthop
= bgp_static
->igpnexthop
;
4353 attr
.med
= bgp_static
->igpmetric
;
4354 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4356 if (bgp_static
->atomic
)
4357 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4359 /* Store label index, if required. */
4360 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4361 attr
.label_index
= bgp_static
->label_index
;
4362 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4365 /* Apply route-map. */
4366 if (bgp_static
->rmap
.name
) {
4367 struct attr attr_tmp
= attr
;
4369 memset(&info
, 0, sizeof(struct bgp_info
));
4370 info
.peer
= bgp
->peer_self
;
4371 info
.attr
= &attr_tmp
;
4373 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4375 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4377 bgp
->peer_self
->rmap_type
= 0;
4379 if (ret
== RMAP_DENYMATCH
) {
4380 /* Free uninterned attribute. */
4381 bgp_attr_flush(&attr_tmp
);
4383 /* Unintern original. */
4384 aspath_unintern(&attr
.aspath
);
4385 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4389 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4390 bgp_attr_add_gshut_community(&attr_tmp
);
4392 attr_new
= bgp_attr_intern(&attr_tmp
);
4395 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4396 bgp_attr_add_gshut_community(&attr
);
4398 attr_new
= bgp_attr_intern(&attr
);
4401 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4402 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4403 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4407 if (attrhash_cmp(ri
->attr
, attr_new
)
4408 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4409 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4410 bgp_unlock_node(rn
);
4411 bgp_attr_unintern(&attr_new
);
4412 aspath_unintern(&attr
.aspath
);
4415 /* The attribute is changed. */
4416 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4418 /* Rewrite BGP route information. */
4419 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4420 bgp_info_restore(rn
, ri
);
4422 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4424 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4425 && (safi
== SAFI_UNICAST
)) {
4426 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4428 * Implicit withdraw case.
4429 * We have to do this before ri is
4432 ++vnc_implicit_withdraw
;
4433 vnc_import_bgp_del_route(bgp
, p
, ri
);
4434 vnc_import_bgp_exterior_del_route(
4439 bgp_attr_unintern(&ri
->attr
);
4440 ri
->attr
= attr_new
;
4441 ri
->uptime
= bgp_clock();
4443 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4444 && (safi
== SAFI_UNICAST
)) {
4445 if (vnc_implicit_withdraw
) {
4446 vnc_import_bgp_add_route(bgp
, p
, ri
);
4447 vnc_import_bgp_exterior_add_route(
4453 /* Nexthop reachability check. */
4454 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4455 && (safi
== SAFI_UNICAST
4456 || safi
== SAFI_LABELED_UNICAST
)) {
4458 struct bgp
*bgp_nexthop
= bgp
;
4460 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4461 bgp_nexthop
= ri
->extra
->bgp_orig
;
4463 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4465 bgp_info_set_flag(rn
, ri
,
4468 if (BGP_DEBUG(nht
, NHT
)) {
4469 char buf1
[INET6_ADDRSTRLEN
];
4470 inet_ntop(p
->family
,
4474 "%s(%s): Route not in table, not advertising",
4475 __FUNCTION__
, buf1
);
4477 bgp_info_unset_flag(rn
, ri
,
4481 /* Delete the NHT structure if any, if we're
4483 * enabling/disabling import check. We
4484 * deregister the route
4485 * from NHT to avoid overloading NHT and the
4486 * process interaction
4488 bgp_unlink_nexthop(ri
);
4489 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4491 /* Process change. */
4492 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4493 bgp_process(bgp
, rn
, afi
, safi
);
4495 if (SAFI_UNICAST
== safi
4496 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4498 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4499 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4503 bgp_unlock_node(rn
);
4504 aspath_unintern(&attr
.aspath
);
4509 /* Make new BGP info. */
4510 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4512 /* Nexthop reachability check. */
4513 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4514 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4515 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4516 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4518 if (BGP_DEBUG(nht
, NHT
)) {
4519 char buf1
[INET6_ADDRSTRLEN
];
4520 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4523 "%s(%s): Route not in table, not advertising",
4524 __FUNCTION__
, buf1
);
4526 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4529 /* Delete the NHT structure if any, if we're toggling between
4530 * enabling/disabling import check. We deregister the route
4531 * from NHT to avoid overloading NHT and the process interaction
4533 bgp_unlink_nexthop(new);
4535 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4538 /* Aggregate address increment. */
4539 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4541 /* Register new BGP information. */
4542 bgp_info_add(rn
, new);
4544 /* route_node_get lock */
4545 bgp_unlock_node(rn
);
4547 /* Process change. */
4548 bgp_process(bgp
, rn
, afi
, safi
);
4550 if (SAFI_UNICAST
== safi
4551 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4552 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4553 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4556 /* Unintern original. */
4557 aspath_unintern(&attr
.aspath
);
4560 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4563 struct bgp_node
*rn
;
4564 struct bgp_info
*ri
;
4566 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4568 /* Check selected route and self inserted route. */
4569 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4570 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4571 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4574 /* Withdraw static BGP route from routing table. */
4576 if (SAFI_UNICAST
== safi
4577 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4578 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4579 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4581 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4582 bgp_unlink_nexthop(ri
);
4583 bgp_info_delete(rn
, ri
);
4584 bgp_process(bgp
, rn
, afi
, safi
);
4587 /* Unlock bgp_node_lookup. */
4588 bgp_unlock_node(rn
);
4592 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4594 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4595 afi_t afi
, safi_t safi
,
4596 struct prefix_rd
*prd
)
4598 struct bgp_node
*rn
;
4599 struct bgp_info
*ri
;
4601 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4603 /* Check selected route and self inserted route. */
4604 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4605 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4606 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4609 /* Withdraw static BGP route from routing table. */
4612 rfapiProcessWithdraw(
4613 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4614 1); /* Kill, since it is an administrative change */
4616 if (SAFI_MPLS_VPN
== safi
4617 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4618 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4620 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4621 bgp_info_delete(rn
, ri
);
4622 bgp_process(bgp
, rn
, afi
, safi
);
4625 /* Unlock bgp_node_lookup. */
4626 bgp_unlock_node(rn
);
4629 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4630 struct bgp_static
*bgp_static
, afi_t afi
,
4633 struct bgp_node
*rn
;
4634 struct bgp_info
*new;
4635 struct attr
*attr_new
;
4636 struct attr attr
= {0};
4637 struct bgp_info
*ri
;
4639 mpls_label_t label
= 0;
4641 uint32_t num_labels
= 0;
4646 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4648 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4651 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4653 attr
.nexthop
= bgp_static
->igpnexthop
;
4654 attr
.med
= bgp_static
->igpmetric
;
4655 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4657 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4658 || (safi
== SAFI_ENCAP
)) {
4659 if (afi
== AFI_IP
) {
4660 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4661 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4664 if (afi
== AFI_L2VPN
) {
4665 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4667 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4668 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4669 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4670 sizeof(struct in6_addr
));
4671 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4672 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4673 struct bgp_encap_type_vxlan bet
;
4674 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4675 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4676 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4678 if (bgp_static
->router_mac
) {
4679 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4682 /* Apply route-map. */
4683 if (bgp_static
->rmap
.name
) {
4684 struct attr attr_tmp
= attr
;
4685 struct bgp_info info
;
4688 info
.peer
= bgp
->peer_self
;
4689 info
.attr
= &attr_tmp
;
4691 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4693 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4695 bgp
->peer_self
->rmap_type
= 0;
4697 if (ret
== RMAP_DENYMATCH
) {
4698 /* Free uninterned attribute. */
4699 bgp_attr_flush(&attr_tmp
);
4701 /* Unintern original. */
4702 aspath_unintern(&attr
.aspath
);
4703 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4708 attr_new
= bgp_attr_intern(&attr_tmp
);
4710 attr_new
= bgp_attr_intern(&attr
);
4713 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4714 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4715 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4720 memset(&add
, 0, sizeof(union gw_addr
));
4721 if (attrhash_cmp(ri
->attr
, attr_new
)
4722 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4723 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4724 bgp_unlock_node(rn
);
4725 bgp_attr_unintern(&attr_new
);
4726 aspath_unintern(&attr
.aspath
);
4729 /* The attribute is changed. */
4730 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4732 /* Rewrite BGP route information. */
4733 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4734 bgp_info_restore(rn
, ri
);
4736 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4737 bgp_attr_unintern(&ri
->attr
);
4738 ri
->attr
= attr_new
;
4739 ri
->uptime
= bgp_clock();
4742 label
= decode_label(&ri
->extra
->label
[0]);
4745 /* Process change. */
4746 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4747 bgp_process(bgp
, rn
, afi
, safi
);
4749 if (SAFI_MPLS_VPN
== safi
4750 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4751 vpn_leak_to_vrf_update(bgp
, ri
);
4754 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4755 ri
->attr
, afi
, safi
, ri
->type
,
4756 ri
->sub_type
, &label
);
4758 bgp_unlock_node(rn
);
4759 aspath_unintern(&attr
.aspath
);
4765 /* Make new BGP info. */
4766 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4768 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4769 new->extra
= bgp_info_extra_new();
4771 new->extra
->label
[0] = bgp_static
->label
;
4772 new->extra
->num_labels
= num_labels
;
4775 label
= decode_label(&bgp_static
->label
);
4778 /* Aggregate address increment. */
4779 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4781 /* Register new BGP information. */
4782 bgp_info_add(rn
, new);
4783 /* route_node_get lock */
4784 bgp_unlock_node(rn
);
4786 /* Process change. */
4787 bgp_process(bgp
, rn
, afi
, safi
);
4789 if (SAFI_MPLS_VPN
== safi
4790 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4791 vpn_leak_to_vrf_update(bgp
, new);
4794 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4795 safi
, new->type
, new->sub_type
, &label
);
4798 /* Unintern original. */
4799 aspath_unintern(&attr
.aspath
);
4802 /* Configure static BGP network. When user don't run zebra, static
4803 route should be installed as valid. */
4804 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4805 const char *ip_str
, afi_t afi
, safi_t safi
,
4806 const char *rmap
, int backdoor
, uint32_t label_index
)
4808 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4811 struct bgp_static
*bgp_static
;
4812 struct bgp_node
*rn
;
4813 uint8_t need_update
= 0;
4815 /* Convert IP prefix string to struct prefix. */
4816 ret
= str2prefix(ip_str
, &p
);
4818 vty_out(vty
, "%% Malformed prefix\n");
4819 return CMD_WARNING_CONFIG_FAILED
;
4821 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4822 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4823 return CMD_WARNING_CONFIG_FAILED
;
4830 /* Set BGP static route configuration. */
4831 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4834 vty_out(vty
, "%% Can't find static route specified\n");
4835 return CMD_WARNING_CONFIG_FAILED
;
4838 bgp_static
= rn
->info
;
4840 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4841 && (label_index
!= bgp_static
->label_index
)) {
4843 "%% label-index doesn't match static route\n");
4844 return CMD_WARNING_CONFIG_FAILED
;
4847 if ((rmap
&& bgp_static
->rmap
.name
)
4848 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4850 "%% route-map name doesn't match static route\n");
4851 return CMD_WARNING_CONFIG_FAILED
;
4854 /* Update BGP RIB. */
4855 if (!bgp_static
->backdoor
)
4856 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4858 /* Clear configuration. */
4859 bgp_static_free(bgp_static
);
4861 bgp_unlock_node(rn
);
4862 bgp_unlock_node(rn
);
4865 /* Set BGP static route configuration. */
4866 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4869 /* Configuration change. */
4870 bgp_static
= rn
->info
;
4872 /* Label index cannot be changed. */
4873 if (bgp_static
->label_index
!= label_index
) {
4874 vty_out(vty
, "%% cannot change label-index\n");
4875 return CMD_WARNING_CONFIG_FAILED
;
4878 /* Check previous routes are installed into BGP. */
4879 if (bgp_static
->valid
4880 && bgp_static
->backdoor
!= backdoor
)
4883 bgp_static
->backdoor
= backdoor
;
4886 if (bgp_static
->rmap
.name
)
4887 XFREE(MTYPE_ROUTE_MAP_NAME
,
4888 bgp_static
->rmap
.name
);
4889 bgp_static
->rmap
.name
=
4890 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4891 bgp_static
->rmap
.map
=
4892 route_map_lookup_by_name(rmap
);
4894 if (bgp_static
->rmap
.name
)
4895 XFREE(MTYPE_ROUTE_MAP_NAME
,
4896 bgp_static
->rmap
.name
);
4897 bgp_static
->rmap
.name
= NULL
;
4898 bgp_static
->rmap
.map
= NULL
;
4899 bgp_static
->valid
= 0;
4901 bgp_unlock_node(rn
);
4903 /* New configuration. */
4904 bgp_static
= bgp_static_new();
4905 bgp_static
->backdoor
= backdoor
;
4906 bgp_static
->valid
= 0;
4907 bgp_static
->igpmetric
= 0;
4908 bgp_static
->igpnexthop
.s_addr
= 0;
4909 bgp_static
->label_index
= label_index
;
4912 if (bgp_static
->rmap
.name
)
4913 XFREE(MTYPE_ROUTE_MAP_NAME
,
4914 bgp_static
->rmap
.name
);
4915 bgp_static
->rmap
.name
=
4916 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4917 bgp_static
->rmap
.map
=
4918 route_map_lookup_by_name(rmap
);
4920 rn
->info
= bgp_static
;
4923 bgp_static
->valid
= 1;
4925 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4927 if (!bgp_static
->backdoor
)
4928 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4934 void bgp_static_add(struct bgp
*bgp
)
4938 struct bgp_node
*rn
;
4939 struct bgp_node
*rm
;
4940 struct bgp_table
*table
;
4941 struct bgp_static
*bgp_static
;
4943 FOREACH_AFI_SAFI (afi
, safi
)
4944 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4945 rn
= bgp_route_next(rn
)) {
4946 if (rn
->info
== NULL
)
4949 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4950 || (safi
== SAFI_EVPN
)) {
4953 for (rm
= bgp_table_top(table
); rm
;
4954 rm
= bgp_route_next(rm
)) {
4955 bgp_static
= rm
->info
;
4956 bgp_static_update_safi(bgp
, &rm
->p
,
4961 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4967 /* Called from bgp_delete(). Delete all static routes from the BGP
4969 void bgp_static_delete(struct bgp
*bgp
)
4973 struct bgp_node
*rn
;
4974 struct bgp_node
*rm
;
4975 struct bgp_table
*table
;
4976 struct bgp_static
*bgp_static
;
4978 FOREACH_AFI_SAFI (afi
, safi
)
4979 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4980 rn
= bgp_route_next(rn
)) {
4981 if (rn
->info
== NULL
)
4984 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4985 || (safi
== SAFI_EVPN
)) {
4988 for (rm
= bgp_table_top(table
); rm
;
4989 rm
= bgp_route_next(rm
)) {
4990 bgp_static
= rm
->info
;
4991 bgp_static_withdraw_safi(
4992 bgp
, &rm
->p
, AFI_IP
, safi
,
4993 (struct prefix_rd
*)&rn
->p
);
4994 bgp_static_free(bgp_static
);
4996 bgp_unlock_node(rn
);
4999 bgp_static
= rn
->info
;
5000 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5001 bgp_static_free(bgp_static
);
5003 bgp_unlock_node(rn
);
5008 void bgp_static_redo_import_check(struct bgp
*bgp
)
5012 struct bgp_node
*rn
;
5013 struct bgp_node
*rm
;
5014 struct bgp_table
*table
;
5015 struct bgp_static
*bgp_static
;
5017 /* Use this flag to force reprocessing of the route */
5018 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5019 FOREACH_AFI_SAFI (afi
, safi
) {
5020 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5021 rn
= bgp_route_next(rn
)) {
5022 if (rn
->info
== NULL
)
5025 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5026 || (safi
== SAFI_EVPN
)) {
5029 for (rm
= bgp_table_top(table
); rm
;
5030 rm
= bgp_route_next(rm
)) {
5031 bgp_static
= rm
->info
;
5032 bgp_static_update_safi(bgp
, &rm
->p
,
5037 bgp_static
= rn
->info
;
5038 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5043 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5046 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5049 struct bgp_table
*table
;
5050 struct bgp_node
*rn
;
5051 struct bgp_info
*ri
;
5053 table
= bgp
->rib
[afi
][safi
];
5054 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5055 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5056 if (ri
->peer
== bgp
->peer_self
5057 && ((ri
->type
== ZEBRA_ROUTE_BGP
5058 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5059 || (ri
->type
!= ZEBRA_ROUTE_BGP
5061 == BGP_ROUTE_REDISTRIBUTE
))) {
5062 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5064 bgp_unlink_nexthop(ri
);
5065 bgp_info_delete(rn
, ri
);
5066 bgp_process(bgp
, rn
, afi
, safi
);
5073 * Purge all networks and redistributed routes from routing table.
5074 * Invoked upon the instance going down.
5076 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5081 FOREACH_AFI_SAFI (afi
, safi
)
5082 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5087 * Currently this is used to set static routes for VPN and ENCAP.
5088 * I think it can probably be factored with bgp_static_set.
5090 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5091 const char *ip_str
, const char *rd_str
,
5092 const char *label_str
, const char *rmap_str
,
5093 int evpn_type
, const char *esi
, const char *gwip
,
5094 const char *ethtag
, const char *routermac
)
5096 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5099 struct prefix_rd prd
;
5100 struct bgp_node
*prn
;
5101 struct bgp_node
*rn
;
5102 struct bgp_table
*table
;
5103 struct bgp_static
*bgp_static
;
5104 mpls_label_t label
= MPLS_INVALID_LABEL
;
5105 struct prefix gw_ip
;
5107 /* validate ip prefix */
5108 ret
= str2prefix(ip_str
, &p
);
5110 vty_out(vty
, "%% Malformed prefix\n");
5111 return CMD_WARNING_CONFIG_FAILED
;
5114 if ((afi
== AFI_L2VPN
)
5115 && (bgp_build_evpn_prefix(evpn_type
,
5116 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5117 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5118 return CMD_WARNING_CONFIG_FAILED
;
5121 ret
= str2prefix_rd(rd_str
, &prd
);
5123 vty_out(vty
, "%% Malformed rd\n");
5124 return CMD_WARNING_CONFIG_FAILED
;
5128 unsigned long label_val
;
5129 label_val
= strtoul(label_str
, NULL
, 10);
5130 encode_label(label_val
, &label
);
5133 if (safi
== SAFI_EVPN
) {
5134 if (esi
&& str2esi(esi
, NULL
) == 0) {
5135 vty_out(vty
, "%% Malformed ESI\n");
5136 return CMD_WARNING_CONFIG_FAILED
;
5138 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5139 vty_out(vty
, "%% Malformed Router MAC\n");
5140 return CMD_WARNING_CONFIG_FAILED
;
5143 memset(&gw_ip
, 0, sizeof(struct prefix
));
5144 ret
= str2prefix(gwip
, &gw_ip
);
5146 vty_out(vty
, "%% Malformed GatewayIp\n");
5147 return CMD_WARNING_CONFIG_FAILED
;
5149 if ((gw_ip
.family
== AF_INET
5150 && is_evpn_prefix_ipaddr_v6(
5151 (struct prefix_evpn
*)&p
))
5152 || (gw_ip
.family
== AF_INET6
5153 && is_evpn_prefix_ipaddr_v4(
5154 (struct prefix_evpn
*)&p
))) {
5156 "%% GatewayIp family differs with IP prefix\n");
5157 return CMD_WARNING_CONFIG_FAILED
;
5161 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5162 if (prn
->info
== NULL
)
5163 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5165 bgp_unlock_node(prn
);
5168 rn
= bgp_node_get(table
, &p
);
5171 vty_out(vty
, "%% Same network configuration exists\n");
5172 bgp_unlock_node(rn
);
5174 /* New configuration. */
5175 bgp_static
= bgp_static_new();
5176 bgp_static
->backdoor
= 0;
5177 bgp_static
->valid
= 0;
5178 bgp_static
->igpmetric
= 0;
5179 bgp_static
->igpnexthop
.s_addr
= 0;
5180 bgp_static
->label
= label
;
5181 bgp_static
->prd
= prd
;
5184 if (bgp_static
->rmap
.name
)
5185 XFREE(MTYPE_ROUTE_MAP_NAME
,
5186 bgp_static
->rmap
.name
);
5187 bgp_static
->rmap
.name
=
5188 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5189 bgp_static
->rmap
.map
=
5190 route_map_lookup_by_name(rmap_str
);
5193 if (safi
== SAFI_EVPN
) {
5195 bgp_static
->eth_s_id
=
5197 sizeof(struct eth_segment_id
));
5198 str2esi(esi
, bgp_static
->eth_s_id
);
5201 bgp_static
->router_mac
=
5202 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5203 prefix_str2mac(routermac
,
5204 bgp_static
->router_mac
);
5207 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5209 rn
->info
= bgp_static
;
5211 bgp_static
->valid
= 1;
5212 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5218 /* Configure static BGP network. */
5219 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5220 const char *ip_str
, const char *rd_str
,
5221 const char *label_str
, int evpn_type
, const char *esi
,
5222 const char *gwip
, const char *ethtag
)
5224 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5227 struct prefix_rd prd
;
5228 struct bgp_node
*prn
;
5229 struct bgp_node
*rn
;
5230 struct bgp_table
*table
;
5231 struct bgp_static
*bgp_static
;
5232 mpls_label_t label
= MPLS_INVALID_LABEL
;
5234 /* Convert IP prefix string to struct prefix. */
5235 ret
= str2prefix(ip_str
, &p
);
5237 vty_out(vty
, "%% Malformed prefix\n");
5238 return CMD_WARNING_CONFIG_FAILED
;
5241 if ((afi
== AFI_L2VPN
)
5242 && (bgp_build_evpn_prefix(evpn_type
,
5243 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5244 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5245 return CMD_WARNING_CONFIG_FAILED
;
5247 ret
= str2prefix_rd(rd_str
, &prd
);
5249 vty_out(vty
, "%% Malformed rd\n");
5250 return CMD_WARNING_CONFIG_FAILED
;
5254 unsigned long label_val
;
5255 label_val
= strtoul(label_str
, NULL
, 10);
5256 encode_label(label_val
, &label
);
5259 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5260 if (prn
->info
== NULL
)
5261 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5263 bgp_unlock_node(prn
);
5266 rn
= bgp_node_lookup(table
, &p
);
5269 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5271 bgp_static
= rn
->info
;
5272 bgp_static_free(bgp_static
);
5274 bgp_unlock_node(rn
);
5275 bgp_unlock_node(rn
);
5277 vty_out(vty
, "%% Can't find the route\n");
5282 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5283 const char *rmap_name
)
5285 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5286 struct bgp_rmap
*rmap
;
5288 rmap
= &bgp
->table_map
[afi
][safi
];
5291 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5292 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5293 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5296 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5301 if (bgp_fibupd_safi(safi
))
5302 bgp_zebra_announce_table(bgp
, afi
, safi
);
5307 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5308 const char *rmap_name
)
5310 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5311 struct bgp_rmap
*rmap
;
5313 rmap
= &bgp
->table_map
[afi
][safi
];
5315 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5319 if (bgp_fibupd_safi(safi
))
5320 bgp_zebra_announce_table(bgp
, afi
, safi
);
5325 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5328 if (bgp
->table_map
[afi
][safi
].name
) {
5329 vty_out(vty
, " table-map %s\n",
5330 bgp
->table_map
[afi
][safi
].name
);
5334 DEFUN (bgp_table_map
,
5337 "BGP table to RIB route download filter\n"
5338 "Name of the route map\n")
5341 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5342 argv
[idx_word
]->arg
);
5344 DEFUN (no_bgp_table_map
,
5345 no_bgp_table_map_cmd
,
5346 "no table-map WORD",
5348 "BGP table to RIB route download filter\n"
5349 "Name of the route map\n")
5352 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5353 argv
[idx_word
]->arg
);
5359 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5360 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5361 backdoor$backdoor}]",
5363 "Specify a network to announce via BGP\n"
5368 "Route-map to modify the attributes\n"
5369 "Name of the route map\n"
5370 "Label index to associate with the prefix\n"
5371 "Label index value\n"
5372 "Specify a BGP backdoor route\n")
5374 char addr_prefix_str
[BUFSIZ
];
5379 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5382 vty_out(vty
, "%% Inconsistent address and mask\n");
5383 return CMD_WARNING_CONFIG_FAILED
;
5387 return bgp_static_set(
5388 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5389 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5390 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5393 DEFPY(ipv6_bgp_network
,
5394 ipv6_bgp_network_cmd
,
5395 "[no] network X:X::X:X/M$prefix \
5396 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5398 "Specify a network to announce via BGP\n"
5400 "Route-map to modify the attributes\n"
5401 "Name of the route map\n"
5402 "Label index to associate with the prefix\n"
5403 "Label index value\n")
5405 return bgp_static_set(
5406 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5407 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5410 /* Aggreagete address:
5412 advertise-map Set condition to advertise attribute
5413 as-set Generate AS set path information
5414 attribute-map Set attributes of aggregate
5415 route-map Set parameters of aggregate
5416 summary-only Filter more specific routes from updates
5417 suppress-map Conditionally filter more specific routes from updates
5420 struct bgp_aggregate
{
5421 /* Summary-only flag. */
5422 uint8_t summary_only
;
5424 /* AS set generation. */
5427 /* Route-map for aggregated route. */
5428 struct route_map
*map
;
5430 /* Suppress-count. */
5431 unsigned long count
;
5433 /* SAFI configuration. */
5437 static struct bgp_aggregate
*bgp_aggregate_new(void)
5439 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5442 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5444 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5447 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5448 struct community
*comm
)
5450 static struct aspath
*ae
= NULL
;
5453 ae
= aspath_empty();
5458 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5461 if (!community_cmp(ri
->attr
->community
, comm
))
5467 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5468 struct prefix
*p
, uint8_t origin
,
5469 struct aspath
*aspath
,
5470 struct community
*community
,
5471 uint8_t atomic_aggregate
,
5472 struct bgp_aggregate
*aggregate
)
5474 struct bgp_node
*rn
;
5475 struct bgp_table
*table
;
5476 struct bgp_info
*ri
, *new;
5478 table
= bgp
->rib
[afi
][safi
];
5480 rn
= bgp_node_get(table
, p
);
5482 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5483 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5484 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5487 if (aggregate
->count
> 0) {
5489 * If the aggregate information has not changed
5490 * no need to re-install it again.
5492 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5493 bgp_unlock_node(rn
);
5496 aspath_free(aspath
);
5498 community_free(community
);
5504 * Mark the old as unusable
5507 bgp_info_delete(rn
, ri
);
5510 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5511 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5512 community
, aggregate
->as_set
,
5515 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5517 bgp_info_add(rn
, new);
5518 bgp_process(bgp
, rn
, afi
, safi
);
5520 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5521 if (ri
->peer
== bgp
->peer_self
5522 && ri
->type
== ZEBRA_ROUTE_BGP
5523 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5526 /* Withdraw static BGP route from routing table. */
5528 bgp_info_delete(rn
, ri
);
5529 bgp_process(bgp
, rn
, afi
, safi
);
5533 bgp_unlock_node(rn
);
5536 /* Update an aggregate as routes are added/removed from the BGP table */
5537 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5538 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5539 struct bgp_info
*del
,
5540 struct bgp_aggregate
*aggregate
)
5542 struct bgp_table
*table
;
5543 struct bgp_node
*top
;
5544 struct bgp_node
*rn
;
5546 struct aspath
*aspath
= NULL
;
5547 struct aspath
*asmerge
= NULL
;
5548 struct community
*community
= NULL
;
5549 struct community
*commerge
= NULL
;
5550 struct bgp_info
*ri
;
5551 unsigned long match
= 0;
5552 uint8_t atomic_aggregate
= 0;
5554 /* ORIGIN attribute: If at least one route among routes that are
5555 aggregated has ORIGIN with the value INCOMPLETE, then the
5556 aggregated route must have the ORIGIN attribute with the value
5557 INCOMPLETE. Otherwise, if at least one route among routes that
5558 are aggregated has ORIGIN with the value EGP, then the aggregated
5559 route must have the origin attribute with the value EGP. In all
5560 other case the value of the ORIGIN attribute of the aggregated
5561 route is INTERNAL. */
5562 origin
= BGP_ORIGIN_IGP
;
5564 table
= bgp
->rib
[afi
][safi
];
5566 top
= bgp_node_get(table
, p
);
5567 for (rn
= bgp_node_get(table
, p
); rn
;
5568 rn
= bgp_route_next_until(rn
, top
)) {
5569 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5574 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5575 if (BGP_INFO_HOLDDOWN(ri
))
5578 if (del
&& ri
== del
)
5582 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5583 atomic_aggregate
= 1;
5585 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5589 * summary-only aggregate route suppress
5590 * aggregated route announcements.
5592 if (aggregate
->summary_only
) {
5593 (bgp_info_extra_get(ri
))->suppress
++;
5594 bgp_info_set_flag(rn
, ri
,
5595 BGP_INFO_ATTR_CHANGED
);
5602 * If at least one route among routes that are
5603 * aggregated has ORIGIN with the value INCOMPLETE,
5604 * then the aggregated route MUST have the ORIGIN
5605 * attribute with the value INCOMPLETE. Otherwise, if
5606 * at least one route among routes that are aggregated
5607 * has ORIGIN with the value EGP, then the aggregated
5608 * route MUST have the ORIGIN attribute with the value
5611 if (origin
< ri
->attr
->origin
)
5612 origin
= ri
->attr
->origin
;
5614 if (!aggregate
->as_set
)
5618 * as-set aggregate route generate origin, as path,
5619 * and community aggregation.
5622 asmerge
= aspath_aggregate(aspath
,
5624 aspath_free(aspath
);
5627 aspath
= aspath_dup(ri
->attr
->aspath
);
5629 if (!ri
->attr
->community
)
5633 commerge
= community_merge(community
,
5634 ri
->attr
->community
);
5635 community
= community_uniq_sort(commerge
);
5636 community_free(commerge
);
5638 community
= community_dup(ri
->attr
->community
);
5641 bgp_process(bgp
, rn
, afi
, safi
);
5643 bgp_unlock_node(top
);
5648 if (aggregate
->summary_only
)
5649 (bgp_info_extra_get(rinew
))->suppress
++;
5651 if (origin
< rinew
->attr
->origin
)
5652 origin
= rinew
->attr
->origin
;
5654 if (aggregate
->as_set
) {
5656 asmerge
= aspath_aggregate(aspath
,
5657 rinew
->attr
->aspath
);
5658 aspath_free(aspath
);
5661 aspath
= aspath_dup(rinew
->attr
->aspath
);
5663 if (rinew
->attr
->community
) {
5665 commerge
= community_merge(
5667 rinew
->attr
->community
);
5669 community_uniq_sort(commerge
);
5670 community_free(commerge
);
5672 community
= community_dup(
5673 rinew
->attr
->community
);
5678 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5679 atomic_aggregate
, aggregate
);
5681 if (aggregate
->count
== 0) {
5683 aspath_free(aspath
);
5685 community_free(community
);
5689 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5690 safi_t safi
, struct bgp_aggregate
*aggregate
)
5692 struct bgp_table
*table
;
5693 struct bgp_node
*top
;
5694 struct bgp_node
*rn
;
5695 struct bgp_info
*ri
;
5696 unsigned long match
;
5698 table
= bgp
->rib
[afi
][safi
];
5700 /* If routes exists below this node, generate aggregate routes. */
5701 top
= bgp_node_get(table
, p
);
5702 for (rn
= bgp_node_get(table
, p
); rn
;
5703 rn
= bgp_route_next_until(rn
, top
)) {
5704 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5708 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5709 if (BGP_INFO_HOLDDOWN(ri
))
5712 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5715 if (aggregate
->summary_only
&& ri
->extra
) {
5716 ri
->extra
->suppress
--;
5718 if (ri
->extra
->suppress
== 0) {
5720 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5727 /* If this node was suppressed, process the change. */
5729 bgp_process(bgp
, rn
, afi
, safi
);
5731 bgp_unlock_node(top
);
5734 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5735 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5737 struct bgp_node
*child
;
5738 struct bgp_node
*rn
;
5739 struct bgp_aggregate
*aggregate
;
5740 struct bgp_table
*table
;
5742 table
= bgp
->aggregate
[afi
][safi
];
5744 /* No aggregates configured. */
5745 if (bgp_table_top_nolock(table
) == NULL
)
5748 if (p
->prefixlen
== 0)
5751 if (BGP_INFO_HOLDDOWN(ri
))
5754 child
= bgp_node_get(table
, p
);
5756 /* Aggregate address configuration check. */
5757 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5758 if ((aggregate
= rn
->info
) != NULL
5759 && rn
->p
.prefixlen
< p
->prefixlen
) {
5760 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5761 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5764 bgp_unlock_node(child
);
5767 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5768 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5770 struct bgp_node
*child
;
5771 struct bgp_node
*rn
;
5772 struct bgp_aggregate
*aggregate
;
5773 struct bgp_table
*table
;
5775 table
= bgp
->aggregate
[afi
][safi
];
5777 /* No aggregates configured. */
5778 if (bgp_table_top_nolock(table
) == NULL
)
5781 if (p
->prefixlen
== 0)
5784 child
= bgp_node_get(table
, p
);
5786 /* Aggregate address configuration check. */
5787 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5788 if ((aggregate
= rn
->info
) != NULL
5789 && rn
->p
.prefixlen
< p
->prefixlen
) {
5790 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5791 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5794 bgp_unlock_node(child
);
5797 /* Aggregate route attribute. */
5798 #define AGGREGATE_SUMMARY_ONLY 1
5799 #define AGGREGATE_AS_SET 1
5801 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5802 afi_t afi
, safi_t safi
)
5804 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5807 struct bgp_node
*rn
;
5808 struct bgp_aggregate
*aggregate
;
5810 /* Convert string to prefix structure. */
5811 ret
= str2prefix(prefix_str
, &p
);
5813 vty_out(vty
, "Malformed prefix\n");
5814 return CMD_WARNING_CONFIG_FAILED
;
5818 /* Old configuration check. */
5819 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5822 "%% There is no aggregate-address configuration.\n");
5823 return CMD_WARNING_CONFIG_FAILED
;
5826 aggregate
= rn
->info
;
5827 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5828 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5830 /* Unlock aggregate address configuration. */
5832 bgp_aggregate_free(aggregate
);
5833 bgp_unlock_node(rn
);
5834 bgp_unlock_node(rn
);
5839 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5840 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5842 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5845 struct bgp_node
*rn
;
5846 struct bgp_aggregate
*aggregate
;
5848 /* Convert string to prefix structure. */
5849 ret
= str2prefix(prefix_str
, &p
);
5851 vty_out(vty
, "Malformed prefix\n");
5852 return CMD_WARNING_CONFIG_FAILED
;
5856 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5857 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5858 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5860 return CMD_WARNING_CONFIG_FAILED
;
5863 /* Old configuration check. */
5864 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5867 vty_out(vty
, "There is already same aggregate network.\n");
5868 /* try to remove the old entry */
5869 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5871 vty_out(vty
, "Error deleting aggregate.\n");
5872 bgp_unlock_node(rn
);
5873 return CMD_WARNING_CONFIG_FAILED
;
5877 /* Make aggregate address structure. */
5878 aggregate
= bgp_aggregate_new();
5879 aggregate
->summary_only
= summary_only
;
5880 aggregate
->as_set
= as_set
;
5881 aggregate
->safi
= safi
;
5882 rn
->info
= aggregate
;
5884 /* Aggregate address insert into BGP routing table. */
5885 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5890 DEFUN (aggregate_address
,
5891 aggregate_address_cmd
,
5892 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5893 "Configure BGP aggregate entries\n"
5894 "Aggregate prefix\n"
5895 "Generate AS set path information\n"
5896 "Filter more specific routes from updates\n"
5897 "Filter more specific routes from updates\n"
5898 "Generate AS set path information\n")
5901 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5902 char *prefix
= argv
[idx
]->arg
;
5904 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5906 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5907 ? AGGREGATE_SUMMARY_ONLY
5910 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5911 summary_only
, as_set
);
5914 DEFUN (aggregate_address_mask
,
5915 aggregate_address_mask_cmd
,
5916 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5917 "Configure BGP aggregate entries\n"
5918 "Aggregate address\n"
5920 "Generate AS set path information\n"
5921 "Filter more specific routes from updates\n"
5922 "Filter more specific routes from updates\n"
5923 "Generate AS set path information\n")
5926 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5927 char *prefix
= argv
[idx
]->arg
;
5928 char *mask
= argv
[idx
+ 1]->arg
;
5930 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5932 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5933 ? AGGREGATE_SUMMARY_ONLY
5936 char prefix_str
[BUFSIZ
];
5937 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5940 vty_out(vty
, "%% Inconsistent address and mask\n");
5941 return CMD_WARNING_CONFIG_FAILED
;
5944 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5945 summary_only
, as_set
);
5948 DEFUN (no_aggregate_address
,
5949 no_aggregate_address_cmd
,
5950 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5952 "Configure BGP aggregate entries\n"
5953 "Aggregate prefix\n"
5954 "Generate AS set path information\n"
5955 "Filter more specific routes from updates\n"
5956 "Filter more specific routes from updates\n"
5957 "Generate AS set path information\n")
5960 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5961 char *prefix
= argv
[idx
]->arg
;
5962 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5965 DEFUN (no_aggregate_address_mask
,
5966 no_aggregate_address_mask_cmd
,
5967 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5969 "Configure BGP aggregate entries\n"
5970 "Aggregate address\n"
5972 "Generate AS set path information\n"
5973 "Filter more specific routes from updates\n"
5974 "Filter more specific routes from updates\n"
5975 "Generate AS set path information\n")
5978 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5979 char *prefix
= argv
[idx
]->arg
;
5980 char *mask
= argv
[idx
+ 1]->arg
;
5982 char prefix_str
[BUFSIZ
];
5983 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5986 vty_out(vty
, "%% Inconsistent address and mask\n");
5987 return CMD_WARNING_CONFIG_FAILED
;
5990 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5993 DEFUN (ipv6_aggregate_address
,
5994 ipv6_aggregate_address_cmd
,
5995 "aggregate-address X:X::X:X/M [summary-only]",
5996 "Configure BGP aggregate entries\n"
5997 "Aggregate prefix\n"
5998 "Filter more specific routes from updates\n")
6001 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6002 char *prefix
= argv
[idx
]->arg
;
6003 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6004 ? AGGREGATE_SUMMARY_ONLY
6006 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6010 DEFUN (no_ipv6_aggregate_address
,
6011 no_ipv6_aggregate_address_cmd
,
6012 "no aggregate-address X:X::X:X/M [summary-only]",
6014 "Configure BGP aggregate entries\n"
6015 "Aggregate prefix\n"
6016 "Filter more specific routes from updates\n")
6019 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6020 char *prefix
= argv
[idx
]->arg
;
6021 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6024 /* Redistribute route treatment. */
6025 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6026 const union g_addr
*nexthop
, ifindex_t ifindex
,
6027 enum nexthop_types_t nhtype
, uint32_t metric
,
6028 uint8_t type
, unsigned short instance
,
6031 struct bgp_info
*new;
6032 struct bgp_info
*bi
;
6033 struct bgp_info info
;
6034 struct bgp_node
*bn
;
6036 struct attr
*new_attr
;
6039 struct bgp_redist
*red
;
6041 /* Make default attribute. */
6042 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6045 case NEXTHOP_TYPE_IFINDEX
:
6047 case NEXTHOP_TYPE_IPV4
:
6048 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6049 attr
.nexthop
= nexthop
->ipv4
;
6051 case NEXTHOP_TYPE_IPV6
:
6052 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6053 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6054 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6056 case NEXTHOP_TYPE_BLACKHOLE
:
6057 switch (p
->family
) {
6059 attr
.nexthop
.s_addr
= INADDR_ANY
;
6062 memset(&attr
.mp_nexthop_global
, 0,
6063 sizeof(attr
.mp_nexthop_global
));
6064 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6069 attr
.nh_ifindex
= ifindex
;
6072 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6075 afi
= family2afi(p
->family
);
6077 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6079 struct attr attr_new
;
6081 /* Copy attribute for modification. */
6082 bgp_attr_dup(&attr_new
, &attr
);
6084 if (red
->redist_metric_flag
)
6085 attr_new
.med
= red
->redist_metric
;
6087 /* Apply route-map. */
6088 if (red
->rmap
.name
) {
6089 memset(&info
, 0, sizeof(struct bgp_info
));
6090 info
.peer
= bgp
->peer_self
;
6091 info
.attr
= &attr_new
;
6093 SET_FLAG(bgp
->peer_self
->rmap_type
,
6094 PEER_RMAP_TYPE_REDISTRIBUTE
);
6096 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6099 bgp
->peer_self
->rmap_type
= 0;
6101 if (ret
== RMAP_DENYMATCH
) {
6102 /* Free uninterned attribute. */
6103 bgp_attr_flush(&attr_new
);
6105 /* Unintern original. */
6106 aspath_unintern(&attr
.aspath
);
6107 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6112 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6113 bgp_attr_add_gshut_community(&attr_new
);
6115 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6116 SAFI_UNICAST
, p
, NULL
);
6118 new_attr
= bgp_attr_intern(&attr_new
);
6120 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6121 if (bi
->peer
== bgp
->peer_self
6122 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6126 /* Ensure the (source route) type is updated. */
6128 if (attrhash_cmp(bi
->attr
, new_attr
)
6129 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6130 bgp_attr_unintern(&new_attr
);
6131 aspath_unintern(&attr
.aspath
);
6132 bgp_unlock_node(bn
);
6135 /* The attribute is changed. */
6136 bgp_info_set_flag(bn
, bi
,
6137 BGP_INFO_ATTR_CHANGED
);
6139 /* Rewrite BGP route information. */
6140 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6141 bgp_info_restore(bn
, bi
);
6143 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6145 bgp_attr_unintern(&bi
->attr
);
6146 bi
->attr
= new_attr
;
6147 bi
->uptime
= bgp_clock();
6149 /* Process change. */
6150 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6152 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6153 bgp_unlock_node(bn
);
6154 aspath_unintern(&attr
.aspath
);
6156 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6158 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6160 vpn_leak_from_vrf_update(
6161 bgp_get_default(), bgp
, bi
);
6167 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6168 bgp
->peer_self
, new_attr
, bn
);
6169 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6171 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6172 bgp_info_add(bn
, new);
6173 bgp_unlock_node(bn
);
6174 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6176 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6177 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6179 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6183 /* Unintern original. */
6184 aspath_unintern(&attr
.aspath
);
6187 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6188 unsigned short instance
)
6191 struct bgp_node
*rn
;
6192 struct bgp_info
*ri
;
6193 struct bgp_redist
*red
;
6195 afi
= family2afi(p
->family
);
6197 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6199 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6200 SAFI_UNICAST
, p
, NULL
);
6202 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6203 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6207 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6208 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6210 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6213 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6214 bgp_info_delete(rn
, ri
);
6215 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6217 bgp_unlock_node(rn
);
6221 /* Withdraw specified route type's route. */
6222 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6223 unsigned short instance
)
6225 struct bgp_node
*rn
;
6226 struct bgp_info
*ri
;
6227 struct bgp_table
*table
;
6229 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6231 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6232 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6233 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6234 && ri
->instance
== instance
)
6238 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6239 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6241 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6244 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6246 bgp_info_delete(rn
, ri
);
6247 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6252 /* Static function to display route. */
6253 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6257 uint32_t destination
;
6260 if (p
->family
== AF_INET
) {
6262 len
= vty_out(vty
, "%s",
6263 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6265 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6267 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6268 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6269 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6270 || p
->u
.prefix4
.s_addr
== 0) {
6271 /* When mask is natural,
6272 mask is not displayed. */
6274 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6276 json_object_string_add(json
, "prefix",
6277 inet_ntop(p
->family
,
6280 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6282 } else if (p
->family
== AF_ETHERNET
) {
6283 prefix2str(p
, buf
, PREFIX_STRLEN
);
6284 len
= vty_out(vty
, "%s", buf
);
6285 } else if (p
->family
== AF_EVPN
) {
6289 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6292 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6293 } else if (p
->family
== AF_FLOWSPEC
) {
6294 route_vty_out_flowspec(vty
, p
, NULL
,
6296 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6297 NLRI_STRING_FORMAT_MIN
, json
);
6302 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6309 vty_out(vty
, "\n%*s", 20, " ");
6311 vty_out(vty
, "%*s", len
, " ");
6315 enum bgp_display_type
{
6319 /* Print the short form route status for a bgp_info */
6320 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6321 json_object
*json_path
)
6325 /* Route status display. */
6326 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6327 json_object_boolean_true_add(json_path
, "removed");
6329 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6330 json_object_boolean_true_add(json_path
, "stale");
6332 if (binfo
->extra
&& binfo
->extra
->suppress
)
6333 json_object_boolean_true_add(json_path
, "suppressed");
6335 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6336 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6337 json_object_boolean_true_add(json_path
, "valid");
6340 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6341 json_object_boolean_true_add(json_path
, "history");
6343 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6344 json_object_boolean_true_add(json_path
, "damped");
6346 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6347 json_object_boolean_true_add(json_path
, "bestpath");
6349 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6350 json_object_boolean_true_add(json_path
, "multipath");
6352 /* Internal route. */
6353 if ((binfo
->peer
->as
)
6354 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6355 json_object_string_add(json_path
, "pathFrom",
6358 json_object_string_add(json_path
, "pathFrom",
6364 /* Route status display. */
6365 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6367 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6369 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6371 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6372 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6378 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6380 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6382 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6384 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6389 /* Internal route. */
6390 if (binfo
->peer
&& (binfo
->peer
->as
)
6391 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6397 /* called from terminal list command */
6398 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6399 int display
, safi_t safi
, json_object
*json_paths
)
6402 json_object
*json_path
= NULL
;
6403 json_object
*json_nexthops
= NULL
;
6404 json_object
*json_nexthop_global
= NULL
;
6405 json_object
*json_nexthop_ll
= NULL
;
6406 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6407 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6410 bool nexthop_othervrf
= false;
6411 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6412 const char *nexthop_vrfname
= "Default";
6415 json_path
= json_object_new_object();
6417 /* short status lead text */
6418 route_vty_short_status_out(vty
, binfo
, json_path
);
6421 /* print prefix and mask */
6423 route_vty_out_route(p
, vty
, json_path
);
6425 vty_out(vty
, "%*s", 17, " ");
6427 route_vty_out_route(p
, vty
, json_path
);
6430 /* Print attribute */
6434 json_object_array_add(json_paths
, json_path
);
6442 * If vrf id of nexthop is different from that of prefix,
6443 * set up printable string to append
6445 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6446 const char *self
= "";
6451 nexthop_othervrf
= true;
6452 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6454 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6455 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6456 "@%s%s", VRFID_NONE_STR
, self
);
6458 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6459 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6461 if (binfo
->extra
->bgp_orig
->inst_type
!=
6462 BGP_INSTANCE_TYPE_DEFAULT
)
6464 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6466 const char *self
= "";
6471 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6475 * For ENCAP and EVPN routes, nexthop address family is not
6476 * neccessarily the same as the prefix address family.
6477 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6478 * EVPN routes are also exchanged with a MP nexthop. Currently,
6480 * is only IPv4, the value will be present in either
6482 * attr->mp_nexthop_global_in
6484 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6487 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6491 sprintf(nexthop
, "%s",
6492 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6496 sprintf(nexthop
, "%s",
6497 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6501 sprintf(nexthop
, "?");
6506 json_nexthop_global
= json_object_new_object();
6508 json_object_string_add(json_nexthop_global
, "afi",
6509 (af
== AF_INET
) ? "ip" : "ipv6");
6510 json_object_string_add(json_nexthop_global
,
6511 (af
== AF_INET
) ? "ip" : "ipv6",
6513 json_object_boolean_true_add(json_nexthop_global
,
6516 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6517 } else if (safi
== SAFI_EVPN
) {
6519 json_nexthop_global
= json_object_new_object();
6521 json_object_string_add(json_nexthop_global
, "ip",
6522 inet_ntoa(attr
->nexthop
));
6523 json_object_string_add(json_nexthop_global
, "afi",
6525 json_object_boolean_true_add(json_nexthop_global
,
6528 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6530 } else if (safi
== SAFI_FLOWSPEC
) {
6531 if (attr
->nexthop
.s_addr
!= 0) {
6533 json_nexthop_global
= json_object_new_object();
6534 json_object_string_add(
6535 json_nexthop_global
, "ip",
6536 inet_ntoa(attr
->nexthop
));
6537 json_object_string_add(json_nexthop_global
,
6539 json_object_boolean_true_add(json_nexthop_global
,
6542 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6545 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6547 json_nexthop_global
= json_object_new_object();
6549 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6550 json_object_string_add(
6551 json_nexthop_global
, "ip",
6552 inet_ntoa(attr
->mp_nexthop_global_in
));
6554 json_object_string_add(
6555 json_nexthop_global
, "ip",
6556 inet_ntoa(attr
->nexthop
));
6558 json_object_string_add(json_nexthop_global
, "afi",
6560 json_object_boolean_true_add(json_nexthop_global
,
6565 snprintf(buf
, sizeof(buf
), "%s%s",
6566 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6567 vty_out(vty
, "%-16s", buf
);
6572 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6577 json_nexthop_global
= json_object_new_object();
6578 json_object_string_add(
6579 json_nexthop_global
, "ip",
6580 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6582 json_object_string_add(json_nexthop_global
, "afi",
6584 json_object_string_add(json_nexthop_global
, "scope",
6587 /* We display both LL & GL if both have been
6589 if ((attr
->mp_nexthop_len
== 32)
6590 || (binfo
->peer
->conf_if
)) {
6591 json_nexthop_ll
= json_object_new_object();
6592 json_object_string_add(
6593 json_nexthop_ll
, "ip",
6595 &attr
->mp_nexthop_local
, buf
,
6597 json_object_string_add(json_nexthop_ll
, "afi",
6599 json_object_string_add(json_nexthop_ll
, "scope",
6602 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6603 &attr
->mp_nexthop_local
)
6605 && !attr
->mp_nexthop_prefer_global
)
6606 json_object_boolean_true_add(
6607 json_nexthop_ll
, "used");
6609 json_object_boolean_true_add(
6610 json_nexthop_global
, "used");
6612 json_object_boolean_true_add(
6613 json_nexthop_global
, "used");
6615 /* Display LL if LL/Global both in table unless
6616 * prefer-global is set */
6617 if (((attr
->mp_nexthop_len
== 32)
6618 && !attr
->mp_nexthop_prefer_global
)
6619 || (binfo
->peer
->conf_if
)) {
6620 if (binfo
->peer
->conf_if
) {
6621 len
= vty_out(vty
, "%s",
6622 binfo
->peer
->conf_if
);
6623 len
= 16 - len
; /* len of IPv6
6629 vty_out(vty
, "\n%*s", 36, " ");
6631 vty_out(vty
, "%*s", len
, " ");
6637 &attr
->mp_nexthop_local
,
6643 vty_out(vty
, "\n%*s", 36, " ");
6645 vty_out(vty
, "%*s", len
, " ");
6651 &attr
->mp_nexthop_global
, buf
,
6657 vty_out(vty
, "\n%*s", 36, " ");
6659 vty_out(vty
, "%*s", len
, " ");
6665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6667 json_object_int_add(json_path
, "med", attr
->med
);
6669 vty_out(vty
, "%10u", attr
->med
);
6670 else if (!json_paths
)
6674 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6676 json_object_int_add(json_path
, "localpref",
6679 vty_out(vty
, "%7u", attr
->local_pref
);
6680 else if (!json_paths
)
6684 json_object_int_add(json_path
, "weight", attr
->weight
);
6686 vty_out(vty
, "%7u ", attr
->weight
);
6690 json_object_string_add(
6691 json_path
, "peerId",
6692 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6698 json_object_string_add(json_path
, "aspath",
6701 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6706 json_object_string_add(json_path
, "origin",
6707 bgp_origin_long_str
[attr
->origin
]);
6709 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6713 json_object_boolean_true_add(json_path
,
6714 "announceNexthopSelf");
6715 if (nexthop_othervrf
) {
6716 json_object_string_add(json_path
, "nhVrfName",
6719 json_object_int_add(json_path
, "nhVrfId",
6720 ((nexthop_vrfid
== VRF_UNKNOWN
)
6722 : (int)nexthop_vrfid
));
6727 if (json_nexthop_global
|| json_nexthop_ll
) {
6728 json_nexthops
= json_object_new_array();
6730 if (json_nexthop_global
)
6731 json_object_array_add(json_nexthops
,
6732 json_nexthop_global
);
6734 if (json_nexthop_ll
)
6735 json_object_array_add(json_nexthops
,
6738 json_object_object_add(json_path
, "nexthops",
6742 json_object_array_add(json_paths
, json_path
);
6746 /* prints an additional line, indented, with VNC info, if
6748 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6749 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6754 /* called from terminal list command */
6755 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6756 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6758 json_object
*json_status
= NULL
;
6759 json_object
*json_net
= NULL
;
6761 /* Route status display. */
6763 json_status
= json_object_new_object();
6764 json_net
= json_object_new_object();
6771 /* print prefix and mask */
6773 json_object_string_add(
6774 json_net
, "addrPrefix",
6775 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6777 route_vty_out_route(p
, vty
, NULL
);
6779 /* Print attribute */
6782 if (p
->family
== AF_INET
6783 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6784 || safi
== SAFI_EVPN
6785 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6786 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6787 || safi
== SAFI_EVPN
)
6788 json_object_string_add(
6789 json_net
, "nextHop",
6791 attr
->mp_nexthop_global_in
));
6793 json_object_string_add(
6794 json_net
, "nextHop",
6795 inet_ntoa(attr
->nexthop
));
6796 } else if (p
->family
== AF_INET6
6797 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6800 json_object_string_add(
6801 json_net
, "netHopGloabal",
6803 &attr
->mp_nexthop_global
, buf
,
6808 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6809 json_object_int_add(json_net
, "metric",
6812 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6813 json_object_int_add(json_net
, "localPref",
6816 json_object_int_add(json_net
, "weight", attr
->weight
);
6820 json_object_string_add(json_net
, "asPath",
6824 json_object_string_add(json_net
, "bgpOriginCode",
6825 bgp_origin_str
[attr
->origin
]);
6827 if (p
->family
== AF_INET
6828 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6829 || safi
== SAFI_EVPN
6830 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6831 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6832 || safi
== SAFI_EVPN
)
6833 vty_out(vty
, "%-16s",
6835 attr
->mp_nexthop_global_in
));
6837 vty_out(vty
, "%-16s",
6838 inet_ntoa(attr
->nexthop
));
6839 } else if (p
->family
== AF_INET6
6840 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6847 &attr
->mp_nexthop_global
, buf
,
6851 vty_out(vty
, "\n%*s", 36, " ");
6853 vty_out(vty
, "%*s", len
, " ");
6856 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6857 vty_out(vty
, "%10u", attr
->med
);
6861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6862 vty_out(vty
, "%7u", attr
->local_pref
);
6866 vty_out(vty
, "%7u ", attr
->weight
);
6870 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6873 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6877 json_object_boolean_true_add(json_status
, "*");
6878 json_object_boolean_true_add(json_status
, ">");
6879 json_object_object_add(json_net
, "appliedStatusSymbols",
6881 char buf_cut
[BUFSIZ
];
6882 json_object_object_add(
6884 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6890 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6891 struct bgp_info
*binfo
, int display
, safi_t safi
,
6894 json_object
*json_out
= NULL
;
6896 mpls_label_t label
= MPLS_INVALID_LABEL
;
6902 json_out
= json_object_new_object();
6904 /* short status lead text */
6905 route_vty_short_status_out(vty
, binfo
, json_out
);
6907 /* print prefix and mask */
6910 route_vty_out_route(p
, vty
, NULL
);
6912 vty_out(vty
, "%*s", 17, " ");
6915 /* Print attribute */
6918 if (((p
->family
== AF_INET
)
6919 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6920 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6921 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6922 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6923 || safi
== SAFI_EVPN
) {
6925 json_object_string_add(
6926 json_out
, "mpNexthopGlobalIn",
6928 attr
->mp_nexthop_global_in
));
6930 vty_out(vty
, "%-16s",
6932 attr
->mp_nexthop_global_in
));
6935 json_object_string_add(
6936 json_out
, "nexthop",
6937 inet_ntoa(attr
->nexthop
));
6939 vty_out(vty
, "%-16s",
6940 inet_ntoa(attr
->nexthop
));
6942 } else if (((p
->family
== AF_INET6
)
6943 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6944 || (safi
== SAFI_EVPN
6945 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6946 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6950 if (attr
->mp_nexthop_len
6951 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6953 json_object_string_add(
6954 json_out
, "mpNexthopGlobalIn",
6957 &attr
->mp_nexthop_global
,
6958 buf_a
, sizeof(buf_a
)));
6963 &attr
->mp_nexthop_global
,
6964 buf_a
, sizeof(buf_a
)));
6965 } else if (attr
->mp_nexthop_len
6966 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6969 &attr
->mp_nexthop_global
,
6970 buf_a
, sizeof(buf_a
));
6972 &attr
->mp_nexthop_local
,
6973 buf_b
, sizeof(buf_b
));
6974 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6975 json_object_string_add(
6977 "mpNexthopGlobalLocal", buf_c
);
6979 vty_out(vty
, "%s(%s)",
6982 &attr
->mp_nexthop_global
,
6983 buf_a
, sizeof(buf_a
)),
6986 &attr
->mp_nexthop_local
,
6987 buf_b
, sizeof(buf_b
)));
6992 label
= decode_label(&binfo
->extra
->label
[0]);
6994 if (bgp_is_valid_label(&label
)) {
6996 json_object_int_add(json_out
, "notag", label
);
6997 json_object_array_add(json
, json_out
);
6999 vty_out(vty
, "notag/%d", label
);
7005 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7006 struct bgp_info
*binfo
, int display
,
7007 json_object
*json_paths
)
7011 json_object
*json_path
= NULL
;
7014 json_path
= json_object_new_object();
7019 /* short status lead text */
7020 route_vty_short_status_out(vty
, binfo
, json_path
);
7022 /* print prefix and mask */
7024 route_vty_out_route(p
, vty
, NULL
);
7026 vty_out(vty
, "%*s", 17, " ");
7028 /* Print attribute */
7032 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7036 vty_out(vty
, "%-16s",
7037 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7041 vty_out(vty
, "%s(%s)",
7042 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7044 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7051 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7053 vty_out(vty
, "%s", str
);
7054 XFREE(MTYPE_TMP
, str
);
7056 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7058 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7059 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7062 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7065 if (attr
->ecommunity
) {
7067 struct ecommunity_val
*routermac
= ecommunity_lookup(
7068 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7069 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7071 mac
= ecom_mac2str((char *)routermac
->val
);
7073 vty_out(vty
, "/%s", (char *)mac
);
7074 XFREE(MTYPE_TMP
, mac
);
7082 /* dampening route */
7083 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7084 struct bgp_info
*binfo
, int display
, safi_t safi
,
7085 uint8_t use_json
, json_object
*json
)
7089 char timebuf
[BGP_UPTIME_LEN
];
7091 /* short status lead text */
7092 route_vty_short_status_out(vty
, binfo
, json
);
7094 /* print prefix and mask */
7097 route_vty_out_route(p
, vty
, NULL
);
7099 vty_out(vty
, "%*s", 17, " ");
7102 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7106 vty_out(vty
, "\n%*s", 34, " ");
7109 json_object_int_add(json
, "peerHost", len
);
7111 vty_out(vty
, "%*s", len
, " ");
7115 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7118 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7122 /* Print attribute */
7128 json_object_string_add(json
, "asPath",
7131 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7136 json_object_string_add(json
, "origin",
7137 bgp_origin_str
[attr
->origin
]);
7139 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7146 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7147 struct bgp_info
*binfo
, int display
, safi_t safi
,
7148 uint8_t use_json
, json_object
*json
)
7151 struct bgp_damp_info
*bdi
;
7152 char timebuf
[BGP_UPTIME_LEN
];
7158 bdi
= binfo
->extra
->damp_info
;
7160 /* short status lead text */
7161 route_vty_short_status_out(vty
, binfo
, json
);
7163 /* print prefix and mask */
7166 route_vty_out_route(p
, vty
, NULL
);
7168 vty_out(vty
, "%*s", 17, " ");
7171 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7175 vty_out(vty
, "\n%*s", 33, " ");
7178 json_object_int_add(json
, "peerHost", len
);
7180 vty_out(vty
, "%*s", len
, " ");
7183 len
= vty_out(vty
, "%d", bdi
->flap
);
7190 json_object_int_add(json
, "bdiFlap", len
);
7192 vty_out(vty
, "%*s", len
, " ");
7196 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7199 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7200 BGP_UPTIME_LEN
, 0, NULL
));
7202 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7203 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7205 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7206 BGP_UPTIME_LEN
, use_json
, json
);
7209 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7214 vty_out(vty
, "%*s ", 8, " ");
7217 /* Print attribute */
7223 json_object_string_add(json
, "asPath",
7226 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7231 json_object_string_add(json
, "origin",
7232 bgp_origin_str
[attr
->origin
]);
7234 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7240 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7241 int *first
, const char *header
,
7242 json_object
*json_adv_to
)
7244 char buf1
[INET6_ADDRSTRLEN
];
7245 json_object
*json_peer
= NULL
;
7248 /* 'advertised-to' is a dictionary of peers we have advertised
7250 * prefix too. The key is the peer's IP or swpX, the value is
7252 * hostname if we know it and "" if not.
7254 json_peer
= json_object_new_object();
7257 json_object_string_add(json_peer
, "hostname",
7261 json_object_object_add(json_adv_to
, peer
->conf_if
,
7264 json_object_object_add(
7266 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7270 vty_out(vty
, "%s", header
);
7275 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7277 vty_out(vty
, " %s(%s)", peer
->hostname
,
7280 vty_out(vty
, " %s(%s)", peer
->hostname
,
7281 sockunion2str(&peer
->su
, buf1
,
7285 vty_out(vty
, " %s", peer
->conf_if
);
7288 sockunion2str(&peer
->su
, buf1
,
7294 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7295 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7296 json_object
*json_paths
)
7298 char buf
[INET6_ADDRSTRLEN
];
7300 char buf2
[EVPN_ROUTE_STRLEN
];
7302 int sockunion_vty_out(struct vty
*, union sockunion
*);
7304 json_object
*json_bestpath
= NULL
;
7305 json_object
*json_cluster_list
= NULL
;
7306 json_object
*json_cluster_list_list
= NULL
;
7307 json_object
*json_ext_community
= NULL
;
7308 json_object
*json_last_update
= NULL
;
7309 json_object
*json_pmsi
= NULL
;
7310 json_object
*json_nexthop_global
= NULL
;
7311 json_object
*json_nexthop_ll
= NULL
;
7312 json_object
*json_nexthops
= NULL
;
7313 json_object
*json_path
= NULL
;
7314 json_object
*json_peer
= NULL
;
7315 json_object
*json_string
= NULL
;
7316 json_object
*json_adv_to
= NULL
;
7318 struct listnode
*node
, *nnode
;
7320 int addpath_capable
;
7322 unsigned int first_as
;
7323 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7328 json_path
= json_object_new_object();
7329 json_peer
= json_object_new_object();
7330 json_nexthop_global
= json_object_new_object();
7333 if (!json_paths
&& safi
== SAFI_EVPN
) {
7336 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7337 vty_out(vty
, " Route %s", buf2
);
7339 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7340 bgp_evpn_label2str(binfo
->extra
->label
,
7341 binfo
->extra
->num_labels
, tag_buf
,
7343 vty_out(vty
, " VNI %s", tag_buf
);
7346 if (binfo
->extra
&& binfo
->extra
->parent
) {
7347 struct bgp_info
*parent_ri
;
7348 struct bgp_node
*rn
, *prn
;
7350 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7351 rn
= parent_ri
->net
;
7352 if (rn
&& rn
->prn
) {
7354 vty_out(vty
, " Imported from %s:%s\n",
7356 (struct prefix_rd
*)&prn
->p
,
7357 buf1
, sizeof(buf1
)),
7366 /* Line1 display AS-path, Aggregator */
7369 if (!attr
->aspath
->json
)
7370 aspath_str_update(attr
->aspath
, true);
7371 json_object_lock(attr
->aspath
->json
);
7372 json_object_object_add(json_path
, "aspath",
7373 attr
->aspath
->json
);
7375 if (attr
->aspath
->segments
)
7376 aspath_print_vty(vty
, " %s",
7379 vty_out(vty
, " Local");
7383 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7385 json_object_boolean_true_add(json_path
,
7388 vty_out(vty
, ", (removed)");
7391 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7393 json_object_boolean_true_add(json_path
,
7396 vty_out(vty
, ", (stale)");
7399 if (CHECK_FLAG(attr
->flag
,
7400 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7402 json_object_int_add(json_path
, "aggregatorAs",
7403 attr
->aggregator_as
);
7404 json_object_string_add(
7405 json_path
, "aggregatorId",
7406 inet_ntoa(attr
->aggregator_addr
));
7408 vty_out(vty
, ", (aggregated by %u %s)",
7409 attr
->aggregator_as
,
7410 inet_ntoa(attr
->aggregator_addr
));
7414 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7415 PEER_FLAG_REFLECTOR_CLIENT
)) {
7417 json_object_boolean_true_add(
7418 json_path
, "rxedFromRrClient");
7420 vty_out(vty
, ", (Received from a RR-client)");
7423 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7424 PEER_FLAG_RSERVER_CLIENT
)) {
7426 json_object_boolean_true_add(
7427 json_path
, "rxedFromRsClient");
7429 vty_out(vty
, ", (Received from a RS-client)");
7432 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7434 json_object_boolean_true_add(
7435 json_path
, "dampeningHistoryEntry");
7437 vty_out(vty
, ", (history entry)");
7438 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7440 json_object_boolean_true_add(
7441 json_path
, "dampeningSuppressed");
7443 vty_out(vty
, ", (suppressed due to dampening)");
7449 /* Line2 display Next-hop, Neighbor, Router-id */
7450 /* Display the nexthop */
7451 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7452 || p
->family
== AF_EVPN
)
7453 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7454 || safi
== SAFI_EVPN
7455 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7456 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7457 || safi
== SAFI_EVPN
) {
7459 json_object_string_add(
7460 json_nexthop_global
, "ip",
7462 attr
->mp_nexthop_global_in
));
7466 attr
->mp_nexthop_global_in
));
7469 json_object_string_add(
7470 json_nexthop_global
, "ip",
7471 inet_ntoa(attr
->nexthop
));
7474 inet_ntoa(attr
->nexthop
));
7478 json_object_string_add(json_nexthop_global
,
7482 json_object_string_add(
7483 json_nexthop_global
, "ip",
7485 &attr
->mp_nexthop_global
, buf
,
7487 json_object_string_add(json_nexthop_global
,
7489 json_object_string_add(json_nexthop_global
,
7494 &attr
->mp_nexthop_global
, buf
,
7499 /* Display the IGP cost or 'inaccessible' */
7500 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7502 json_object_boolean_false_add(
7503 json_nexthop_global
, "accessible");
7505 vty_out(vty
, " (inaccessible)");
7507 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7509 json_object_int_add(
7510 json_nexthop_global
, "metric",
7511 binfo
->extra
->igpmetric
);
7513 vty_out(vty
, " (metric %u)",
7514 binfo
->extra
->igpmetric
);
7517 /* IGP cost is 0, display this only for json */
7520 json_object_int_add(json_nexthop_global
,
7525 json_object_boolean_true_add(
7526 json_nexthop_global
, "accessible");
7529 /* Display peer "from" output */
7530 /* This path was originated locally */
7531 if (binfo
->peer
== bgp
->peer_self
) {
7533 if (safi
== SAFI_EVPN
7534 || (p
->family
== AF_INET
7535 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7537 json_object_string_add(
7538 json_peer
, "peerId", "0.0.0.0");
7540 vty_out(vty
, " from 0.0.0.0 ");
7543 json_object_string_add(json_peer
,
7546 vty_out(vty
, " from :: ");
7550 json_object_string_add(
7551 json_peer
, "routerId",
7552 inet_ntoa(bgp
->router_id
));
7554 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7557 /* We RXed this path from one of our peers */
7561 json_object_string_add(
7562 json_peer
, "peerId",
7563 sockunion2str(&binfo
->peer
->su
, buf
,
7565 json_object_string_add(
7566 json_peer
, "routerId",
7568 &binfo
->peer
->remote_id
, buf1
,
7571 if (binfo
->peer
->hostname
)
7572 json_object_string_add(
7573 json_peer
, "hostname",
7574 binfo
->peer
->hostname
);
7576 if (binfo
->peer
->domainname
)
7577 json_object_string_add(
7578 json_peer
, "domainname",
7579 binfo
->peer
->domainname
);
7581 if (binfo
->peer
->conf_if
)
7582 json_object_string_add(
7583 json_peer
, "interface",
7584 binfo
->peer
->conf_if
);
7586 if (binfo
->peer
->conf_if
) {
7587 if (binfo
->peer
->hostname
7590 BGP_FLAG_SHOW_HOSTNAME
))
7591 vty_out(vty
, " from %s(%s)",
7592 binfo
->peer
->hostname
,
7593 binfo
->peer
->conf_if
);
7595 vty_out(vty
, " from %s",
7596 binfo
->peer
->conf_if
);
7598 if (binfo
->peer
->hostname
7601 BGP_FLAG_SHOW_HOSTNAME
))
7602 vty_out(vty
, " from %s(%s)",
7603 binfo
->peer
->hostname
,
7606 vty_out(vty
, " from %s",
7615 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7616 vty_out(vty
, " (%s)",
7617 inet_ntoa(attr
->originator_id
));
7619 vty_out(vty
, " (%s)",
7622 &binfo
->peer
->remote_id
,
7623 buf1
, sizeof(buf1
)));
7628 * Note when vrfid of nexthop is different from that of prefix
7630 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7631 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7636 if (binfo
->extra
->bgp_orig
->inst_type
==
7637 BGP_INSTANCE_TYPE_DEFAULT
)
7641 vn
= binfo
->extra
->bgp_orig
->name
;
7643 json_object_string_add(json_path
, "nhVrfName",
7646 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7647 json_object_int_add(json_path
,
7650 json_object_int_add(json_path
,
7651 "nhVrfId", (int)nexthop_vrfid
);
7654 if (nexthop_vrfid
== VRF_UNKNOWN
)
7655 vty_out(vty
, " vrf ?");
7657 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7663 json_object_boolean_true_add(json_path
,
7664 "announceNexthopSelf");
7666 vty_out(vty
, " announce-nh-self");
7673 /* display the link-local nexthop */
7674 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7676 json_nexthop_ll
= json_object_new_object();
7677 json_object_string_add(
7678 json_nexthop_ll
, "ip",
7680 &attr
->mp_nexthop_local
, buf
,
7682 json_object_string_add(json_nexthop_ll
, "afi",
7684 json_object_string_add(json_nexthop_ll
, "scope",
7687 json_object_boolean_true_add(json_nexthop_ll
,
7690 if (!attr
->mp_nexthop_prefer_global
)
7691 json_object_boolean_true_add(
7692 json_nexthop_ll
, "used");
7694 json_object_boolean_true_add(
7695 json_nexthop_global
, "used");
7697 vty_out(vty
, " (%s) %s\n",
7699 &attr
->mp_nexthop_local
, buf
,
7701 attr
->mp_nexthop_prefer_global
7706 /* If we do not have a link-local nexthop then we must flag the
7710 json_object_boolean_true_add(
7711 json_nexthop_global
, "used");
7714 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7715 * Int/Ext/Local, Atomic, best */
7717 json_object_string_add(
7718 json_path
, "origin",
7719 bgp_origin_long_str
[attr
->origin
]);
7721 vty_out(vty
, " Origin %s",
7722 bgp_origin_long_str
[attr
->origin
]);
7724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7726 json_object_int_add(json_path
, "med",
7729 vty_out(vty
, ", metric %u", attr
->med
);
7732 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7734 json_object_int_add(json_path
, "localpref",
7737 vty_out(vty
, ", localpref %u",
7741 json_object_int_add(json_path
, "localpref",
7742 bgp
->default_local_pref
);
7744 vty_out(vty
, ", localpref %u",
7745 bgp
->default_local_pref
);
7748 if (attr
->weight
!= 0) {
7750 json_object_int_add(json_path
, "weight",
7753 vty_out(vty
, ", weight %u", attr
->weight
);
7756 if (attr
->tag
!= 0) {
7758 json_object_int_add(json_path
, "tag",
7761 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7765 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7767 json_object_boolean_false_add(json_path
,
7770 vty_out(vty
, ", invalid");
7771 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7773 json_object_boolean_true_add(json_path
,
7776 vty_out(vty
, ", valid");
7779 if (binfo
->peer
!= bgp
->peer_self
) {
7780 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7781 if (CHECK_FLAG(bgp
->config
,
7782 BGP_CONFIG_CONFEDERATION
)) {
7784 json_object_string_add(
7789 ", confed-internal");
7792 json_object_string_add(
7796 vty_out(vty
, ", internal");
7799 if (bgp_confederation_peers_check(
7800 bgp
, binfo
->peer
->as
)) {
7802 json_object_string_add(
7807 ", confed-external");
7810 json_object_string_add(
7814 vty_out(vty
, ", external");
7817 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7819 json_object_boolean_true_add(json_path
,
7821 json_object_boolean_true_add(json_path
,
7824 vty_out(vty
, ", aggregated, local");
7826 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7828 json_object_boolean_true_add(json_path
,
7831 vty_out(vty
, ", sourced");
7834 json_object_boolean_true_add(json_path
,
7836 json_object_boolean_true_add(json_path
,
7839 vty_out(vty
, ", sourced, local");
7843 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7845 json_object_boolean_true_add(json_path
,
7848 vty_out(vty
, ", atomic-aggregate");
7851 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7852 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7853 && bgp_info_mpath_count(binfo
))) {
7855 json_object_boolean_true_add(json_path
,
7858 vty_out(vty
, ", multipath");
7861 // Mark the bestpath(s)
7862 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7863 first_as
= aspath_get_first_as(attr
->aspath
);
7868 json_object_new_object();
7869 json_object_int_add(json_bestpath
,
7870 "bestpathFromAs", first_as
);
7873 vty_out(vty
, ", bestpath-from-AS %u",
7877 ", bestpath-from-AS Local");
7881 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7885 json_object_new_object();
7886 json_object_boolean_true_add(json_bestpath
,
7889 vty_out(vty
, ", best");
7893 json_object_object_add(json_path
, "bestpath",
7899 /* Line 4 display Community */
7900 if (attr
->community
) {
7902 if (!attr
->community
->json
)
7903 community_str(attr
->community
, true);
7904 json_object_lock(attr
->community
->json
);
7905 json_object_object_add(json_path
, "community",
7906 attr
->community
->json
);
7908 vty_out(vty
, " Community: %s\n",
7909 attr
->community
->str
);
7913 /* Line 5 display Extended-community */
7914 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7916 json_ext_community
= json_object_new_object();
7917 json_object_string_add(json_ext_community
,
7919 attr
->ecommunity
->str
);
7920 json_object_object_add(json_path
,
7921 "extendedCommunity",
7922 json_ext_community
);
7924 vty_out(vty
, " Extended Community: %s\n",
7925 attr
->ecommunity
->str
);
7929 /* Line 6 display Large community */
7930 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7932 if (!attr
->lcommunity
->json
)
7933 lcommunity_str(attr
->lcommunity
, true);
7934 json_object_lock(attr
->lcommunity
->json
);
7935 json_object_object_add(json_path
,
7937 attr
->lcommunity
->json
);
7939 vty_out(vty
, " Large Community: %s\n",
7940 attr
->lcommunity
->str
);
7944 /* Line 7 display Originator, Cluster-id */
7945 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7946 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7948 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7950 json_object_string_add(
7951 json_path
, "originatorId",
7952 inet_ntoa(attr
->originator_id
));
7954 vty_out(vty
, " Originator: %s",
7955 inet_ntoa(attr
->originator_id
));
7958 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7963 json_object_new_object();
7964 json_cluster_list_list
=
7965 json_object_new_array();
7968 i
< attr
->cluster
->length
/ 4;
7970 json_string
= json_object_new_string(
7974 json_object_array_add(
7975 json_cluster_list_list
,
7979 /* struct cluster_list does not have
7981 * aspath and community do. Add this
7984 json_object_string_add(json_cluster_list,
7985 "string", attr->cluster->str);
7987 json_object_object_add(
7988 json_cluster_list
, "list",
7989 json_cluster_list_list
);
7990 json_object_object_add(
7991 json_path
, "clusterList",
7994 vty_out(vty
, ", Cluster list: ");
7997 i
< attr
->cluster
->length
/ 4;
8011 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8012 bgp_damp_info_vty(vty
, binfo
, json_path
);
8015 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8016 && safi
!= SAFI_EVPN
) {
8017 mpls_label_t label
=
8018 label_pton(&binfo
->extra
->label
[0]);
8020 json_object_int_add(json_path
, "remoteLabel",
8023 vty_out(vty
, " Remote label: %d\n", label
);
8027 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8029 json_object_int_add(json_path
, "labelIndex",
8032 vty_out(vty
, " Label Index: %d\n",
8036 /* Line 8 display Addpath IDs */
8037 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8039 json_object_int_add(json_path
, "addpathRxId",
8040 binfo
->addpath_rx_id
);
8041 json_object_int_add(json_path
, "addpathTxId",
8042 binfo
->addpath_tx_id
);
8044 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8045 binfo
->addpath_rx_id
,
8046 binfo
->addpath_tx_id
);
8050 /* If we used addpath to TX a non-bestpath we need to display
8051 * "Advertised to" on a path-by-path basis */
8052 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8055 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8057 bgp_addpath_encode_tx(peer
, afi
, safi
);
8058 has_adj
= bgp_adj_out_lookup(
8059 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8061 if ((addpath_capable
&& has_adj
)
8062 || (!addpath_capable
&& has_adj
8063 && CHECK_FLAG(binfo
->flags
,
8064 BGP_INFO_SELECTED
))) {
8065 if (json_path
&& !json_adv_to
)
8067 json_object_new_object();
8069 route_vty_out_advertised_to(
8078 json_object_object_add(json_path
,
8089 /* Line 9 display Uptime */
8090 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8092 json_last_update
= json_object_new_object();
8093 json_object_int_add(json_last_update
, "epoch", tbuf
);
8094 json_object_string_add(json_last_update
, "string",
8096 json_object_object_add(json_path
, "lastUpdate",
8099 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8101 /* Line 10 display PMSI tunnel attribute, if present */
8102 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8103 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8104 attr
->pmsi_tnl_type
,
8105 PMSI_TNLTYPE_STR_DEFAULT
);
8108 json_pmsi
= json_object_new_object();
8109 json_object_string_add(json_pmsi
,
8111 json_object_object_add(json_path
, "pmsi",
8114 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8120 /* We've constructed the json object for this path, add it to the json
8124 if (json_nexthop_global
|| json_nexthop_ll
) {
8125 json_nexthops
= json_object_new_array();
8127 if (json_nexthop_global
)
8128 json_object_array_add(json_nexthops
,
8129 json_nexthop_global
);
8131 if (json_nexthop_ll
)
8132 json_object_array_add(json_nexthops
,
8135 json_object_object_add(json_path
, "nexthops",
8139 json_object_object_add(json_path
, "peer", json_peer
);
8140 json_object_array_add(json_paths
, json_path
);
8145 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8146 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8147 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8149 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8150 const char *prefix_list_str
, afi_t afi
,
8151 safi_t safi
, enum bgp_show_type type
);
8152 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8153 const char *filter
, afi_t afi
, safi_t safi
,
8154 enum bgp_show_type type
);
8155 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8156 const char *rmap_str
, afi_t afi
, safi_t safi
,
8157 enum bgp_show_type type
);
8158 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8159 const char *com
, int exact
, afi_t afi
,
8161 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8162 const char *prefix
, afi_t afi
, safi_t safi
,
8163 enum bgp_show_type type
);
8164 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8165 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8166 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8167 const char *comstr
, int exact
, afi_t afi
,
8171 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8172 struct bgp_table
*table
, enum bgp_show_type type
,
8173 void *output_arg
, uint8_t use_json
, char *rd
,
8174 int is_last
, unsigned long *output_cum
,
8175 unsigned long *total_cum
,
8176 unsigned long *json_header_depth
)
8178 struct bgp_info
*ri
;
8179 struct bgp_node
*rn
;
8182 unsigned long output_count
= 0;
8183 unsigned long total_count
= 0;
8187 json_object
*json_paths
= NULL
;
8190 if (output_cum
&& *output_cum
!= 0)
8193 if (use_json
&& !*json_header_depth
) {
8195 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8196 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8197 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8198 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8200 table
->version
, inet_ntoa(bgp
->router_id
));
8201 *json_header_depth
= 2;
8203 vty_out(vty
, " \"routeDistinguishers\" : {");
8204 ++*json_header_depth
;
8206 json_paths
= json_object_new_object();
8209 if (use_json
&& rd
) {
8210 vty_out(vty
, " \"%s\" : { ", rd
);
8213 /* Start processing of routes. */
8214 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8215 if (rn
->info
== NULL
)
8220 json_paths
= json_object_new_array();
8224 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8226 if (type
== bgp_show_type_flap_statistics
8227 || type
== bgp_show_type_flap_neighbor
8228 || type
== bgp_show_type_dampend_paths
8229 || type
== bgp_show_type_damp_neighbor
) {
8230 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8233 if (type
== bgp_show_type_regexp
) {
8234 regex_t
*regex
= output_arg
;
8236 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8240 if (type
== bgp_show_type_prefix_list
) {
8241 struct prefix_list
*plist
= output_arg
;
8243 if (prefix_list_apply(plist
, &rn
->p
)
8247 if (type
== bgp_show_type_filter_list
) {
8248 struct as_list
*as_list
= output_arg
;
8250 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8251 != AS_FILTER_PERMIT
)
8254 if (type
== bgp_show_type_route_map
) {
8255 struct route_map
*rmap
= output_arg
;
8256 struct bgp_info binfo
;
8257 struct attr dummy_attr
;
8260 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8262 binfo
.peer
= ri
->peer
;
8263 binfo
.attr
= &dummy_attr
;
8265 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8267 if (ret
== RMAP_DENYMATCH
)
8270 if (type
== bgp_show_type_neighbor
8271 || type
== bgp_show_type_flap_neighbor
8272 || type
== bgp_show_type_damp_neighbor
) {
8273 union sockunion
*su
= output_arg
;
8275 if (ri
->peer
== NULL
8276 || ri
->peer
->su_remote
== NULL
8277 || !sockunion_same(ri
->peer
->su_remote
, su
))
8280 if (type
== bgp_show_type_cidr_only
) {
8281 uint32_t destination
;
8283 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8284 if (IN_CLASSC(destination
)
8285 && rn
->p
.prefixlen
== 24)
8287 if (IN_CLASSB(destination
)
8288 && rn
->p
.prefixlen
== 16)
8290 if (IN_CLASSA(destination
)
8291 && rn
->p
.prefixlen
== 8)
8294 if (type
== bgp_show_type_prefix_longer
) {
8295 struct prefix
*p
= output_arg
;
8297 if (!prefix_match(p
, &rn
->p
))
8300 if (type
== bgp_show_type_community_all
) {
8301 if (!ri
->attr
->community
)
8304 if (type
== bgp_show_type_community
) {
8305 struct community
*com
= output_arg
;
8307 if (!ri
->attr
->community
8308 || !community_match(ri
->attr
->community
,
8312 if (type
== bgp_show_type_community_exact
) {
8313 struct community
*com
= output_arg
;
8315 if (!ri
->attr
->community
8316 || !community_cmp(ri
->attr
->community
, com
))
8319 if (type
== bgp_show_type_community_list
) {
8320 struct community_list
*list
= output_arg
;
8322 if (!community_list_match(ri
->attr
->community
,
8326 if (type
== bgp_show_type_community_list_exact
) {
8327 struct community_list
*list
= output_arg
;
8329 if (!community_list_exact_match(
8330 ri
->attr
->community
, list
))
8333 if (type
== bgp_show_type_lcommunity
) {
8334 struct lcommunity
*lcom
= output_arg
;
8336 if (!ri
->attr
->lcommunity
8337 || !lcommunity_match(ri
->attr
->lcommunity
,
8341 if (type
== bgp_show_type_lcommunity_list
) {
8342 struct community_list
*list
= output_arg
;
8344 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8348 if (type
== bgp_show_type_lcommunity_all
) {
8349 if (!ri
->attr
->lcommunity
)
8352 if (type
== bgp_show_type_dampend_paths
8353 || type
== bgp_show_type_damp_neighbor
) {
8354 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8355 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8359 if (!use_json
&& header
) {
8360 vty_out(vty
, "BGP table version is %" PRIu64
8361 ", local router ID is %s, vrf id ",
8363 inet_ntoa(bgp
->router_id
));
8364 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8365 vty_out(vty
, "%s", VRFID_NONE_STR
);
8367 vty_out(vty
, "%u", bgp
->vrf_id
);
8369 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8370 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8371 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8372 if (type
== bgp_show_type_dampend_paths
8373 || type
== bgp_show_type_damp_neighbor
)
8374 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8375 else if (type
== bgp_show_type_flap_statistics
8376 || type
== bgp_show_type_flap_neighbor
)
8377 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8379 vty_out(vty
, BGP_SHOW_HEADER
);
8382 if (rd
!= NULL
&& !display
&& !output_count
) {
8385 "Route Distinguisher: %s\n",
8388 if (type
== bgp_show_type_dampend_paths
8389 || type
== bgp_show_type_damp_neighbor
)
8390 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8391 safi
, use_json
, json_paths
);
8392 else if (type
== bgp_show_type_flap_statistics
8393 || type
== bgp_show_type_flap_neighbor
)
8394 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8395 safi
, use_json
, json_paths
);
8397 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8408 sprintf(buf2
, "%s/%d",
8409 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8412 vty_out(vty
, "\"%s\": ", buf2
);
8414 vty_out(vty
, ",\"%s\": ", buf2
);
8417 json_object_to_json_string(json_paths
));
8418 json_object_free(json_paths
);
8425 output_count
+= *output_cum
;
8426 *output_cum
= output_count
;
8429 total_count
+= *total_cum
;
8430 *total_cum
= total_count
;
8434 json_object_free(json_paths
);
8436 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8440 for (i
= 0; i
< *json_header_depth
; ++i
)
8441 vty_out(vty
, " } ");
8445 /* No route is displayed */
8446 if (output_count
== 0) {
8447 if (type
== bgp_show_type_normal
)
8449 "No BGP prefixes displayed, %ld exist\n",
8453 "\nDisplayed %ld routes and %ld total paths\n",
8454 output_count
, total_count
);
8461 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8462 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8463 enum bgp_show_type type
, void *output_arg
,
8466 struct bgp_node
*rn
, *next
;
8467 unsigned long output_cum
= 0;
8468 unsigned long total_cum
= 0;
8469 unsigned long json_header_depth
= 0;
8472 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8474 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8475 next
= bgp_route_next(rn
);
8476 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8478 if (rn
->info
!= NULL
) {
8479 struct prefix_rd prd
;
8480 char rd
[RD_ADDRSTRLEN
];
8482 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8483 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8484 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8485 output_arg
, use_json
, rd
, next
== NULL
,
8486 &output_cum
, &total_cum
,
8487 &json_header_depth
);
8493 if (output_cum
== 0)
8494 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8498 "\nDisplayed %ld routes and %ld total paths\n",
8499 output_cum
, total_cum
);
8503 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8504 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8506 struct bgp_table
*table
;
8507 unsigned long json_header_depth
= 0;
8510 bgp
= bgp_get_default();
8515 vty_out(vty
, "No BGP process is configured\n");
8517 vty_out(vty
, "{}\n");
8521 table
= bgp
->rib
[afi
][safi
];
8522 /* use MPLS and ENCAP specific shows until they are merged */
8523 if (safi
== SAFI_MPLS_VPN
) {
8524 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8525 output_arg
, use_json
);
8528 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8529 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8530 output_arg
, use_json
,
8533 /* labeled-unicast routes live in the unicast table */
8534 else if (safi
== SAFI_LABELED_UNICAST
)
8535 safi
= SAFI_UNICAST
;
8537 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8538 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8541 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8542 safi_t safi
, uint8_t use_json
)
8544 struct listnode
*node
, *nnode
;
8549 vty_out(vty
, "{\n");
8551 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8554 vty_out(vty
, ",\n");
8558 vty_out(vty
, "\"%s\":",
8559 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8563 vty_out(vty
, "\nInstance %s:\n",
8564 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8568 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8573 vty_out(vty
, "}\n");
8576 /* Header of detailed BGP route information */
8577 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8578 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8579 afi_t afi
, safi_t safi
, json_object
*json
)
8581 struct bgp_info
*ri
;
8584 struct listnode
*node
, *nnode
;
8585 char buf1
[RD_ADDRSTRLEN
];
8586 char buf2
[INET6_ADDRSTRLEN
];
8587 char buf3
[EVPN_ROUTE_STRLEN
];
8588 char prefix_str
[BUFSIZ
];
8593 int no_advertise
= 0;
8596 int has_valid_label
= 0;
8597 mpls_label_t label
= 0;
8598 json_object
*json_adv_to
= NULL
;
8601 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8603 if (has_valid_label
)
8604 label
= label_pton(&rn
->local_label
);
8607 if (has_valid_label
)
8608 json_object_int_add(json
, "localLabel", label
);
8610 json_object_string_add(
8612 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8614 if (safi
== SAFI_EVPN
)
8615 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8616 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8619 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8620 buf3
, sizeof(buf3
)));
8622 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8623 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8624 ? prefix_rd2str(prd
, buf1
,
8627 safi
== SAFI_MPLS_VPN
? ":" : "",
8628 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8632 if (has_valid_label
)
8633 vty_out(vty
, "Local label: %d\n", label
);
8634 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8635 vty_out(vty
, "not allocated\n");
8638 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8640 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8642 if (ri
->extra
&& ri
->extra
->suppress
)
8644 if (ri
->attr
->community
!= NULL
) {
8645 if (community_include(ri
->attr
->community
,
8646 COMMUNITY_NO_ADVERTISE
))
8648 if (community_include(ri
->attr
->community
,
8649 COMMUNITY_NO_EXPORT
))
8651 if (community_include(ri
->attr
->community
,
8652 COMMUNITY_LOCAL_AS
))
8659 vty_out(vty
, "Paths: (%d available", count
);
8661 vty_out(vty
, ", best #%d", best
);
8662 if (safi
== SAFI_UNICAST
)
8663 vty_out(vty
, ", table %s",
8665 == BGP_INSTANCE_TYPE_DEFAULT
)
8666 ? "Default-IP-Routing-Table"
8669 vty_out(vty
, ", no best path");
8672 vty_out(vty
, ", not advertised to any peer");
8674 vty_out(vty
, ", not advertised to EBGP peer");
8676 vty_out(vty
, ", not advertised outside local AS");
8680 ", Advertisements suppressed by an aggregate.");
8681 vty_out(vty
, ")\n");
8684 /* If we are not using addpath then we can display Advertised to and
8686 * show what peers we advertised the bestpath to. If we are using
8688 * though then we must display Advertised to on a path-by-path basis. */
8689 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8690 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8691 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8692 if (json
&& !json_adv_to
)
8693 json_adv_to
= json_object_new_object();
8695 route_vty_out_advertised_to(
8697 " Advertised to non peer-group peers:\n ",
8704 json_object_object_add(json
, "advertisedTo",
8709 vty_out(vty
, " Not advertised to any peer");
8715 /* Display specified route of BGP table. */
8716 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8717 struct bgp_table
*rib
, const char *ip_str
,
8718 afi_t afi
, safi_t safi
,
8719 struct prefix_rd
*prd
, int prefix_check
,
8720 enum bgp_path_type pathtype
,
8726 struct prefix match
;
8727 struct bgp_node
*rn
;
8728 struct bgp_node
*rm
;
8729 struct bgp_info
*ri
;
8730 struct bgp_table
*table
;
8731 json_object
*json
= NULL
;
8732 json_object
*json_paths
= NULL
;
8734 /* Check IP address argument. */
8735 ret
= str2prefix(ip_str
, &match
);
8737 vty_out(vty
, "address is malformed\n");
8741 match
.family
= afi2family(afi
);
8744 json
= json_object_new_object();
8745 json_paths
= json_object_new_array();
8748 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8749 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8750 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8753 if ((table
= rn
->info
) == NULL
)
8758 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8762 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8763 bgp_unlock_node(rm
);
8767 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8769 route_vty_out_detail_header(
8771 (struct prefix_rd
*)&rn
->p
,
8772 AFI_IP
, safi
, json
);
8777 if (pathtype
== BGP_PATH_ALL
8778 || (pathtype
== BGP_PATH_BESTPATH
8779 && CHECK_FLAG(ri
->flags
,
8781 || (pathtype
== BGP_PATH_MULTIPATH
8782 && (CHECK_FLAG(ri
->flags
,
8784 || CHECK_FLAG(ri
->flags
,
8785 BGP_INFO_SELECTED
))))
8786 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8791 bgp_unlock_node(rm
);
8793 } else if (safi
== SAFI_FLOWSPEC
) {
8794 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8795 &match
, prefix_check
);
8797 route_vty_out_flowspec(vty
, &rn
->p
,
8798 rn
->info
, use_json
?
8799 NLRI_STRING_FORMAT_JSON
:
8800 NLRI_STRING_FORMAT_LARGE
,
8803 bgp_unlock_node(rn
);
8808 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8810 || rn
->p
.prefixlen
== match
.prefixlen
) {
8811 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8813 route_vty_out_detail_header(
8814 vty
, bgp
, rn
, NULL
, afi
,
8820 if (pathtype
== BGP_PATH_ALL
8821 || (pathtype
== BGP_PATH_BESTPATH
8825 || (pathtype
== BGP_PATH_MULTIPATH
8831 BGP_INFO_SELECTED
))))
8832 route_vty_out_detail(
8833 vty
, bgp
, &rn
->p
, ri
,
8834 afi
, safi
, json_paths
);
8838 bgp_unlock_node(rn
);
8844 json_object_object_add(json
, "paths", json_paths
);
8846 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8847 json
, JSON_C_TO_STRING_PRETTY
));
8848 json_object_free(json
);
8851 vty_out(vty
, "%% Network not in table\n");
8859 /* Display specified route of Main RIB */
8860 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8861 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8862 int prefix_check
, enum bgp_path_type pathtype
,
8866 bgp
= bgp_get_default();
8869 vty_out(vty
, "No BGP process is configured\n");
8871 vty_out(vty
, "{}\n");
8876 /* labeled-unicast routes live in the unicast table */
8877 if (safi
== SAFI_LABELED_UNICAST
)
8878 safi
= SAFI_UNICAST
;
8880 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8881 afi
, safi
, prd
, prefix_check
, pathtype
,
8885 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8886 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8889 struct lcommunity
*lcom
;
8895 b
= buffer_new(1024);
8896 for (i
= 0; i
< argc
; i
++) {
8898 buffer_putc(b
, ' ');
8900 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8902 buffer_putstr(b
, argv
[i
]->arg
);
8906 buffer_putc(b
, '\0');
8908 str
= buffer_getstr(b
);
8911 lcom
= lcommunity_str2com(str
);
8912 XFREE(MTYPE_TMP
, str
);
8914 vty_out(vty
, "%% Large-community malformed\n");
8918 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8922 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8923 const char *lcom
, afi_t afi
, safi_t safi
,
8926 struct community_list
*list
;
8928 list
= community_list_lookup(bgp_clist
, lcom
,
8929 LARGE_COMMUNITY_LIST_MASTER
);
8931 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8936 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8940 DEFUN (show_ip_bgp_large_community_list
,
8941 show_ip_bgp_large_community_list_cmd
,
8942 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8946 BGP_INSTANCE_HELP_STR
8948 BGP_SAFI_WITH_LABEL_HELP_STR
8949 "Display routes matching the large-community-list\n"
8950 "large-community-list number\n"
8951 "large-community-list name\n"
8955 afi_t afi
= AFI_IP6
;
8956 safi_t safi
= SAFI_UNICAST
;
8959 if (argv_find(argv
, argc
, "ip", &idx
))
8961 if (argv_find(argv
, argc
, "view", &idx
)
8962 || argv_find(argv
, argc
, "vrf", &idx
))
8963 vrf
= argv
[++idx
]->arg
;
8964 if (argv_find(argv
, argc
, "ipv4", &idx
)
8965 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8966 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8967 if (argv_find(argv
, argc
, "unicast", &idx
)
8968 || argv_find(argv
, argc
, "multicast", &idx
))
8969 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8972 int uj
= use_json(argc
, argv
);
8974 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8976 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8980 argv_find(argv
, argc
, "large-community-list", &idx
);
8981 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8984 DEFUN (show_ip_bgp_large_community
,
8985 show_ip_bgp_large_community_cmd
,
8986 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8990 BGP_INSTANCE_HELP_STR
8992 BGP_SAFI_WITH_LABEL_HELP_STR
8993 "Display routes matching the large-communities\n"
8994 "List of large-community numbers\n"
8998 afi_t afi
= AFI_IP6
;
8999 safi_t safi
= SAFI_UNICAST
;
9002 if (argv_find(argv
, argc
, "ip", &idx
))
9004 if (argv_find(argv
, argc
, "view", &idx
)
9005 || argv_find(argv
, argc
, "vrf", &idx
))
9006 vrf
= argv
[++idx
]->arg
;
9007 if (argv_find(argv
, argc
, "ipv4", &idx
)
9008 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9009 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9010 if (argv_find(argv
, argc
, "unicast", &idx
)
9011 || argv_find(argv
, argc
, "multicast", &idx
))
9012 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9015 int uj
= use_json(argc
, argv
);
9017 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9019 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9023 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9024 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9026 return bgp_show(vty
, bgp
, afi
, safi
,
9027 bgp_show_type_lcommunity_all
, NULL
, uj
);
9030 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9034 /* BGP route print out function without JSON */
9037 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9038 <dampening <parameters>\
9043 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9044 |community-list <(1-500)|WORD> [exact-match]\
9045 |A.B.C.D/M longer-prefixes\
9046 |X:X::X:X/M longer-prefixes\
9051 BGP_INSTANCE_HELP_STR
9053 BGP_SAFI_WITH_LABEL_HELP_STR
9054 "Display detailed information about dampening\n"
9055 "Display detail of configured dampening parameters\n"
9056 "Display routes matching the route-map\n"
9057 "A route-map to match on\n"
9058 "Display routes conforming to the prefix-list\n"
9059 "Prefix-list name\n"
9060 "Display routes conforming to the filter-list\n"
9061 "Regular expression access list name\n"
9062 "BGP RIB advertisement statistics\n"
9063 "Display routes matching the communities\n"
9065 "Do not send outside local AS (well-known community)\n"
9066 "Do not advertise to any peer (well-known community)\n"
9067 "Do not export to next AS (well-known community)\n"
9068 "Graceful shutdown (well-known community)\n"
9069 "Exact match of the communities\n"
9070 "Display routes matching the community-list\n"
9071 "community-list number\n"
9072 "community-list name\n"
9073 "Exact match of the communities\n"
9075 "Display route and more specific routes\n"
9077 "Display route and more specific routes\n")
9079 afi_t afi
= AFI_IP6
;
9080 safi_t safi
= SAFI_UNICAST
;
9081 int exact_match
= 0;
9082 struct bgp
*bgp
= NULL
;
9084 int idx_community_type
= 0;
9086 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9091 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9092 if (argv_find(argv
, argc
, "parameters", &idx
))
9093 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9096 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9097 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9098 safi
, bgp_show_type_prefix_list
);
9100 if (argv_find(argv
, argc
, "filter-list", &idx
))
9101 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9102 safi
, bgp_show_type_filter_list
);
9104 if (argv_find(argv
, argc
, "statistics", &idx
))
9105 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9107 if (argv_find(argv
, argc
, "route-map", &idx
))
9108 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9109 safi
, bgp_show_type_route_map
);
9111 if (argv_find(argv
, argc
, "community", &idx
)) {
9112 /* show a specific community */
9113 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9114 || argv_find(argv
, argc
, "no-advertise",
9115 &idx_community_type
)
9116 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9117 || argv_find(argv
, argc
, "graceful-shutdown",
9118 &idx_community_type
)
9119 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9121 if (argv_find(argv
, argc
, "exact-match", &idx
))
9123 return bgp_show_community(vty
, bgp
,
9124 argv
[idx_community_type
]->arg
,
9125 exact_match
, afi
, safi
);
9129 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9130 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9131 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9133 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9134 exact_match
, afi
, safi
);
9137 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9138 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9139 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9141 bgp_show_type_prefix_longer
);
9146 /* BGP route print out function with JSON */
9147 DEFUN (show_ip_bgp_json
,
9148 show_ip_bgp_json_cmd
,
9149 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9152 |dampening <flap-statistics|dampened-paths>\
9158 BGP_INSTANCE_HELP_STR
9160 BGP_SAFI_WITH_LABEL_HELP_STR
9161 "Display only routes with non-natural netmasks\n"
9162 "Display detailed information about dampening\n"
9163 "Display flap statistics of routes\n"
9164 "Display paths suppressed due to dampening\n"
9165 "Display routes matching the communities\n"
9168 afi_t afi
= AFI_IP6
;
9169 safi_t safi
= SAFI_UNICAST
;
9170 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9171 struct bgp
*bgp
= NULL
;
9174 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9179 int uj
= use_json(argc
, argv
);
9183 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9184 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9187 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9188 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9189 return bgp_show(vty
, bgp
, afi
, safi
,
9190 bgp_show_type_dampend_paths
, NULL
, uj
);
9191 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9192 return bgp_show(vty
, bgp
, afi
, safi
,
9193 bgp_show_type_flap_statistics
, NULL
,
9197 if (argv_find(argv
, argc
, "community", &idx
)) {
9198 /* show all communities */
9199 return bgp_show(vty
, bgp
, afi
, safi
,
9200 bgp_show_type_community_all
, NULL
, uj
);
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
,
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
;