1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "sockunion.h"
36 #include "workqueue.h"
41 #include "bgpd/bgpd.h"
42 #include "bgpd/bgp_table.h"
43 #include "bgpd/bgp_route.h"
44 #include "bgpd/bgp_attr.h"
45 #include "bgpd/bgp_debug.h"
46 #include "bgpd/bgp_aspath.h"
47 #include "bgpd/bgp_regex.h"
48 #include "bgpd/bgp_community.h"
49 #include "bgpd/bgp_ecommunity.h"
50 #include "bgpd/bgp_lcommunity.h"
51 #include "bgpd/bgp_clist.h"
52 #include "bgpd/bgp_packet.h"
53 #include "bgpd/bgp_filter.h"
54 #include "bgpd/bgp_fsm.h"
55 #include "bgpd/bgp_mplsvpn.h"
56 #include "bgpd/bgp_nexthop.h"
57 #include "bgpd/bgp_damp.h"
58 #include "bgpd/bgp_advertise.h"
59 #include "bgpd/bgp_zebra.h"
60 #include "bgpd/bgp_vty.h"
61 #include "bgpd/bgp_mpath.h"
62 #include "bgpd/bgp_nht.h"
63 #include "bgpd/bgp_updgrp.h"
64 #include "bgpd/bgp_label.h"
67 #include "bgpd/rfapi/rfapi_backend.h"
68 #include "bgpd/rfapi/vnc_import_bgp.h"
69 #include "bgpd/rfapi/vnc_export_bgp.h"
71 #include "bgpd/bgp_encap_types.h"
72 #include "bgpd/bgp_encap_tlv.h"
73 #include "bgpd/bgp_evpn.h"
74 #include "bgpd/bgp_evpn_vty.h"
77 /* Extern from bgp_dump.c */
78 extern const char *bgp_origin_str
[];
79 extern const char *bgp_origin_long_str
[];
81 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
82 safi_t safi
, struct prefix
*p
,
83 struct prefix_rd
*prd
)
86 struct bgp_node
*prn
= NULL
;
92 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
93 || (safi
== SAFI_EVPN
)) {
94 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
96 if (prn
->info
== NULL
)
97 prn
->info
= bgp_table_init(afi
, safi
);
103 rn
= bgp_node_get(table
, p
);
105 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
106 || (safi
== SAFI_EVPN
))
112 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
113 safi_t safi
, struct prefix
*p
,
114 struct prefix_rd
*prd
)
117 struct bgp_node
*prn
= NULL
;
122 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
123 || (safi
== SAFI_EVPN
)) {
124 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
128 if (prn
->info
== NULL
) {
129 bgp_unlock_node(prn
);
136 rn
= bgp_node_lookup(table
, p
);
141 /* Allocate bgp_info_extra */
142 static struct bgp_info_extra
*bgp_info_extra_new(void)
144 struct bgp_info_extra
*new;
145 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
146 new->label
= MPLS_INVALID_LABEL
;
150 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
152 if (extra
&& *extra
) {
153 if ((*extra
)->damp_info
)
154 bgp_damp_info_free((*extra
)->damp_info
, 0);
156 (*extra
)->damp_info
= NULL
;
158 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
164 /* Get bgp_info extra information for the given bgp_info, lazy allocated
167 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
170 ri
->extra
= bgp_info_extra_new();
174 /* Allocate new bgp info structure. */
175 struct bgp_info
*bgp_info_new(void)
177 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
180 /* Free bgp route information. */
181 static void bgp_info_free(struct bgp_info
*binfo
)
184 bgp_attr_unintern(&binfo
->attr
);
186 bgp_unlink_nexthop(binfo
);
187 bgp_info_extra_free(&binfo
->extra
);
188 bgp_info_mpath_free(&binfo
->mpath
);
190 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
192 XFREE(MTYPE_BGP_ROUTE
, binfo
);
195 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
201 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
203 assert(binfo
&& binfo
->lock
> 0);
206 if (binfo
->lock
== 0) {
208 zlog_debug ("%s: unlocked and freeing", __func__
);
209 zlog_backtrace (LOG_DEBUG
);
211 bgp_info_free(binfo
);
216 if (binfo
->lock
== 1)
218 zlog_debug ("%s: unlocked to 1", __func__
);
219 zlog_backtrace (LOG_DEBUG
);
226 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
228 struct bgp_info
*top
;
240 peer_lock(ri
->peer
); /* bgp_info peer reference */
243 /* Do the actual removal of info from RIB, for use by bgp_process
244 completion callback *only* */
245 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
248 ri
->next
->prev
= ri
->prev
;
250 ri
->prev
->next
= ri
->next
;
254 bgp_info_mpath_dequeue(ri
);
259 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
261 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
262 /* set of previous already took care of pcount */
263 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
266 /* undo the effects of a previous call to bgp_info_delete; typically
267 called when a route is deleted and then quickly re-added before the
268 deletion has been processed */
269 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
271 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
272 /* unset of previous already took care of pcount */
273 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
276 /* Adjust pcount as required */
277 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
279 struct bgp_table
*table
;
281 assert(rn
&& bgp_node_table(rn
));
282 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
284 table
= bgp_node_table(rn
);
286 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
289 if (!BGP_INFO_COUNTABLE(ri
)
290 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
292 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
294 /* slight hack, but more robust against errors. */
295 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
296 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
299 "%s: Asked to decrement 0 prefix count for peer %s",
300 __func__
, ri
->peer
->host
);
301 zlog_backtrace(LOG_WARNING
);
302 zlog_warn("%s: Please report to Quagga bugzilla",
305 } else if (BGP_INFO_COUNTABLE(ri
)
306 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
307 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
308 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
312 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
314 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
317 /* Set/unset bgp_info flags, adjusting any other state as needed.
318 * This is here primarily to keep prefix-count in check.
320 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, u_int32_t flag
)
322 SET_FLAG(ri
->flags
, flag
);
324 /* early bath if we know it's not a flag that changes countability state
326 if (!CHECK_FLAG(flag
,
327 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
330 bgp_pcount_adjust(rn
, ri
);
333 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
336 UNSET_FLAG(ri
->flags
, flag
);
338 /* early bath if we know it's not a flag that changes countability state
340 if (!CHECK_FLAG(flag
,
341 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
344 bgp_pcount_adjust(rn
, ri
);
347 /* Get MED value. If MED value is missing and "bgp bestpath
348 missing-as-worst" is specified, treat it as the worst value. */
349 static u_int32_t
bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
351 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
354 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
361 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
363 if (ri
->addpath_rx_id
)
364 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
367 sprintf(buf
, "path %s", ri
->peer
->host
);
370 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
372 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
373 struct bgp_info
*exist
, int *paths_eq
,
374 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
375 char *pfx_buf
, afi_t afi
, safi_t safi
)
377 struct attr
*newattr
, *existattr
;
378 bgp_peer_sort_t new_sort
;
379 bgp_peer_sort_t exist_sort
;
381 u_int32_t exist_pref
;
384 u_int32_t new_weight
;
385 u_int32_t exist_weight
;
386 uint32_t newm
, existm
;
387 struct in_addr new_id
;
388 struct in_addr exist_id
;
391 int internal_as_route
;
394 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
395 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
396 u_int32_t new_mm_seq
;
397 u_int32_t exist_mm_seq
;
404 zlog_debug("%s: new is NULL", pfx_buf
);
409 bgp_info_path_with_addpath_rx_str(new, new_buf
);
413 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
419 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
420 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
421 pfx_buf
, new_buf
, new->flags
, exist_buf
,
426 existattr
= exist
->attr
;
428 /* For EVPN routes, we cannot just go by local vs remote, we have to
429 * look at the MAC mobility sequence number, if present.
431 if (safi
== SAFI_EVPN
) {
432 /* This is an error condition described in RFC 7432 Section
434 * states that in this scenario "the PE MUST alert the operator"
436 * does not state what other action to take. In order to provide
438 * consistency in this scenario we are going to prefer the path
442 if (newattr
->sticky
!= existattr
->sticky
) {
444 prefix2str(&new->net
->p
, pfx_buf
,
446 * PREFIX2STR_BUFFER
);
447 bgp_info_path_with_addpath_rx_str(new, new_buf
);
448 bgp_info_path_with_addpath_rx_str(exist
,
452 if (newattr
->sticky
&& !existattr
->sticky
) {
454 "%s: %s wins over %s due to sticky MAC flag",
455 pfx_buf
, new_buf
, exist_buf
);
459 if (!newattr
->sticky
&& existattr
->sticky
) {
461 "%s: %s loses to %s due to sticky MAC flag",
462 pfx_buf
, new_buf
, exist_buf
);
467 new_mm_seq
= mac_mobility_seqnum(newattr
);
468 exist_mm_seq
= mac_mobility_seqnum(existattr
);
470 if (new_mm_seq
> exist_mm_seq
) {
473 "%s: %s wins over %s due to MM seq %u > %u",
474 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
479 if (new_mm_seq
< exist_mm_seq
) {
482 "%s: %s loses to %s due to MM seq %u < %u",
483 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
489 /* 1. Weight check. */
490 new_weight
= exist_weight
= 0;
492 new_weight
= newattr
->weight
;
493 exist_weight
= existattr
->weight
;
495 if (new_weight
> exist_weight
) {
497 zlog_debug("%s: %s wins over %s due to weight %d > %d",
498 pfx_buf
, new_buf
, exist_buf
, new_weight
,
503 if (new_weight
< exist_weight
) {
505 zlog_debug("%s: %s loses to %s due to weight %d < %d",
506 pfx_buf
, new_buf
, exist_buf
, new_weight
,
511 /* 2. Local preference check. */
512 new_pref
= exist_pref
= bgp
->default_local_pref
;
514 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
515 new_pref
= newattr
->local_pref
;
516 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
517 exist_pref
= existattr
->local_pref
;
519 if (new_pref
> exist_pref
) {
522 "%s: %s wins over %s due to localpref %d > %d",
523 pfx_buf
, new_buf
, exist_buf
, new_pref
,
528 if (new_pref
< exist_pref
) {
531 "%s: %s loses to %s due to localpref %d < %d",
532 pfx_buf
, new_buf
, exist_buf
, new_pref
,
537 /* 3. Local route check. We prefer:
539 * - BGP_ROUTE_AGGREGATE
540 * - BGP_ROUTE_REDISTRIBUTE
542 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
545 "%s: %s wins over %s due to preferred BGP_ROUTE type",
546 pfx_buf
, new_buf
, exist_buf
);
550 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
553 "%s: %s loses to %s due to preferred BGP_ROUTE type",
554 pfx_buf
, new_buf
, exist_buf
);
558 /* 4. AS path length check. */
559 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
560 int exist_hops
= aspath_count_hops(existattr
->aspath
);
561 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
563 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
566 aspath_hops
= aspath_count_hops(newattr
->aspath
);
567 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
569 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
572 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
573 pfx_buf
, new_buf
, exist_buf
,
575 (exist_hops
+ exist_confeds
));
579 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
582 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
583 pfx_buf
, new_buf
, exist_buf
,
585 (exist_hops
+ exist_confeds
));
589 int newhops
= aspath_count_hops(newattr
->aspath
);
591 if (newhops
< exist_hops
) {
594 "%s: %s wins over %s due to aspath hopcount %d < %d",
595 pfx_buf
, new_buf
, exist_buf
,
596 newhops
, exist_hops
);
600 if (newhops
> exist_hops
) {
603 "%s: %s loses to %s due to aspath hopcount %d > %d",
604 pfx_buf
, new_buf
, exist_buf
,
605 newhops
, exist_hops
);
611 /* 5. Origin check. */
612 if (newattr
->origin
< existattr
->origin
) {
614 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
615 pfx_buf
, new_buf
, exist_buf
,
616 bgp_origin_long_str
[newattr
->origin
],
617 bgp_origin_long_str
[existattr
->origin
]);
621 if (newattr
->origin
> existattr
->origin
) {
623 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
624 pfx_buf
, new_buf
, exist_buf
,
625 bgp_origin_long_str
[newattr
->origin
],
626 bgp_origin_long_str
[existattr
->origin
]);
631 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
632 && aspath_count_hops(existattr
->aspath
) == 0);
633 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
634 && aspath_count_confeds(existattr
->aspath
) > 0
635 && aspath_count_hops(newattr
->aspath
) == 0
636 && aspath_count_hops(existattr
->aspath
) == 0);
638 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
639 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
640 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
641 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
642 || internal_as_route
) {
643 new_med
= bgp_med_value(new->attr
, bgp
);
644 exist_med
= bgp_med_value(exist
->attr
, bgp
);
646 if (new_med
< exist_med
) {
649 "%s: %s wins over %s due to MED %d < %d",
650 pfx_buf
, new_buf
, exist_buf
, new_med
,
655 if (new_med
> exist_med
) {
658 "%s: %s loses to %s due to MED %d > %d",
659 pfx_buf
, new_buf
, exist_buf
, new_med
,
665 /* 7. Peer type check. */
666 new_sort
= new->peer
->sort
;
667 exist_sort
= exist
->peer
->sort
;
669 if (new_sort
== BGP_PEER_EBGP
670 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
673 "%s: %s wins over %s due to eBGP peer > iBGP peer",
674 pfx_buf
, new_buf
, exist_buf
);
678 if (exist_sort
== BGP_PEER_EBGP
679 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
682 "%s: %s loses to %s due to iBGP peer < eBGP peer",
683 pfx_buf
, new_buf
, exist_buf
);
687 /* 8. IGP metric check. */
691 newm
= new->extra
->igpmetric
;
693 existm
= exist
->extra
->igpmetric
;
698 "%s: %s wins over %s due to IGP metric %d < %d",
699 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
706 "%s: %s loses to %s due to IGP metric %d > %d",
707 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
711 /* 9. Same IGP metric. Compare the cluster list length as
712 representative of IGP hops metric. Rewrite the metric value
713 pair (newm, existm) with the cluster list length. Prefer the
714 path with smaller cluster list length. */
715 if (newm
== existm
) {
716 if (peer_sort(new->peer
) == BGP_PEER_IBGP
717 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
718 && (mpath_cfg
== NULL
720 mpath_cfg
->ibgp_flags
,
721 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
722 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
723 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
728 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
729 pfx_buf
, new_buf
, exist_buf
,
737 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
738 pfx_buf
, new_buf
, exist_buf
,
745 /* 10. confed-external vs. confed-internal */
746 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
747 if (new_sort
== BGP_PEER_CONFED
748 && exist_sort
== BGP_PEER_IBGP
) {
751 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
752 pfx_buf
, new_buf
, exist_buf
);
756 if (exist_sort
== BGP_PEER_CONFED
757 && new_sort
== BGP_PEER_IBGP
) {
760 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
761 pfx_buf
, new_buf
, exist_buf
);
766 /* 11. Maximum path check. */
767 if (newm
== existm
) {
768 /* If one path has a label but the other does not, do not treat
769 * them as equals for multipath
771 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
))
773 && bgp_is_valid_label(&exist
->extra
->label
))) {
776 "%s: %s and %s cannot be multipath, one has a label while the other does not",
777 pfx_buf
, new_buf
, exist_buf
);
778 } else if (bgp_flag_check(bgp
,
779 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
782 * For the two paths, all comparison steps till IGP
784 * have succeeded - including AS_PATH hop count. Since
786 * bestpath as-path multipath-relax' knob is on, we
788 * an exact match of AS_PATH. Thus, mark the paths are
790 * That will trigger both these paths to get into the
798 "%s: %s and %s are equal via multipath-relax",
799 pfx_buf
, new_buf
, exist_buf
);
800 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
801 if (aspath_cmp(new->attr
->aspath
,
802 exist
->attr
->aspath
)) {
807 "%s: %s and %s are equal via matching aspaths",
808 pfx_buf
, new_buf
, exist_buf
);
810 } else if (new->peer
->as
== exist
->peer
->as
) {
815 "%s: %s and %s are equal via same remote-as",
816 pfx_buf
, new_buf
, exist_buf
);
820 * TODO: If unequal cost ibgp multipath is enabled we can
821 * mark the paths as equal here instead of returning
826 "%s: %s wins over %s after IGP metric comparison",
827 pfx_buf
, new_buf
, exist_buf
);
830 "%s: %s loses to %s after IGP metric comparison",
831 pfx_buf
, new_buf
, exist_buf
);
836 /* 12. If both paths are external, prefer the path that was received
837 first (the oldest one). This step minimizes route-flap, since a
838 newer path won't displace an older one, even if it was the
839 preferred route based on the additional decision criteria below. */
840 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
841 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
842 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
845 "%s: %s wins over %s due to oldest external",
846 pfx_buf
, new_buf
, exist_buf
);
850 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
853 "%s: %s loses to %s due to oldest external",
854 pfx_buf
, new_buf
, exist_buf
);
859 /* 13. Router-ID comparision. */
860 /* If one of the paths is "stale", the corresponding peer router-id will
861 * be 0 and would always win over the other path. If originator id is
862 * used for the comparision, it will decide which path is better.
864 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
865 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
867 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
868 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
869 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
871 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
873 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
876 "%s: %s wins over %s due to Router-ID comparison",
877 pfx_buf
, new_buf
, exist_buf
);
881 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
884 "%s: %s loses to %s due to Router-ID comparison",
885 pfx_buf
, new_buf
, exist_buf
);
889 /* 14. Cluster length comparision. */
890 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
891 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
893 if (new_cluster
< exist_cluster
) {
896 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
897 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
902 if (new_cluster
> exist_cluster
) {
905 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
906 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
911 /* 15. Neighbor address comparision. */
912 /* Do this only if neither path is "stale" as stale paths do not have
913 * valid peer information (as the connection may or may not be up).
915 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
918 "%s: %s wins over %s due to latter path being STALE",
919 pfx_buf
, new_buf
, exist_buf
);
923 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
926 "%s: %s loses to %s due to former path being STALE",
927 pfx_buf
, new_buf
, exist_buf
);
931 /* locally configured routes to advertise do not have su_remote */
932 if (new->peer
->su_remote
== NULL
)
934 if (exist
->peer
->su_remote
== NULL
)
937 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
942 "%s: %s loses to %s due to Neighor IP comparison",
943 pfx_buf
, new_buf
, exist_buf
);
950 "%s: %s wins over %s due to Neighor IP comparison",
951 pfx_buf
, new_buf
, exist_buf
);
956 zlog_debug("%s: %s wins over %s due to nothing left to compare",
957 pfx_buf
, new_buf
, exist_buf
);
962 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
963 * is preferred, or 0 if they are the same (usually will only occur if
964 * multipath is enabled
965 * This version is compatible with */
966 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
967 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
972 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
986 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
987 struct attr
*attr
, afi_t afi
,
990 struct bgp_filter
*filter
;
992 filter
= &peer
->filter
[afi
][safi
];
994 #define FILTER_EXIST_WARN(F, f, filter) \
995 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
996 zlog_warn("%s: Could not find configured input %s-list %s!", \
997 peer->host, #f, F##_IN_NAME(filter));
999 if (DISTRIBUTE_IN_NAME(filter
)) {
1000 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1002 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1006 if (PREFIX_LIST_IN_NAME(filter
)) {
1007 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1009 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1013 if (FILTER_LIST_IN_NAME(filter
)) {
1014 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1016 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1021 return FILTER_PERMIT
;
1022 #undef FILTER_EXIST_WARN
1025 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1026 struct attr
*attr
, afi_t afi
,
1029 struct bgp_filter
*filter
;
1031 filter
= &peer
->filter
[afi
][safi
];
1033 #define FILTER_EXIST_WARN(F, f, filter) \
1034 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1035 zlog_warn("%s: Could not find configured output %s-list %s!", \
1036 peer->host, #f, F##_OUT_NAME(filter));
1038 if (DISTRIBUTE_OUT_NAME(filter
)) {
1039 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1041 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1045 if (PREFIX_LIST_OUT_NAME(filter
)) {
1046 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1048 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1053 if (FILTER_LIST_OUT_NAME(filter
)) {
1054 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1056 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1061 return FILTER_PERMIT
;
1062 #undef FILTER_EXIST_WARN
1065 /* If community attribute includes no_export then return 1. */
1066 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1068 if (attr
->community
) {
1069 /* NO_ADVERTISE check. */
1070 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1073 /* NO_EXPORT check. */
1074 if (peer
->sort
== BGP_PEER_EBGP
1075 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1078 /* NO_EXPORT_SUBCONFED check. */
1079 if (peer
->sort
== BGP_PEER_EBGP
1080 || peer
->sort
== BGP_PEER_CONFED
)
1081 if (community_include(attr
->community
,
1082 COMMUNITY_NO_EXPORT_SUBCONFED
))
1088 /* Route reflection loop check. */
1089 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1091 struct in_addr cluster_id
;
1093 if (attr
->cluster
) {
1094 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1095 cluster_id
= peer
->bgp
->cluster_id
;
1097 cluster_id
= peer
->bgp
->router_id
;
1099 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1105 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1106 struct attr
*attr
, afi_t afi
, safi_t safi
,
1107 const char *rmap_name
)
1109 struct bgp_filter
*filter
;
1110 struct bgp_info info
;
1111 route_map_result_t ret
;
1112 struct route_map
*rmap
= NULL
;
1114 filter
= &peer
->filter
[afi
][safi
];
1116 /* Apply default weight value. */
1117 if (peer
->weight
[afi
][safi
])
1118 attr
->weight
= peer
->weight
[afi
][safi
];
1121 rmap
= route_map_lookup_by_name(rmap_name
);
1126 if (ROUTE_MAP_IN_NAME(filter
)) {
1127 rmap
= ROUTE_MAP_IN(filter
);
1134 /* Route map apply. */
1136 /* Duplicate current value to new strucutre for modification. */
1140 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1142 /* Apply BGP route map to the attribute. */
1143 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1145 peer
->rmap_type
= 0;
1147 if (ret
== RMAP_DENYMATCH
) {
1148 /* Free newly generated AS path and community by
1150 bgp_attr_flush(attr
);
1157 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1158 struct attr
*attr
, afi_t afi
, safi_t safi
,
1159 const char *rmap_name
)
1161 struct bgp_filter
*filter
;
1162 struct bgp_info info
;
1163 route_map_result_t ret
;
1164 struct route_map
*rmap
= NULL
;
1166 filter
= &peer
->filter
[afi
][safi
];
1168 /* Apply default weight value. */
1169 if (peer
->weight
[afi
][safi
])
1170 attr
->weight
= peer
->weight
[afi
][safi
];
1173 rmap
= route_map_lookup_by_name(rmap_name
);
1178 if (ROUTE_MAP_OUT_NAME(filter
)) {
1179 rmap
= ROUTE_MAP_OUT(filter
);
1186 /* Route map apply. */
1188 /* Duplicate current value to new strucutre for modification. */
1192 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1194 /* Apply BGP route map to the attribute. */
1195 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1197 peer
->rmap_type
= 0;
1199 if (ret
== RMAP_DENYMATCH
)
1200 /* caller has multiple error paths with bgp_attr_flush()
1207 /* If this is an EBGP peer with remove-private-AS */
1208 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1209 struct peer
*peer
, struct attr
*attr
)
1211 if (peer
->sort
== BGP_PEER_EBGP
1212 && (peer_af_flag_check(peer
, afi
, safi
,
1213 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1214 || peer_af_flag_check(peer
, afi
, safi
,
1215 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1216 || peer_af_flag_check(peer
, afi
, safi
,
1217 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1218 || peer_af_flag_check(peer
, afi
, safi
,
1219 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1220 // Take action on the entire aspath
1221 if (peer_af_flag_check(peer
, afi
, safi
,
1222 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1223 || peer_af_flag_check(peer
, afi
, safi
,
1224 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1225 if (peer_af_flag_check(
1227 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1228 attr
->aspath
= aspath_replace_private_asns(
1229 attr
->aspath
, bgp
->as
);
1231 // The entire aspath consists of private ASNs so create
1233 else if (aspath_private_as_check(attr
->aspath
))
1234 attr
->aspath
= aspath_empty_get();
1236 // There are some public and some private ASNs, remove
1239 attr
->aspath
= aspath_remove_private_asns(
1243 // 'all' was not specified so the entire aspath must be private
1245 // for us to do anything
1246 else if (aspath_private_as_check(attr
->aspath
)) {
1247 if (peer_af_flag_check(
1249 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1250 attr
->aspath
= aspath_replace_private_asns(
1251 attr
->aspath
, bgp
->as
);
1253 attr
->aspath
= aspath_empty_get();
1258 /* If this is an EBGP peer with as-override */
1259 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1260 struct peer
*peer
, struct attr
*attr
)
1262 if (peer
->sort
== BGP_PEER_EBGP
1263 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1264 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1265 attr
->aspath
= aspath_replace_specific_asn(
1266 attr
->aspath
, peer
->as
, bgp
->as
);
1270 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1272 if (family
== AF_INET
)
1273 attr
->nexthop
.s_addr
= 0;
1274 if (family
== AF_INET6
)
1275 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1278 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1279 struct update_subgroup
*subgrp
, struct prefix
*p
,
1282 struct bgp_filter
*filter
;
1285 struct peer
*onlypeer
;
1287 struct attr
*riattr
;
1288 struct peer_af
*paf
;
1289 char buf
[PREFIX_STRLEN
];
1295 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1297 if (DISABLE_BGP_ANNOUNCE
)
1300 afi
= SUBGRP_AFI(subgrp
);
1301 safi
= SUBGRP_SAFI(subgrp
);
1302 peer
= SUBGRP_PEER(subgrp
);
1304 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1305 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1308 filter
= &peer
->filter
[afi
][safi
];
1309 bgp
= SUBGRP_INST(subgrp
);
1310 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1313 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1314 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1315 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1318 * direct and direct_ext type routes originate internally even
1319 * though they can have peer pointers that reference other
1322 prefix2str(p
, buf
, PREFIX_STRLEN
);
1323 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1329 /* With addpath we may be asked to TX all kinds of paths so make sure
1331 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1332 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1333 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1337 /* If this is not the bestpath then check to see if there is an enabled
1339 * feature that requires us to advertise it */
1340 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1341 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1346 /* Aggregate-address suppress check. */
1347 if (ri
->extra
&& ri
->extra
->suppress
)
1348 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1352 /* If it's labeled safi, make sure the route has a valid label. */
1353 if (safi
== SAFI_LABELED_UNICAST
) {
1354 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1355 if (!bgp_is_valid_label(&label
)) {
1356 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1357 zlog_debug("u%" PRIu64
":s%" PRIu64
1358 " %s/%d is filtered - no label (%p)",
1359 subgrp
->update_group
->id
, subgrp
->id
,
1360 inet_ntop(p
->family
, &p
->u
.prefix
,
1361 buf
, SU_ADDRSTRLEN
),
1362 p
->prefixlen
, &label
);
1367 /* Do not send back route to sender. */
1368 if (onlypeer
&& from
== onlypeer
) {
1372 /* Do not send the default route in the BGP table if the neighbor is
1373 * configured for default-originate */
1374 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1375 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1376 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1378 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1382 /* Transparency check. */
1383 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1384 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1389 /* If community is not disabled check the no-export and local. */
1390 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1391 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1393 "subgrpannouncecheck: community filter check fail");
1397 /* If the attribute has originator-id and it is same as remote
1399 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1400 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1401 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1403 "%s [Update:SEND] %s originator-id is same as "
1406 prefix2str(p
, buf
, sizeof(buf
)));
1410 /* ORF prefix-list filter check */
1411 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1412 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1413 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1414 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1415 if (peer
->orf_plist
[afi
][safi
]) {
1416 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1418 if (bgp_debug_update(NULL
, p
,
1419 subgrp
->update_group
, 0))
1421 "%s [Update:SEND] %s is filtered via ORF",
1429 /* Output filter check. */
1430 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1431 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1432 zlog_debug("%s [Update:SEND] %s is filtered",
1433 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1437 #ifdef BGP_SEND_ASPATH_CHECK
1438 /* AS path loop check. */
1439 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1440 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1442 "%s [Update:SEND] suppress announcement to peer AS %u "
1443 "that is part of AS path.",
1444 onlypeer
->host
, onlypeer
->as
);
1447 #endif /* BGP_SEND_ASPATH_CHECK */
1449 /* If we're a CONFED we need to loop check the CONFED ID too */
1450 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1451 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1452 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1454 "%s [Update:SEND] suppress announcement to peer AS %u"
1456 peer
->host
, bgp
->confed_id
);
1461 /* Route-Reflect check. */
1462 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1467 /* IBGP reflection check. */
1468 if (reflect
&& !samepeer_safe
) {
1469 /* A route from a Client peer. */
1470 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1471 PEER_FLAG_REFLECTOR_CLIENT
)) {
1472 /* Reflect to all the Non-Client peers and also to the
1473 Client peers other than the originator. Originator
1475 is already done. So there is noting to do. */
1476 /* no bgp client-to-client reflection check. */
1477 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1478 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1479 PEER_FLAG_REFLECTOR_CLIENT
))
1482 /* A route from a Non-client peer. Reflect to all other
1484 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1485 PEER_FLAG_REFLECTOR_CLIENT
))
1490 /* For modify attribute, copy it to temporary structure. */
1491 bgp_attr_dup(attr
, riattr
);
1493 /* If local-preference is not set. */
1494 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1495 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1496 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1497 attr
->local_pref
= bgp
->default_local_pref
;
1500 /* If originator-id is not set and the route is to be reflected,
1501 set the originator id */
1503 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1504 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1505 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1508 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1510 if (peer
->sort
== BGP_PEER_EBGP
1511 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1512 if (from
!= bgp
->peer_self
&& !transparent
1513 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1514 PEER_FLAG_MED_UNCHANGED
))
1516 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1519 /* Since the nexthop attribute can vary per peer, it is not explicitly
1521 * in announce check, only certain flags and length (or number of
1523 * -- for IPv6/MP_REACH) are set here in order to guide the update
1525 * code in setting the nexthop(s) on a per peer basis in
1527 * Typically, the source nexthop in the attribute is preserved but in
1529 * scenarios where we know it will always be overwritten, we reset the
1530 * nexthop to "0" in an attempt to achieve better Update packing. An
1531 * example of this is when a prefix from each of 2 IBGP peers needs to
1533 * announced to an EBGP peer (and they have the same attributes barring
1537 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1539 #define NEXTHOP_IS_V6 \
1540 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1541 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1542 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1543 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1545 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1547 * the peer (group) is configured to receive link-local nexthop
1549 * and it is available in the prefix OR we're not reflecting the route
1551 * the peer (group) to whom we're going to announce is on a shared
1553 * and this is either a self-originated route or the peer is EBGP.
1555 if (NEXTHOP_IS_V6
) {
1556 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1557 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1558 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1559 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1560 || (!reflect
&& peer
->shared_network
1561 && (from
== bgp
->peer_self
1562 || peer
->sort
== BGP_PEER_EBGP
))) {
1563 attr
->mp_nexthop_len
=
1564 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1567 /* Clear off link-local nexthop in source, whenever it is not
1569 * ensure more prefixes share the same attribute for
1572 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1573 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1574 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1577 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1578 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1580 /* Route map & unsuppress-map apply. */
1581 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1582 struct bgp_info info
;
1583 struct attr dummy_attr
;
1587 /* don't confuse inbound and outbound setting */
1588 RESET_FLAG(attr
->rmap_change_flags
);
1591 * The route reflector is not allowed to modify the attributes
1592 * of the reflected IBGP routes unless explicitly allowed.
1594 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1595 && !bgp_flag_check(bgp
,
1596 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1597 bgp_attr_dup(&dummy_attr
, attr
);
1598 info
.attr
= &dummy_attr
;
1601 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1603 if (ri
->extra
&& ri
->extra
->suppress
)
1604 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1607 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1610 peer
->rmap_type
= 0;
1612 if (ret
== RMAP_DENYMATCH
) {
1613 bgp_attr_flush(attr
);
1618 /* After route-map has been applied, we check to see if the nexthop to
1619 * be carried in the attribute (that is used for the announcement) can
1620 * be cleared off or not. We do this in all cases where we would be
1621 * setting the nexthop to "ourselves". For IPv6, we only need to
1623 * the global nexthop here; the link-local nexthop would have been
1625 * already, and if not, it is required by the update formation code.
1626 * Also see earlier comments in this function.
1629 * If route-map has performed some operation on the nexthop or the peer
1630 * configuration says to pass it unchanged, we cannot reset the nexthop
1631 * here, so only attempt to do it if these aren't true. Note that the
1632 * route-map handler itself might have cleared the nexthop, if for
1634 * it is configured as 'peer-address'.
1636 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1637 riattr
->rmap_change_flags
)
1639 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1640 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1641 /* We can reset the nexthop, if setting (or forcing) it to
1643 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1644 PEER_FLAG_NEXTHOP_SELF
)
1645 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1646 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1648 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1649 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1650 subgroup_announce_reset_nhop(
1651 (peer_cap_enhe(peer
, afi
, safi
)
1655 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1656 /* Can also reset the nexthop if announcing to EBGP, but
1658 * no peer in the subgroup is on a shared subnet.
1659 * Note: 3rd party nexthop currently implemented for
1662 SUBGRP_FOREACH_PEER(subgrp
, paf
)
1664 if (bgp_multiaccess_check_v4(riattr
->nexthop
,
1669 subgroup_announce_reset_nhop(
1670 (peer_cap_enhe(peer
, afi
, safi
)
1675 /* If IPv6/MP and nexthop does not have any override and happens
1677 * be a link-local address, reset it so that we don't pass along
1679 * source's link-local IPv6 address to recipients who may not be
1681 * the same interface.
1683 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1684 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1685 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1692 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1693 struct bgp_maxpaths_cfg
*mpath_cfg
,
1694 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1696 struct bgp_info
*new_select
;
1697 struct bgp_info
*old_select
;
1698 struct bgp_info
*ri
;
1699 struct bgp_info
*ri1
;
1700 struct bgp_info
*ri2
;
1701 struct bgp_info
*nextri
= NULL
;
1702 int paths_eq
, do_mpath
, debug
;
1703 struct list mp_list
;
1704 char pfx_buf
[PREFIX2STR_BUFFER
];
1705 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1707 bgp_mp_list_init(&mp_list
);
1709 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1711 debug
= bgp_debug_bestpath(&rn
->p
);
1714 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1716 /* bgp deterministic-med */
1718 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1720 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1721 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1722 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1724 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1725 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1727 if (BGP_INFO_HOLDDOWN(ri1
))
1729 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1730 if (ri1
->peer
->status
!= Established
)
1735 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1736 if (CHECK_FLAG(ri2
->flags
,
1737 BGP_INFO_DMED_CHECK
))
1739 if (BGP_INFO_HOLDDOWN(ri2
))
1742 && ri2
->peer
!= bgp
->peer_self
1745 PEER_STATUS_NSF_WAIT
))
1746 if (ri2
->peer
->status
1750 if (aspath_cmp_left(ri1
->attr
->aspath
,
1752 || aspath_cmp_left_confed(
1754 ri2
->attr
->aspath
)) {
1755 if (bgp_info_cmp(bgp
, ri2
,
1761 bgp_info_unset_flag(
1763 BGP_INFO_DMED_SELECTED
);
1769 BGP_INFO_DMED_CHECK
);
1773 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1774 bgp_info_set_flag(rn
, new_select
,
1775 BGP_INFO_DMED_SELECTED
);
1778 bgp_info_path_with_addpath_rx_str(new_select
,
1780 zlog_debug("%s: %s is the bestpath from AS %d",
1782 aspath_get_first_as(
1783 new_select
->attr
->aspath
));
1788 /* Check old selected route and new selected route. */
1791 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1793 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1796 if (BGP_INFO_HOLDDOWN(ri
)) {
1797 /* reap REMOVED routes, if needs be
1798 * selected route must stay for a while longer though
1800 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1801 && (ri
!= old_select
))
1802 bgp_info_reap(rn
, ri
);
1807 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1808 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1809 if (ri
->peer
->status
!= Established
)
1812 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1813 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1814 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1818 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1820 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1821 debug
, pfx_buf
, afi
, safi
)) {
1826 /* Now that we know which path is the bestpath see if any of the other
1828 * qualify as multipaths
1832 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1834 sprintf(path_buf
, "NONE");
1836 "%s: After path selection, newbest is %s oldbest was %s",
1838 old_select
? old_select
->peer
->host
: "NONE");
1841 if (do_mpath
&& new_select
) {
1842 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1846 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1848 if (ri
== new_select
) {
1851 "%s: %s is the bestpath, add to the multipath list",
1853 bgp_mp_list_add(&mp_list
, ri
);
1857 if (BGP_INFO_HOLDDOWN(ri
))
1860 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1861 && !CHECK_FLAG(ri
->peer
->sflags
,
1862 PEER_STATUS_NSF_WAIT
))
1863 if (ri
->peer
->status
!= Established
)
1866 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1869 "%s: %s has the same nexthop as the bestpath, skip it",
1874 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1875 debug
, pfx_buf
, afi
, safi
);
1880 "%s: %s is equivalent to the bestpath, add to the multipath list",
1882 bgp_mp_list_add(&mp_list
, ri
);
1887 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1888 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1889 bgp_mp_list_clear(&mp_list
);
1891 result
->old
= old_select
;
1892 result
->new = new_select
;
1898 * A new route/change in bestpath of an existing route. Evaluate the path
1899 * for advertisement to the subgroup.
1901 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1902 struct bgp_info
*selected
,
1903 struct bgp_node
*rn
,
1904 u_int32_t addpath_tx_id
)
1907 struct peer
*onlypeer
;
1913 afi
= SUBGRP_AFI(subgrp
);
1914 safi
= SUBGRP_SAFI(subgrp
);
1915 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1918 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1919 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1920 PEER_STATUS_ORF_WAIT_REFRESH
))
1923 memset(&attr
, 0, sizeof(struct attr
));
1924 /* It's initialized in bgp_announce_check() */
1926 /* Announcement to the subgroup. If the route is filtered withdraw it.
1929 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1930 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1932 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1933 selected
->addpath_tx_id
);
1936 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1938 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1945 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1946 * This is called at the end of route processing.
1948 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1950 struct bgp_info
*ri
;
1952 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1953 if (BGP_INFO_HOLDDOWN(ri
))
1955 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1956 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
1961 * Has the route changed from the RIB's perspective? This is invoked only
1962 * if the route selection returns the same best route as earlier - to
1963 * determine if we need to update zebra or not.
1965 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
1967 struct bgp_info
*mpinfo
;
1969 /* If this is multipath, check all selected paths for any nexthop change
1971 * attribute change. Some attribute changes (e.g., community) aren't of
1972 * relevance to the RIB, but we'll update zebra to ensure we handle the
1973 * case of BGP nexthop change. This is the behavior when the best path
1975 * an attribute change anyway.
1977 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
1978 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
1981 /* If this is multipath, check all selected paths for any nexthop change
1983 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
1984 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
1985 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
1986 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
1990 /* Nothing has changed from the RIB's perspective. */
1994 struct bgp_process_queue
{
1996 struct bgp_node
*rn
;
2001 static wq_item_status
bgp_process_main(struct work_queue
*wq
, void *data
)
2003 struct bgp_process_queue
*pq
= data
;
2004 struct bgp
*bgp
= pq
->bgp
;
2005 struct bgp_node
*rn
= pq
->rn
;
2006 afi_t afi
= pq
->afi
;
2007 safi_t safi
= pq
->safi
;
2008 struct prefix
*p
= &rn
->p
;
2009 struct bgp_info
*new_select
;
2010 struct bgp_info
*old_select
;
2011 struct bgp_info_pair old_and_new
;
2013 /* Is it end of initial update? (after startup) */
2015 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2016 sizeof(bgp
->update_delay_zebra_resume_time
));
2018 bgp
->main_zebra_update_hold
= 0;
2019 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
2020 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
2021 if (bgp_fibupd_safi(safi
))
2022 bgp_zebra_announce_table(bgp
, afi
,
2025 bgp
->main_peers_update_hold
= 0;
2027 bgp_start_routeadv(bgp
);
2031 /* Best path selection. */
2032 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2034 old_select
= old_and_new
.old
;
2035 new_select
= old_and_new
.new;
2037 /* Do we need to allocate or free labels?
2038 * Right now, since we only deal with per-prefix labels, it is not
2040 * to do this upon changes to best path except of the label index
2043 if (safi
== SAFI_UNICAST
) {
2046 || bgp_label_index_differs(new_select
, old_select
)
2047 || new_select
->sub_type
!= old_select
->sub_type
) {
2048 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2049 && new_select
->attr
->flag
2051 BGP_ATTR_PREFIX_SID
)
2052 && new_select
->attr
->label_index
2053 != BGP_INVALID_LABEL_INDEX
) {
2056 BGP_NODE_REGISTERED_FOR_LABEL
))
2057 bgp_unregister_for_label(rn
);
2058 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2060 bgp_set_valid_label(&rn
->local_label
);
2062 bgp_register_for_label(rn
, new_select
);
2064 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
2065 bgp_unregister_for_label(rn
);
2068 /* If best route remains the same and this is not due to user-initiated
2069 * clear, see exactly what needs to be done.
2072 if (old_select
&& old_select
== new_select
2073 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2074 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2075 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2076 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2078 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2079 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2081 if (bgp_fibupd_safi(safi
) && !bgp
->name
2082 && !bgp_option_check(BGP_OPT_NO_FIB
)
2083 && new_select
->type
== ZEBRA_ROUTE_BGP
2084 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2085 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2088 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2089 bgp_zebra_clear_route_change_flags(rn
);
2091 /* If there is a change of interest to peers, reannounce the
2093 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2094 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2095 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2097 /* unicast routes must also be annouced to
2098 * labeled-unicast update-groups */
2099 if (safi
== SAFI_UNICAST
)
2100 group_announce_route(bgp
, afi
,
2101 SAFI_LABELED_UNICAST
, rn
,
2104 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2105 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2108 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2112 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2114 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2116 /* bestpath has changed; bump version */
2117 if (old_select
|| new_select
) {
2118 bgp_bump_version(rn
);
2120 if (!bgp
->t_rmap_def_originate_eval
) {
2124 update_group_refresh_default_originate_route_map
,
2125 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2126 &bgp
->t_rmap_def_originate_eval
);
2131 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2133 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2134 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2135 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2139 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2140 if (old_select
!= new_select
) {
2142 vnc_import_bgp_exterior_del_route(bgp
, p
,
2144 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2147 vnc_import_bgp_exterior_add_route(bgp
, p
,
2149 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2155 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2157 /* unicast routes must also be annouced to labeled-unicast update-groups
2159 if (safi
== SAFI_UNICAST
)
2160 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2164 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2165 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2166 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2167 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2168 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2169 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2171 /* Withdraw the route from the kernel. */
2172 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2173 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2174 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2175 bgp_zebra_withdraw(p
, old_select
, safi
);
2179 /* Clear any route change flags. */
2180 bgp_zebra_clear_route_change_flags(rn
);
2182 /* Reap old select bgp_info, if it has been removed */
2183 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2184 bgp_info_reap(rn
, old_select
);
2186 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2190 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2192 struct bgp_process_queue
*pq
= data
;
2193 struct bgp_table
*table
;
2195 bgp_unlock(pq
->bgp
);
2197 table
= bgp_node_table(pq
->rn
);
2198 bgp_unlock_node(pq
->rn
);
2199 bgp_table_unlock(table
);
2201 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pq
);
2204 void bgp_process_queue_init(void)
2206 if (!bm
->process_main_queue
) {
2207 bm
->process_main_queue
=
2208 work_queue_new(bm
->master
, "process_main_queue");
2210 if (!bm
->process_main_queue
) {
2211 zlog_err("%s: Failed to allocate work queue", __func__
);
2216 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_main
;
2217 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2218 bm
->process_main_queue
->spec
.max_retries
= 0;
2219 bm
->process_main_queue
->spec
.hold
= 50;
2220 /* Use a higher yield value of 50ms for main queue processing */
2221 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2224 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2226 struct bgp_process_queue
*pqnode
;
2228 /* already scheduled for processing? */
2229 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2232 if (bm
->process_main_queue
== NULL
)
2235 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2236 sizeof(struct bgp_process_queue
));
2240 /* all unlocked in bgp_processq_del */
2241 bgp_table_lock(bgp_node_table(rn
));
2242 pqnode
->rn
= bgp_lock_node(rn
);
2246 pqnode
->safi
= safi
;
2247 work_queue_add(bm
->process_main_queue
, pqnode
);
2248 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2252 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2254 struct bgp_process_queue
*pqnode
;
2256 if (bm
->process_main_queue
== NULL
)
2259 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2260 sizeof(struct bgp_process_queue
));
2267 work_queue_add(bm
->process_main_queue
, pqnode
);
2270 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2274 peer
= THREAD_ARG(thread
);
2275 peer
->t_pmax_restart
= NULL
;
2277 if (bgp_debug_neighbor_events(peer
))
2279 "%s Maximum-prefix restart timer expired, restore peering",
2282 peer_clear(peer
, NULL
);
2287 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2293 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2296 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2297 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2298 PEER_STATUS_PREFIX_LIMIT
)
2303 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2305 afi_safi_print(afi
, safi
), peer
->host
,
2306 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2307 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2309 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2310 PEER_FLAG_MAX_PREFIX_WARNING
))
2313 /* Convert AFI, SAFI to values for packet. */
2314 pkt_afi
= afi_int2iana(afi
);
2315 pkt_safi
= safi_int2iana(safi
);
2319 ndata
[0] = (pkt_afi
>> 8);
2321 ndata
[2] = pkt_safi
;
2322 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2323 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2324 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2325 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2327 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2328 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2329 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2333 /* Dynamic peers will just close their connection. */
2334 if (peer_dynamic_neighbor(peer
))
2337 /* restart timer start */
2338 if (peer
->pmax_restart
[afi
][safi
]) {
2339 peer
->v_pmax_restart
=
2340 peer
->pmax_restart
[afi
][safi
] * 60;
2342 if (bgp_debug_neighbor_events(peer
))
2344 "%s Maximum-prefix restart timer started for %d secs",
2345 peer
->host
, peer
->v_pmax_restart
);
2347 BGP_TIMER_ON(peer
->t_pmax_restart
,
2348 bgp_maximum_prefix_restart_timer
,
2349 peer
->v_pmax_restart
);
2354 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2355 PEER_STATUS_PREFIX_LIMIT
);
2357 if (peer
->pcount
[afi
][safi
]
2358 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2359 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2360 PEER_STATUS_PREFIX_THRESHOLD
)
2365 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2366 afi_safi_print(afi
, safi
), peer
->host
,
2367 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2368 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2369 PEER_STATUS_PREFIX_THRESHOLD
);
2371 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2372 PEER_STATUS_PREFIX_THRESHOLD
);
2376 /* Unconditionally remove the route from the RIB, without taking
2377 * damping into consideration (eg, because the session went down)
2379 static void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
,
2380 struct peer
*peer
, afi_t afi
, safi_t safi
)
2382 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2384 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2385 bgp_info_delete(rn
, ri
); /* keep historical info */
2387 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2390 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2391 struct peer
*peer
, afi_t afi
, safi_t safi
,
2392 struct prefix_rd
*prd
)
2394 int status
= BGP_DAMP_NONE
;
2396 /* apply dampening, if result is suppressed, we'll be retaining
2397 * the bgp_info in the RIB for historical reference.
2399 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2400 && peer
->sort
== BGP_PEER_EBGP
)
2401 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2402 == BGP_DAMP_SUPPRESSED
) {
2403 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2409 if (safi
== SAFI_MPLS_VPN
) {
2410 struct bgp_node
*prn
= NULL
;
2411 struct bgp_table
*table
= NULL
;
2413 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2414 (struct prefix
*)prd
);
2416 table
= (struct bgp_table
*)(prn
->info
);
2418 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2419 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2421 bgp_unlock_node(prn
);
2423 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2424 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2426 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2427 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2433 /* If this is an EVPN route, process for un-import. */
2434 if (safi
== SAFI_EVPN
)
2435 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2437 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2440 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2441 struct peer
*peer
, struct attr
*attr
,
2442 struct bgp_node
*rn
)
2444 struct bgp_info
*new;
2446 /* Make new BGP info. */
2447 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2449 new->instance
= instance
;
2450 new->sub_type
= sub_type
;
2453 new->uptime
= bgp_clock();
2455 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2459 static void overlay_index_update(struct attr
*attr
,
2460 struct eth_segment_id
*eth_s_id
,
2461 union gw_addr
*gw_ip
)
2466 if (eth_s_id
== NULL
) {
2467 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2468 sizeof(struct eth_segment_id
));
2470 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2471 sizeof(struct eth_segment_id
));
2473 if (gw_ip
== NULL
) {
2474 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2476 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2477 sizeof(union gw_addr
));
2481 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2482 struct eth_segment_id
*eth_s_id
,
2483 union gw_addr
*gw_ip
)
2485 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2486 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2489 if (afi
!= AFI_L2VPN
)
2492 memset(&temp
, 0, 16);
2493 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2494 info_gw_ip
= (union gw_addr
*)&temp
;
2495 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2498 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2499 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2502 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2504 info_gw_ip_remote
= gw_ip
;
2505 if (eth_s_id
== NULL
)
2506 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2508 info_eth_s_id_remote
= eth_s_id
;
2509 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2511 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2512 sizeof(struct eth_segment_id
));
2515 /* Check if received nexthop is valid or not. */
2516 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2521 /* Only validated for unicast and multicast currently. */
2522 /* Also valid for EVPN where the nexthop is an IP address. */
2523 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2526 /* If NEXT_HOP is present, validate it. */
2527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2528 if (attr
->nexthop
.s_addr
== 0
2529 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2530 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2534 /* If MP_NEXTHOP is present, validate it. */
2535 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2536 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2537 * it is not an IPv6 link-local address.
2539 if (attr
->mp_nexthop_len
) {
2540 switch (attr
->mp_nexthop_len
) {
2541 case BGP_ATTR_NHLEN_IPV4
:
2542 case BGP_ATTR_NHLEN_VPNV4
:
2543 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2544 || IPV4_CLASS_DE(ntohl(
2545 attr
->mp_nexthop_global_in
.s_addr
))
2546 || bgp_nexthop_self(bgp
,
2547 attr
->mp_nexthop_global_in
));
2550 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2551 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2552 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2553 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2554 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2555 || IN6_IS_ADDR_MULTICAST(
2556 &attr
->mp_nexthop_global
));
2568 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2569 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2570 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2571 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2574 int aspath_loop_count
= 0;
2575 struct bgp_node
*rn
;
2577 struct attr new_attr
;
2578 struct attr
*attr_new
;
2579 struct bgp_info
*ri
;
2580 struct bgp_info
*new;
2582 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2585 int do_loop_check
= 1;
2586 int has_valid_label
= 0;
2588 int vnc_implicit_withdraw
= 0;
2592 memset(&new_attr
, 0, sizeof(struct attr
));
2593 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2594 new_attr
.label
= MPLS_INVALID_LABEL
;
2597 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2598 has_valid_label
= bgp_is_valid_label(label
);
2600 if (has_valid_label
)
2601 sprintf(label_buf
, "label %u", label_pton(label
));
2603 /* When peer's soft reconfiguration enabled. Record input packet in
2606 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2607 && peer
!= bgp
->peer_self
)
2608 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2610 /* Check previously received route. */
2611 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2612 if (ri
->peer
== peer
&& ri
->type
== type
2613 && ri
->sub_type
== sub_type
2614 && ri
->addpath_rx_id
== addpath_id
)
2617 /* AS path local-as loop check. */
2618 if (peer
->change_local_as
) {
2619 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2620 aspath_loop_count
= 1;
2622 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2623 > aspath_loop_count
) {
2624 reason
= "as-path contains our own AS;";
2629 /* If the peer is configured for "allowas-in origin" and the last ASN in
2631 * as-path is our ASN then we do not need to call aspath_loop_check
2633 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2634 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2637 /* AS path loop check. */
2638 if (do_loop_check
) {
2639 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2640 > peer
->allowas_in
[afi
][safi
]
2641 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2642 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2643 > peer
->allowas_in
[afi
][safi
])) {
2644 reason
= "as-path contains our own AS;";
2649 /* Route reflector originator ID check. */
2650 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2651 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2652 reason
= "originator is us;";
2656 /* Route reflector cluster ID check. */
2657 if (bgp_cluster_filter(peer
, attr
)) {
2658 reason
= "reflected from the same cluster;";
2662 /* Apply incoming filter. */
2663 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2668 bgp_attr_dup(&new_attr
, attr
);
2670 /* Apply incoming route-map.
2671 * NB: new_attr may now contain newly allocated values from route-map
2673 * commands, so we need bgp_attr_flush in the error paths, until we
2675 * the attr (which takes over the memory references) */
2676 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2678 reason
= "route-map;";
2679 bgp_attr_flush(&new_attr
);
2683 /* next hop check. */
2684 if (bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2685 reason
= "martian or self next-hop;";
2686 bgp_attr_flush(&new_attr
);
2690 attr_new
= bgp_attr_intern(&new_attr
);
2692 /* If the update is implicit withdraw. */
2694 ri
->uptime
= bgp_clock();
2695 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2697 /* Same attribute comes in. */
2698 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2699 && attrhash_cmp(ri
->attr
, attr_new
)
2700 && (!has_valid_label
2701 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2704 && (overlay_index_equal(
2705 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2706 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2707 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2708 BGP_CONFIG_DAMPENING
)
2709 && peer
->sort
== BGP_PEER_EBGP
2710 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2711 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2712 bgp_debug_rdpfxpath2str(
2713 afi
, safi
, prd
, p
, label
,
2714 addpath_id
? 1 : 0, addpath_id
,
2715 pfx_buf
, sizeof(pfx_buf
));
2716 zlog_debug("%s rcvd %s", peer
->host
,
2720 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2721 != BGP_DAMP_SUPPRESSED
) {
2722 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2724 bgp_process(bgp
, rn
, afi
, safi
);
2726 } else /* Duplicate - odd */
2728 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2729 if (!peer
->rcvd_attr_printed
) {
2731 "%s rcvd UPDATE w/ attr: %s",
2733 peer
->rcvd_attr_str
);
2734 peer
->rcvd_attr_printed
= 1;
2737 bgp_debug_rdpfxpath2str(
2738 afi
, safi
, prd
, p
, label
,
2739 addpath_id
? 1 : 0, addpath_id
,
2740 pfx_buf
, sizeof(pfx_buf
));
2742 "%s rcvd %s...duplicate ignored",
2743 peer
->host
, pfx_buf
);
2746 /* graceful restart STALE flag unset. */
2747 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2748 bgp_info_unset_flag(rn
, ri
,
2750 bgp_process(bgp
, rn
, afi
, safi
);
2754 bgp_unlock_node(rn
);
2755 bgp_attr_unintern(&attr_new
);
2760 /* Withdraw/Announce before we fully processed the withdraw */
2761 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2762 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2763 bgp_debug_rdpfxpath2str(
2764 afi
, safi
, prd
, p
, label
,
2765 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2768 "%s rcvd %s, flapped quicker than processing",
2769 peer
->host
, pfx_buf
);
2772 bgp_info_restore(rn
, ri
);
2775 /* Received Logging. */
2776 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2777 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2778 addpath_id
? 1 : 0, addpath_id
,
2779 pfx_buf
, sizeof(pfx_buf
));
2780 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2783 /* graceful restart STALE flag unset. */
2784 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2785 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2787 /* The attribute is changed. */
2788 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2790 /* implicit withdraw, decrement aggregate and pcount here.
2791 * only if update is accepted, they'll increment below.
2793 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2795 /* Update bgp route dampening information. */
2796 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2797 && peer
->sort
== BGP_PEER_EBGP
) {
2798 /* This is implicit withdraw so we should update
2801 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2802 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2805 if (safi
== SAFI_MPLS_VPN
) {
2806 struct bgp_node
*prn
= NULL
;
2807 struct bgp_table
*table
= NULL
;
2809 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2810 (struct prefix
*)prd
);
2812 table
= (struct bgp_table
*)(prn
->info
);
2814 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2815 bgp
, prd
, table
, p
, ri
);
2817 bgp_unlock_node(prn
);
2819 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2820 && (safi
== SAFI_UNICAST
)) {
2821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2823 * Implicit withdraw case.
2825 ++vnc_implicit_withdraw
;
2826 vnc_import_bgp_del_route(bgp
, p
, ri
);
2827 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2832 /* Special handling for EVPN update of an existing route. If the
2833 * extended community attribute has changed, we need to
2835 * the route using its existing extended community. It will be
2836 * subsequently processed for import with the new extended
2839 if (safi
== SAFI_EVPN
&& !same_attr
) {
2841 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2843 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2846 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2847 attr_new
->ecommunity
);
2849 if (bgp_debug_update(peer
, p
, NULL
, 1))
2851 "Change in EXT-COMM, existing %s new %s",
2853 ri
->attr
->ecommunity
),
2855 attr_new
->ecommunity
));
2856 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2862 /* Update to new attribute. */
2863 bgp_attr_unintern(&ri
->attr
);
2864 ri
->attr
= attr_new
;
2866 /* Update MPLS label */
2867 if (has_valid_label
) {
2868 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2870 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2874 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2875 && (safi
== SAFI_UNICAST
)) {
2876 if (vnc_implicit_withdraw
) {
2878 * Add back the route with its new attributes
2880 * The route is still selected, until the route
2882 * queued by bgp_process actually runs. We have
2884 * update to the VNC side immediately to avoid
2886 * configuration changes (e.g., route-map
2888 * trigger re-importation of the entire RIB.
2890 vnc_import_bgp_add_route(bgp
, p
, ri
);
2891 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
2895 /* Update Overlay Index */
2896 if (afi
== AFI_L2VPN
) {
2897 overlay_index_update(
2898 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2899 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
2902 /* Update bgp route dampening information. */
2903 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2904 && peer
->sort
== BGP_PEER_EBGP
) {
2905 /* Now we do normal update dampening. */
2906 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
2907 if (ret
== BGP_DAMP_SUPPRESSED
) {
2908 bgp_unlock_node(rn
);
2913 /* Nexthop reachability check - for unicast and
2914 * labeled-unicast.. */
2915 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2916 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
2917 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
2918 && !CHECK_FLAG(peer
->flags
,
2919 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
2921 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
2926 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
2928 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2930 if (BGP_DEBUG(nht
, NHT
)) {
2931 char buf1
[INET6_ADDRSTRLEN
];
2933 (const void *)&attr_new
2935 buf1
, INET6_ADDRSTRLEN
);
2936 zlog_debug("%s(%s): NH unresolved",
2937 __FUNCTION__
, buf1
);
2939 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
2942 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2945 if (safi
== SAFI_MPLS_VPN
) {
2946 struct bgp_node
*prn
= NULL
;
2947 struct bgp_table
*table
= NULL
;
2949 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2950 (struct prefix
*)prd
);
2952 table
= (struct bgp_table
*)(prn
->info
);
2954 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
2955 bgp
, prd
, table
, p
, ri
);
2957 bgp_unlock_node(prn
);
2961 /* If this is an EVPN route and some attribute has changed,
2963 * route for import. If the extended community has changed, we
2965 * have done the un-import earlier and the import would result
2967 * route getting injected into appropriate L2 VNIs. If it is
2969 * some other attribute change, the import will result in
2971 * the attributes for the route in the VNI(s).
2973 if (safi
== SAFI_EVPN
&& !same_attr
)
2974 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
2976 /* Process change. */
2977 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
2979 bgp_process(bgp
, rn
, afi
, safi
);
2980 bgp_unlock_node(rn
);
2983 if (SAFI_MPLS_VPN
== safi
) {
2984 mpls_label_t label_decoded
= decode_label(label
);
2986 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2987 type
, sub_type
, &label_decoded
);
2989 if (SAFI_ENCAP
== safi
) {
2990 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2991 type
, sub_type
, NULL
);
2996 } // End of implicit withdraw
2998 /* Received Logging. */
2999 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3000 if (!peer
->rcvd_attr_printed
) {
3001 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3002 peer
->rcvd_attr_str
);
3003 peer
->rcvd_attr_printed
= 1;
3006 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3007 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3009 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3012 /* Make new BGP info. */
3013 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3015 /* Update MPLS label */
3016 if (has_valid_label
) {
3017 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3019 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3022 /* Update Overlay Index */
3023 if (afi
== AFI_L2VPN
) {
3024 overlay_index_update(new->attr
,
3025 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3026 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3028 /* Nexthop reachability check. */
3029 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3030 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3031 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3032 && !CHECK_FLAG(peer
->flags
,
3033 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3034 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3039 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
))
3040 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3042 if (BGP_DEBUG(nht
, NHT
)) {
3043 char buf1
[INET6_ADDRSTRLEN
];
3045 (const void *)&attr_new
->nexthop
,
3046 buf1
, INET6_ADDRSTRLEN
);
3047 zlog_debug("%s(%s): NH unresolved",
3048 __FUNCTION__
, buf1
);
3050 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3053 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3056 new->addpath_rx_id
= addpath_id
;
3058 /* Increment prefix */
3059 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3061 /* Register new BGP information. */
3062 bgp_info_add(rn
, new);
3064 /* route_node_get lock */
3065 bgp_unlock_node(rn
);
3068 if (safi
== SAFI_MPLS_VPN
) {
3069 struct bgp_node
*prn
= NULL
;
3070 struct bgp_table
*table
= NULL
;
3072 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3074 table
= (struct bgp_table
*)(prn
->info
);
3076 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3077 bgp
, prd
, table
, p
, new);
3079 bgp_unlock_node(prn
);
3083 /* If maximum prefix count is configured and current prefix
3085 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3088 /* If this is an EVPN route, process for import. */
3089 if (safi
== SAFI_EVPN
)
3090 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3092 /* Process change. */
3093 bgp_process(bgp
, rn
, afi
, safi
);
3096 if (SAFI_MPLS_VPN
== safi
) {
3097 mpls_label_t label_decoded
= decode_label(label
);
3099 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3100 sub_type
, &label_decoded
);
3102 if (SAFI_ENCAP
== safi
) {
3103 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3110 /* This BGP update is filtered. Log the reason then update BGP
3113 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3114 if (!peer
->rcvd_attr_printed
) {
3115 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3116 peer
->rcvd_attr_str
);
3117 peer
->rcvd_attr_printed
= 1;
3120 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3121 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3123 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3124 peer
->host
, pfx_buf
, reason
);
3128 /* If this is an EVPN route, un-import it as it is now filtered.
3130 if (safi
== SAFI_EVPN
)
3131 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3133 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3136 bgp_unlock_node(rn
);
3140 * Filtered update is treated as an implicit withdrawal (see
3142 * a few lines above)
3144 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3145 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3153 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3154 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3155 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3156 struct bgp_route_evpn
*evpn
)
3159 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3160 struct bgp_node
*rn
;
3161 struct bgp_info
*ri
;
3164 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3165 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3173 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3175 /* If peer is soft reconfiguration enabled. Record input packet for
3176 * further calculation.
3178 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3179 * routes that are filtered. This tanks out Quagga RS pretty badly due
3181 * the iteration over all RS clients.
3182 * Since we need to remove the entry from adj_in anyway, do that first
3184 * if there was no entry, we don't need to do anything more.
3186 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3187 && peer
!= bgp
->peer_self
)
3188 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3189 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3190 bgp_debug_rdpfxpath2str(
3191 afi
, safi
, prd
, p
, label
,
3192 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3195 "%s withdrawing route %s not in adj-in",
3196 peer
->host
, pfx_buf
);
3198 bgp_unlock_node(rn
);
3202 /* Lookup withdrawn route. */
3203 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3204 if (ri
->peer
== peer
&& ri
->type
== type
3205 && ri
->sub_type
== sub_type
3206 && ri
->addpath_rx_id
== addpath_id
)
3210 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3211 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3212 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3214 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3218 /* Withdraw specified route from routing table. */
3219 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3220 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3221 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3222 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3223 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3225 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3228 /* Unlock bgp_node_get() lock. */
3229 bgp_unlock_node(rn
);
3234 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3237 struct update_subgroup
*subgrp
;
3238 subgrp
= peer_subgroup(peer
, afi
, safi
);
3239 subgroup_default_originate(subgrp
, withdraw
);
3244 * bgp_stop_announce_route_timer
3246 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3248 if (!paf
->t_announce_route
)
3251 THREAD_TIMER_OFF(paf
->t_announce_route
);
3255 * bgp_announce_route_timer_expired
3257 * Callback that is invoked when the route announcement timer for a
3260 static int bgp_announce_route_timer_expired(struct thread
*t
)
3262 struct peer_af
*paf
;
3265 paf
= THREAD_ARG(t
);
3268 if (peer
->status
!= Established
)
3271 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3274 peer_af_announce_route(paf
, 1);
3279 * bgp_announce_route
3281 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3283 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3285 struct peer_af
*paf
;
3286 struct update_subgroup
*subgrp
;
3288 paf
= peer_af_find(peer
, afi
, safi
);
3291 subgrp
= PAF_SUBGRP(paf
);
3294 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3295 * or a refresh has already been triggered.
3297 if (!subgrp
|| paf
->t_announce_route
)
3301 * Start a timer to stagger/delay the announce. This serves
3302 * two purposes - announcement can potentially be combined for
3303 * multiple peers and the announcement doesn't happen in the
3306 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3307 (subgrp
->peer_count
== 1)
3308 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3309 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3310 &paf
->t_announce_route
);
3314 * Announce routes from all AF tables to a peer.
3316 * This should ONLY be called when there is a need to refresh the
3317 * routes to the peer based on a policy change for this peer alone
3318 * or a route refresh request received from the peer.
3319 * The operation will result in splitting the peer from its existing
3320 * subgroups and putting it in new subgroups.
3322 void bgp_announce_route_all(struct peer
*peer
)
3327 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3328 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3329 bgp_announce_route(peer
, afi
, safi
);
3332 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3333 struct bgp_table
*table
,
3334 struct prefix_rd
*prd
)
3337 struct bgp_node
*rn
;
3338 struct bgp_adj_in
*ain
;
3341 table
= peer
->bgp
->rib
[afi
][safi
];
3343 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3344 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3345 if (ain
->peer
== peer
) {
3346 struct bgp_info
*ri
= rn
->info
;
3347 mpls_label_t label
=
3348 (ri
&& ri
->extra
) ? ri
->extra
->label
3349 : MPLS_INVALID_LABEL
;
3352 peer
, &rn
->p
, ain
->addpath_rx_id
,
3353 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3354 BGP_ROUTE_NORMAL
, prd
, &label
, 1, NULL
);
3357 bgp_unlock_node(rn
);
3364 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3366 struct bgp_node
*rn
;
3367 struct bgp_table
*table
;
3369 if (peer
->status
!= Established
)
3372 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3373 && (safi
!= SAFI_EVPN
))
3374 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3376 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3377 rn
= bgp_route_next(rn
))
3378 if ((table
= rn
->info
) != NULL
) {
3379 struct prefix_rd prd
;
3380 prd
.family
= AF_UNSPEC
;
3382 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3384 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3390 struct bgp_clear_node_queue
{
3391 struct bgp_node
*rn
;
3394 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3396 struct bgp_clear_node_queue
*cnq
= data
;
3397 struct bgp_node
*rn
= cnq
->rn
;
3398 struct peer
*peer
= wq
->spec
.data
;
3399 struct bgp_info
*ri
;
3400 afi_t afi
= bgp_node_table(rn
)->afi
;
3401 safi_t safi
= bgp_node_table(rn
)->safi
;
3405 /* It is possible that we have multiple paths for a prefix from a peer
3406 * if that peer is using AddPath.
3408 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3409 if (ri
->peer
== peer
) {
3410 /* graceful restart STALE flag set. */
3411 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3412 && peer
->nsf
[afi
][safi
]
3413 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3414 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3415 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3417 /* If this is an EVPN route, process for
3419 if (safi
== SAFI_EVPN
)
3420 bgp_evpn_unimport_route(peer
->bgp
, afi
,
3423 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3429 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3431 struct bgp_clear_node_queue
*cnq
= data
;
3432 struct bgp_node
*rn
= cnq
->rn
;
3433 struct bgp_table
*table
= bgp_node_table(rn
);
3435 bgp_unlock_node(rn
);
3436 bgp_table_unlock(table
);
3437 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3440 static void bgp_clear_node_complete(struct work_queue
*wq
)
3442 struct peer
*peer
= wq
->spec
.data
;
3444 /* Tickle FSM to start moving again */
3445 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3447 peer_unlock(peer
); /* bgp_clear_route */
3450 static void bgp_clear_node_queue_init(struct peer
*peer
)
3452 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3454 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3455 #undef CLEAR_QUEUE_NAME_LEN
3457 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3459 zlog_err("%s: Failed to allocate work queue", __func__
);
3462 peer
->clear_node_queue
->spec
.hold
= 10;
3463 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3464 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3465 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3466 peer
->clear_node_queue
->spec
.max_retries
= 0;
3468 /* we only 'lock' this peer reference when the queue is actually active
3470 peer
->clear_node_queue
->spec
.data
= peer
;
3473 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3474 struct bgp_table
*table
)
3476 struct bgp_node
*rn
;
3477 int force
= bm
->process_main_queue
? 0 : 1;
3480 table
= peer
->bgp
->rib
[afi
][safi
];
3482 /* If still no table => afi/safi isn't configured at all or smth. */
3486 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3487 struct bgp_info
*ri
, *next
;
3488 struct bgp_adj_in
*ain
;
3489 struct bgp_adj_in
*ain_next
;
3491 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3492 * queued for every clearing peer, regardless of whether it is
3493 * relevant to the peer at hand.
3495 * Overview: There are 3 different indices which need to be
3496 * scrubbed, potentially, when a peer is removed:
3498 * 1 peer's routes visible via the RIB (ie accepted routes)
3499 * 2 peer's routes visible by the (optional) peer's adj-in index
3500 * 3 other routes visible by the peer's adj-out index
3502 * 3 there is no hurry in scrubbing, once the struct peer is
3503 * removed from bgp->peer, we could just GC such deleted peer's
3504 * adj-outs at our leisure.
3506 * 1 and 2 must be 'scrubbed' in some way, at least made
3507 * invisible via RIB index before peer session is allowed to be
3508 * brought back up. So one needs to know when such a 'search' is
3513 * - there'd be a single global queue or a single RIB walker
3514 * - rather than tracking which route_nodes still need to be
3515 * examined on a peer basis, we'd track which peers still
3518 * Given that our per-peer prefix-counts now should be reliable,
3519 * this may actually be achievable. It doesn't seem to be a huge
3520 * problem at this time,
3522 * It is possible that we have multiple paths for a prefix from
3524 * if that peer is using AddPath.
3528 ain_next
= ain
->next
;
3530 if (ain
->peer
== peer
) {
3531 bgp_adj_in_remove(rn
, ain
);
3532 bgp_unlock_node(rn
);
3538 for (ri
= rn
->info
; ri
; ri
= next
) {
3540 if (ri
->peer
!= peer
)
3544 bgp_info_reap(rn
, ri
);
3546 struct bgp_clear_node_queue
*cnq
;
3548 /* both unlocked in bgp_clear_node_queue_del */
3549 bgp_table_lock(bgp_node_table(rn
));
3552 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3553 sizeof(struct bgp_clear_node_queue
));
3555 work_queue_add(peer
->clear_node_queue
, cnq
);
3563 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3565 struct bgp_node
*rn
;
3566 struct bgp_table
*table
;
3568 if (peer
->clear_node_queue
== NULL
)
3569 bgp_clear_node_queue_init(peer
);
3571 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3572 * Idle until it receives a Clearing_Completed event. This protects
3573 * against peers which flap faster than we can we clear, which could
3576 * a) race with routes from the new session being installed before
3577 * clear_route_node visits the node (to delete the route of that
3579 * b) resource exhaustion, clear_route_node likely leads to an entry
3580 * on the process_main queue. Fast-flapping could cause that queue
3584 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3585 * the unlock will happen upon work-queue completion; other wise, the
3586 * unlock happens at the end of this function.
3588 if (!peer
->clear_node_queue
->thread
)
3591 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3592 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3594 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3595 rn
= bgp_route_next(rn
))
3596 if ((table
= rn
->info
) != NULL
)
3597 bgp_clear_route_table(peer
, afi
, safi
, table
);
3599 /* unlock if no nodes got added to the clear-node-queue. */
3600 if (!peer
->clear_node_queue
->thread
)
3604 void bgp_clear_route_all(struct peer
*peer
)
3609 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3610 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3611 bgp_clear_route(peer
, afi
, safi
);
3614 rfapiProcessPeerDown(peer
);
3618 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3620 struct bgp_table
*table
;
3621 struct bgp_node
*rn
;
3622 struct bgp_adj_in
*ain
;
3623 struct bgp_adj_in
*ain_next
;
3625 table
= peer
->bgp
->rib
[afi
][safi
];
3627 /* It is possible that we have multiple paths for a prefix from a peer
3628 * if that peer is using AddPath.
3630 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3634 ain_next
= ain
->next
;
3636 if (ain
->peer
== peer
) {
3637 bgp_adj_in_remove(rn
, ain
);
3638 bgp_unlock_node(rn
);
3646 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3648 struct bgp_node
*rn
;
3649 struct bgp_info
*ri
;
3650 struct bgp_table
*table
;
3652 if (safi
== SAFI_MPLS_VPN
) {
3653 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3654 rn
= bgp_route_next(rn
)) {
3655 struct bgp_node
*rm
;
3656 struct bgp_info
*ri
;
3658 /* look for neighbor in tables */
3659 if ((table
= rn
->info
) != NULL
) {
3660 for (rm
= bgp_table_top(table
); rm
;
3661 rm
= bgp_route_next(rm
))
3662 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
3663 if (ri
->peer
== peer
) {
3677 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3678 rn
= bgp_route_next(rn
))
3679 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3680 if (ri
->peer
== peer
) {
3681 if (CHECK_FLAG(ri
->flags
,
3683 bgp_rib_remove(rn
, ri
, peer
,
3690 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3692 struct bgp_node
*rn
;
3693 struct bgp_info
*ri
;
3694 struct bgp_info
*next
;
3696 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3697 for (ri
= rn
->info
; ri
; ri
= next
) {
3699 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3700 && ri
->type
== ZEBRA_ROUTE_BGP
3701 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3702 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3703 if (bgp_fibupd_safi(safi
))
3704 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3705 bgp_info_reap(rn
, ri
);
3710 /* Delete all kernel routes. */
3711 void bgp_cleanup_routes(struct bgp
*bgp
)
3714 struct bgp_node
*rn
;
3716 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3717 if (afi
== AFI_L2VPN
)
3719 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3721 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3723 if (afi
!= AFI_L2VPN
) {
3725 safi
= SAFI_MPLS_VPN
;
3726 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3727 rn
= bgp_route_next(rn
)) {
3730 (struct bgp_table
*)(rn
->info
),
3732 bgp_table_finish((struct bgp_table
**)&(
3735 bgp_unlock_node(rn
);
3739 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3740 rn
= bgp_route_next(rn
)) {
3743 (struct bgp_table
*)(rn
->info
),
3745 bgp_table_finish((struct bgp_table
**)&(
3748 bgp_unlock_node(rn
);
3753 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3754 rn
= bgp_route_next(rn
)) {
3756 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3758 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3760 bgp_unlock_node(rn
);
3765 void bgp_reset(void)
3768 bgp_zclient_reset();
3769 access_list_reset();
3770 prefix_list_reset();
3773 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3775 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3776 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3777 PEER_CAP_ADDPATH_AF_TX_RCV
));
3780 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3782 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3783 struct bgp_nlri
*packet
)
3792 int addpath_encoded
;
3793 u_int32_t addpath_id
;
3795 /* Check peer status. */
3796 if (peer
->status
!= Established
)
3800 lim
= pnt
+ packet
->length
;
3802 safi
= packet
->safi
;
3804 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3806 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3807 syntactic validity. If the field is syntactically incorrect,
3808 then the Error Subcode is set to Invalid Network Field. */
3809 for (; pnt
< lim
; pnt
+= psize
) {
3810 /* Clear prefix structure. */
3811 memset(&p
, 0, sizeof(struct prefix
));
3813 if (addpath_encoded
) {
3815 /* When packet overflow occurs return immediately. */
3816 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3819 addpath_id
= ntohl(*((uint32_t *)pnt
));
3820 pnt
+= BGP_ADDPATH_ID_LEN
;
3823 /* Fetch prefix length. */
3824 p
.prefixlen
= *pnt
++;
3825 /* afi/safi validity already verified by caller,
3826 * bgp_update_receive */
3827 p
.family
= afi2family(afi
);
3829 /* Prefix length check. */
3830 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3832 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3833 peer
->host
, p
.prefixlen
, packet
->afi
);
3837 /* Packet size overflow check. */
3838 psize
= PSIZE(p
.prefixlen
);
3840 /* When packet overflow occur return immediately. */
3841 if (pnt
+ psize
> lim
) {
3843 "%s [Error] Update packet error (prefix length %d overflows packet)",
3844 peer
->host
, p
.prefixlen
);
3848 /* Defensive coding, double-check the psize fits in a struct
3850 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3852 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3853 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3857 /* Fetch prefix from NLRI packet. */
3858 memcpy(&p
.u
.prefix
, pnt
, psize
);
3860 /* Check address. */
3861 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3862 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3863 /* From RFC4271 Section 6.3:
3865 * If a prefix in the NLRI field is semantically
3867 * (e.g., an unexpected multicast IP address),
3869 * be logged locally, and the prefix SHOULD be
3873 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3874 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3879 /* Check address. */
3880 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3881 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3885 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3887 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3892 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
3896 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
3898 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3905 /* Normal process. */
3907 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
3908 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
3909 NULL
, NULL
, 0, NULL
);
3911 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
3912 safi
, ZEBRA_ROUTE_BGP
,
3913 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
3915 /* Address family configuration mismatch or maximum-prefix count
3921 /* Packet length consistency check. */
3924 "%s [Error] Update packet error (prefix length mismatch with total length)",
3932 static struct bgp_static
*bgp_static_new(void)
3934 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
3937 static void bgp_static_free(struct bgp_static
*bgp_static
)
3939 if (bgp_static
->rmap
.name
)
3940 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
3941 if (bgp_static
->eth_s_id
)
3942 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
3943 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
3946 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
3947 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
3949 struct bgp_node
*rn
;
3950 struct bgp_info
*ri
;
3951 struct bgp_info
*new;
3952 struct bgp_info info
;
3954 struct attr
*attr_new
;
3957 int vnc_implicit_withdraw
= 0;
3964 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
3966 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
3968 attr
.nexthop
= bgp_static
->igpnexthop
;
3969 attr
.med
= bgp_static
->igpmetric
;
3970 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
3972 if (bgp_static
->atomic
)
3973 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
3975 /* Store label index, if required. */
3976 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3977 attr
.label_index
= bgp_static
->label_index
;
3978 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3981 /* Apply route-map. */
3982 if (bgp_static
->rmap
.name
) {
3983 struct attr attr_tmp
= attr
;
3984 info
.peer
= bgp
->peer_self
;
3985 info
.attr
= &attr_tmp
;
3987 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
3989 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
3991 bgp
->peer_self
->rmap_type
= 0;
3993 if (ret
== RMAP_DENYMATCH
) {
3994 /* Free uninterned attribute. */
3995 bgp_attr_flush(&attr_tmp
);
3997 /* Unintern original. */
3998 aspath_unintern(&attr
.aspath
);
3999 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4002 attr_new
= bgp_attr_intern(&attr_tmp
);
4004 attr_new
= bgp_attr_intern(&attr
);
4006 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4007 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4008 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4012 if (attrhash_cmp(ri
->attr
, attr_new
)
4013 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4014 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4015 bgp_unlock_node(rn
);
4016 bgp_attr_unintern(&attr_new
);
4017 aspath_unintern(&attr
.aspath
);
4020 /* The attribute is changed. */
4021 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4023 /* Rewrite BGP route information. */
4024 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4025 bgp_info_restore(rn
, ri
);
4027 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4029 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4030 && (safi
== SAFI_UNICAST
)) {
4031 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4033 * Implicit withdraw case.
4034 * We have to do this before ri is
4037 ++vnc_implicit_withdraw
;
4038 vnc_import_bgp_del_route(bgp
, p
, ri
);
4039 vnc_import_bgp_exterior_del_route(
4044 bgp_attr_unintern(&ri
->attr
);
4045 ri
->attr
= attr_new
;
4046 ri
->uptime
= bgp_clock();
4048 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4049 && (safi
== SAFI_UNICAST
)) {
4050 if (vnc_implicit_withdraw
) {
4051 vnc_import_bgp_add_route(bgp
, p
, ri
);
4052 vnc_import_bgp_exterior_add_route(
4058 /* Nexthop reachability check. */
4059 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4060 && (safi
== SAFI_UNICAST
4061 || safi
== SAFI_LABELED_UNICAST
)) {
4062 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4064 bgp_info_set_flag(rn
, ri
,
4067 if (BGP_DEBUG(nht
, NHT
)) {
4068 char buf1
[INET6_ADDRSTRLEN
];
4069 inet_ntop(p
->family
,
4073 "%s(%s): Route not in table, not advertising",
4074 __FUNCTION__
, buf1
);
4076 bgp_info_unset_flag(rn
, ri
,
4080 /* Delete the NHT structure if any, if we're
4082 * enabling/disabling import check. We
4083 * deregister the route
4084 * from NHT to avoid overloading NHT and the
4085 * process interaction
4087 bgp_unlink_nexthop(ri
);
4088 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4090 /* Process change. */
4091 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4092 bgp_process(bgp
, rn
, afi
, safi
);
4093 bgp_unlock_node(rn
);
4094 aspath_unintern(&attr
.aspath
);
4099 /* Make new BGP info. */
4100 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4102 /* Nexthop reachability check. */
4103 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4104 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4105 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4106 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4108 if (BGP_DEBUG(nht
, NHT
)) {
4109 char buf1
[INET6_ADDRSTRLEN
];
4110 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4113 "%s(%s): Route not in table, not advertising",
4114 __FUNCTION__
, buf1
);
4116 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4119 /* Delete the NHT structure if any, if we're toggling between
4120 * enabling/disabling import check. We deregister the route
4121 * from NHT to avoid overloading NHT and the process interaction
4123 bgp_unlink_nexthop(new);
4125 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4128 /* Aggregate address increment. */
4129 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4131 /* Register new BGP information. */
4132 bgp_info_add(rn
, new);
4134 /* route_node_get lock */
4135 bgp_unlock_node(rn
);
4137 /* Process change. */
4138 bgp_process(bgp
, rn
, afi
, safi
);
4140 /* Unintern original. */
4141 aspath_unintern(&attr
.aspath
);
4144 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4147 struct bgp_node
*rn
;
4148 struct bgp_info
*ri
;
4150 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4152 /* Check selected route and self inserted route. */
4153 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4154 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4155 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4158 /* Withdraw static BGP route from routing table. */
4160 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4161 bgp_unlink_nexthop(ri
);
4162 bgp_info_delete(rn
, ri
);
4163 bgp_process(bgp
, rn
, afi
, safi
);
4166 /* Unlock bgp_node_lookup. */
4167 bgp_unlock_node(rn
);
4171 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4173 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4174 afi_t afi
, safi_t safi
,
4175 struct prefix_rd
*prd
)
4177 struct bgp_node
*rn
;
4178 struct bgp_info
*ri
;
4180 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4182 /* Check selected route and self inserted route. */
4183 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4184 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4185 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4188 /* Withdraw static BGP route from routing table. */
4191 rfapiProcessWithdraw(
4192 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4193 1); /* Kill, since it is an administrative change */
4195 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4196 bgp_info_delete(rn
, ri
);
4197 bgp_process(bgp
, rn
, afi
, safi
);
4200 /* Unlock bgp_node_lookup. */
4201 bgp_unlock_node(rn
);
4204 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4205 struct bgp_static
*bgp_static
, afi_t afi
,
4208 struct bgp_node
*rn
;
4209 struct bgp_info
*new;
4210 struct attr
*attr_new
;
4211 struct attr attr
= {0};
4212 struct bgp_info
*ri
;
4214 mpls_label_t label
= 0;
4220 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4223 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4225 attr
.nexthop
= bgp_static
->igpnexthop
;
4226 attr
.med
= bgp_static
->igpmetric
;
4227 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4229 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4230 || (safi
== SAFI_ENCAP
)) {
4231 if (afi
== AFI_IP
) {
4232 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4233 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4236 if (afi
== AFI_L2VPN
) {
4237 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4239 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4240 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4241 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4242 sizeof(struct in6_addr
));
4243 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4244 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4245 struct bgp_encap_type_vxlan bet
;
4246 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4247 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4248 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4250 if (bgp_static
->router_mac
) {
4251 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4254 /* Apply route-map. */
4255 if (bgp_static
->rmap
.name
) {
4256 struct attr attr_tmp
= attr
;
4257 struct bgp_info info
;
4260 info
.peer
= bgp
->peer_self
;
4261 info
.attr
= &attr_tmp
;
4263 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4265 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4267 bgp
->peer_self
->rmap_type
= 0;
4269 if (ret
== RMAP_DENYMATCH
) {
4270 /* Free uninterned attribute. */
4271 bgp_attr_flush(&attr_tmp
);
4273 /* Unintern original. */
4274 aspath_unintern(&attr
.aspath
);
4275 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4280 attr_new
= bgp_attr_intern(&attr_tmp
);
4282 attr_new
= bgp_attr_intern(&attr
);
4285 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4286 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4287 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4292 memset(&add
, 0, sizeof(union gw_addr
));
4293 if (attrhash_cmp(ri
->attr
, attr_new
)
4294 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4295 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4296 bgp_unlock_node(rn
);
4297 bgp_attr_unintern(&attr_new
);
4298 aspath_unintern(&attr
.aspath
);
4301 /* The attribute is changed. */
4302 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4304 /* Rewrite BGP route information. */
4305 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4306 bgp_info_restore(rn
, ri
);
4308 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4309 bgp_attr_unintern(&ri
->attr
);
4310 ri
->attr
= attr_new
;
4311 ri
->uptime
= bgp_clock();
4314 label
= decode_label(&ri
->extra
->label
);
4317 /* Process change. */
4318 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4319 bgp_process(bgp
, rn
, afi
, safi
);
4321 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4322 ri
->attr
, afi
, safi
, ri
->type
,
4323 ri
->sub_type
, &label
);
4325 bgp_unlock_node(rn
);
4326 aspath_unintern(&attr
.aspath
);
4332 /* Make new BGP info. */
4333 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4335 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4336 new->extra
= bgp_info_extra_new();
4337 new->extra
->label
= bgp_static
->label
;
4339 label
= decode_label(&bgp_static
->label
);
4342 /* Aggregate address increment. */
4343 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4345 /* Register new BGP information. */
4346 bgp_info_add(rn
, new);
4347 /* route_node_get lock */
4348 bgp_unlock_node(rn
);
4350 /* Process change. */
4351 bgp_process(bgp
, rn
, afi
, safi
);
4354 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4355 safi
, new->type
, new->sub_type
, &label
);
4358 /* Unintern original. */
4359 aspath_unintern(&attr
.aspath
);
4362 /* Configure static BGP network. When user don't run zebra, static
4363 route should be installed as valid. */
4364 static int bgp_static_set(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4365 safi_t safi
, const char *rmap
, int backdoor
,
4366 u_int32_t label_index
)
4368 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4371 struct bgp_static
*bgp_static
;
4372 struct bgp_node
*rn
;
4373 u_char need_update
= 0;
4375 /* Convert IP prefix string to struct prefix. */
4376 ret
= str2prefix(ip_str
, &p
);
4378 vty_out(vty
, "%% Malformed prefix\n");
4379 return CMD_WARNING_CONFIG_FAILED
;
4381 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4382 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4383 return CMD_WARNING_CONFIG_FAILED
;
4388 /* Set BGP static route configuration. */
4389 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4392 /* Configuration change. */
4393 bgp_static
= rn
->info
;
4395 /* Label index cannot be changed. */
4396 if (bgp_static
->label_index
!= label_index
) {
4397 vty_out(vty
, "%% Label index cannot be changed\n");
4398 return CMD_WARNING_CONFIG_FAILED
;
4401 /* Check previous routes are installed into BGP. */
4402 if (bgp_static
->valid
&& bgp_static
->backdoor
!= backdoor
)
4405 bgp_static
->backdoor
= backdoor
;
4408 if (bgp_static
->rmap
.name
)
4409 XFREE(MTYPE_ROUTE_MAP_NAME
,
4410 bgp_static
->rmap
.name
);
4411 bgp_static
->rmap
.name
=
4412 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4413 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4415 if (bgp_static
->rmap
.name
)
4416 XFREE(MTYPE_ROUTE_MAP_NAME
,
4417 bgp_static
->rmap
.name
);
4418 bgp_static
->rmap
.name
= NULL
;
4419 bgp_static
->rmap
.map
= NULL
;
4420 bgp_static
->valid
= 0;
4422 bgp_unlock_node(rn
);
4424 /* New configuration. */
4425 bgp_static
= bgp_static_new();
4426 bgp_static
->backdoor
= backdoor
;
4427 bgp_static
->valid
= 0;
4428 bgp_static
->igpmetric
= 0;
4429 bgp_static
->igpnexthop
.s_addr
= 0;
4430 bgp_static
->label_index
= label_index
;
4433 if (bgp_static
->rmap
.name
)
4434 XFREE(MTYPE_ROUTE_MAP_NAME
,
4435 bgp_static
->rmap
.name
);
4436 bgp_static
->rmap
.name
=
4437 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4438 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4440 rn
->info
= bgp_static
;
4443 bgp_static
->valid
= 1;
4445 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4447 if (!bgp_static
->backdoor
)
4448 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4453 /* Configure static BGP network. */
4454 static int bgp_static_unset(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4457 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4460 struct bgp_static
*bgp_static
;
4461 struct bgp_node
*rn
;
4463 /* Convert IP prefix string to struct prefix. */
4464 ret
= str2prefix(ip_str
, &p
);
4466 vty_out(vty
, "%% Malformed prefix\n");
4467 return CMD_WARNING_CONFIG_FAILED
;
4469 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4470 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4471 return CMD_WARNING_CONFIG_FAILED
;
4476 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4479 "%% Can't find specified static route configuration.\n");
4480 return CMD_WARNING_CONFIG_FAILED
;
4483 bgp_static
= rn
->info
;
4485 /* Update BGP RIB. */
4486 if (!bgp_static
->backdoor
)
4487 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4489 /* Clear configuration. */
4490 bgp_static_free(bgp_static
);
4492 bgp_unlock_node(rn
);
4493 bgp_unlock_node(rn
);
4498 void bgp_static_add(struct bgp
*bgp
)
4502 struct bgp_node
*rn
;
4503 struct bgp_node
*rm
;
4504 struct bgp_table
*table
;
4505 struct bgp_static
*bgp_static
;
4507 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4508 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4509 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4510 rn
= bgp_route_next(rn
))
4511 if (rn
->info
!= NULL
) {
4512 if ((safi
== SAFI_MPLS_VPN
)
4513 || (safi
== SAFI_ENCAP
)
4514 || (safi
== SAFI_EVPN
)) {
4517 for (rm
= bgp_table_top(table
);
4519 rm
= bgp_route_next(rm
)) {
4520 bgp_static
= rm
->info
;
4521 bgp_static_update_safi(
4527 bgp_static_update(bgp
, &rn
->p
,
4534 /* Called from bgp_delete(). Delete all static routes from the BGP
4536 void bgp_static_delete(struct bgp
*bgp
)
4540 struct bgp_node
*rn
;
4541 struct bgp_node
*rm
;
4542 struct bgp_table
*table
;
4543 struct bgp_static
*bgp_static
;
4545 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4546 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4547 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4548 rn
= bgp_route_next(rn
))
4549 if (rn
->info
!= NULL
) {
4550 if ((safi
== SAFI_MPLS_VPN
)
4551 || (safi
== SAFI_ENCAP
)
4552 || (safi
== SAFI_EVPN
)) {
4555 for (rm
= bgp_table_top(table
);
4557 rm
= bgp_route_next(rm
)) {
4558 bgp_static
= rm
->info
;
4559 bgp_static_withdraw_safi(
4568 bgp_unlock_node(rn
);
4571 bgp_static
= rn
->info
;
4572 bgp_static_withdraw(bgp
, &rn
->p
,
4574 bgp_static_free(bgp_static
);
4576 bgp_unlock_node(rn
);
4581 void bgp_static_redo_import_check(struct bgp
*bgp
)
4585 struct bgp_node
*rn
;
4586 struct bgp_node
*rm
;
4587 struct bgp_table
*table
;
4588 struct bgp_static
*bgp_static
;
4590 /* Use this flag to force reprocessing of the route */
4591 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4592 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4593 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4594 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4595 rn
= bgp_route_next(rn
))
4596 if (rn
->info
!= NULL
) {
4597 if ((safi
== SAFI_MPLS_VPN
)
4598 || (safi
== SAFI_ENCAP
)
4599 || (safi
== SAFI_EVPN
)) {
4602 for (rm
= bgp_table_top(table
);
4604 rm
= bgp_route_next(rm
)) {
4605 bgp_static
= rm
->info
;
4606 bgp_static_update_safi(
4612 bgp_static
= rn
->info
;
4613 bgp_static_update(bgp
, &rn
->p
,
4618 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4621 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4624 struct bgp_table
*table
;
4625 struct bgp_node
*rn
;
4626 struct bgp_info
*ri
;
4628 table
= bgp
->rib
[afi
][safi
];
4629 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4630 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4631 if (ri
->peer
== bgp
->peer_self
4632 && ((ri
->type
== ZEBRA_ROUTE_BGP
4633 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4634 || (ri
->type
!= ZEBRA_ROUTE_BGP
4636 == BGP_ROUTE_REDISTRIBUTE
))) {
4637 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4639 bgp_unlink_nexthop(ri
);
4640 bgp_info_delete(rn
, ri
);
4641 bgp_process(bgp
, rn
, afi
, safi
);
4648 * Purge all networks and redistributed routes from routing table.
4649 * Invoked upon the instance going down.
4651 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4656 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4657 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4658 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4663 * Currently this is used to set static routes for VPN and ENCAP.
4664 * I think it can probably be factored with bgp_static_set.
4666 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4667 const char *ip_str
, const char *rd_str
,
4668 const char *label_str
, const char *rmap_str
,
4669 int evpn_type
, const char *esi
, const char *gwip
,
4670 const char *ethtag
, const char *routermac
)
4672 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4675 struct prefix_rd prd
;
4676 struct bgp_node
*prn
;
4677 struct bgp_node
*rn
;
4678 struct bgp_table
*table
;
4679 struct bgp_static
*bgp_static
;
4680 mpls_label_t label
= MPLS_INVALID_LABEL
;
4681 struct prefix gw_ip
;
4683 /* validate ip prefix */
4684 ret
= str2prefix(ip_str
, &p
);
4686 vty_out(vty
, "%% Malformed prefix\n");
4687 return CMD_WARNING_CONFIG_FAILED
;
4690 if ((afi
== AFI_L2VPN
)
4691 && (bgp_build_evpn_prefix(evpn_type
,
4692 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4693 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4694 return CMD_WARNING_CONFIG_FAILED
;
4697 ret
= str2prefix_rd(rd_str
, &prd
);
4699 vty_out(vty
, "%% Malformed rd\n");
4700 return CMD_WARNING_CONFIG_FAILED
;
4704 unsigned long label_val
;
4705 label_val
= strtoul(label_str
, NULL
, 10);
4706 encode_label(label_val
, &label
);
4709 if (safi
== SAFI_EVPN
) {
4710 if (esi
&& str2esi(esi
, NULL
) == 0) {
4711 vty_out(vty
, "%% Malformed ESI\n");
4712 return CMD_WARNING_CONFIG_FAILED
;
4714 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4715 vty_out(vty
, "%% Malformed Router MAC\n");
4716 return CMD_WARNING_CONFIG_FAILED
;
4719 memset(&gw_ip
, 0, sizeof(struct prefix
));
4720 ret
= str2prefix(gwip
, &gw_ip
);
4722 vty_out(vty
, "%% Malformed GatewayIp\n");
4723 return CMD_WARNING_CONFIG_FAILED
;
4725 if ((gw_ip
.family
== AF_INET
4726 && IS_EVPN_PREFIX_IPADDR_V6(
4727 (struct prefix_evpn
*)&p
))
4728 || (gw_ip
.family
== AF_INET6
4729 && IS_EVPN_PREFIX_IPADDR_V4(
4730 (struct prefix_evpn
*)&p
))) {
4732 "%% GatewayIp family differs with IP prefix\n");
4733 return CMD_WARNING_CONFIG_FAILED
;
4737 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4738 if (prn
->info
== NULL
)
4739 prn
->info
= bgp_table_init(afi
, safi
);
4741 bgp_unlock_node(prn
);
4744 rn
= bgp_node_get(table
, &p
);
4747 vty_out(vty
, "%% Same network configuration exists\n");
4748 bgp_unlock_node(rn
);
4750 /* New configuration. */
4751 bgp_static
= bgp_static_new();
4752 bgp_static
->backdoor
= 0;
4753 bgp_static
->valid
= 0;
4754 bgp_static
->igpmetric
= 0;
4755 bgp_static
->igpnexthop
.s_addr
= 0;
4756 bgp_static
->label
= label
;
4757 bgp_static
->prd
= prd
;
4760 if (bgp_static
->rmap
.name
)
4761 XFREE(MTYPE_ROUTE_MAP_NAME
,
4762 bgp_static
->rmap
.name
);
4763 bgp_static
->rmap
.name
=
4764 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4765 bgp_static
->rmap
.map
=
4766 route_map_lookup_by_name(rmap_str
);
4769 if (safi
== SAFI_EVPN
) {
4771 bgp_static
->eth_s_id
=
4773 sizeof(struct eth_segment_id
));
4774 str2esi(esi
, bgp_static
->eth_s_id
);
4777 bgp_static
->router_mac
=
4778 XCALLOC(MTYPE_ATTR
, ETHER_ADDR_LEN
+ 1);
4779 prefix_str2mac(routermac
,
4780 bgp_static
->router_mac
);
4783 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4785 rn
->info
= bgp_static
;
4787 bgp_static
->valid
= 1;
4788 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4794 /* Configure static BGP network. */
4795 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4796 const char *ip_str
, const char *rd_str
,
4797 const char *label_str
, int evpn_type
, const char *esi
,
4798 const char *gwip
, const char *ethtag
)
4800 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4803 struct prefix_rd prd
;
4804 struct bgp_node
*prn
;
4805 struct bgp_node
*rn
;
4806 struct bgp_table
*table
;
4807 struct bgp_static
*bgp_static
;
4808 mpls_label_t label
= MPLS_INVALID_LABEL
;
4810 /* Convert IP prefix string to struct prefix. */
4811 ret
= str2prefix(ip_str
, &p
);
4813 vty_out(vty
, "%% Malformed prefix\n");
4814 return CMD_WARNING_CONFIG_FAILED
;
4817 if ((afi
== AFI_L2VPN
)
4818 && (bgp_build_evpn_prefix(evpn_type
,
4819 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4820 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4821 return CMD_WARNING_CONFIG_FAILED
;
4823 ret
= str2prefix_rd(rd_str
, &prd
);
4825 vty_out(vty
, "%% Malformed rd\n");
4826 return CMD_WARNING_CONFIG_FAILED
;
4830 unsigned long label_val
;
4831 label_val
= strtoul(label_str
, NULL
, 10);
4832 encode_label(label_val
, &label
);
4835 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4836 if (prn
->info
== NULL
)
4837 prn
->info
= bgp_table_init(afi
, safi
);
4839 bgp_unlock_node(prn
);
4842 rn
= bgp_node_lookup(table
, &p
);
4845 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4847 bgp_static
= rn
->info
;
4848 bgp_static_free(bgp_static
);
4850 bgp_unlock_node(rn
);
4851 bgp_unlock_node(rn
);
4853 vty_out(vty
, "%% Can't find the route\n");
4858 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4859 const char *rmap_name
)
4861 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4862 struct bgp_rmap
*rmap
;
4864 rmap
= &bgp
->table_map
[afi
][safi
];
4867 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4868 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4869 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4872 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4877 if (bgp_fibupd_safi(safi
))
4878 bgp_zebra_announce_table(bgp
, afi
, safi
);
4883 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
4884 const char *rmap_name
)
4886 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4887 struct bgp_rmap
*rmap
;
4889 rmap
= &bgp
->table_map
[afi
][safi
];
4891 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4895 if (bgp_fibupd_safi(safi
))
4896 bgp_zebra_announce_table(bgp
, afi
, safi
);
4901 int bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4902 safi_t safi
, int *write
)
4904 if (bgp
->table_map
[afi
][safi
].name
) {
4905 bgp_config_write_family_header(vty
, afi
, safi
, write
);
4906 vty_out(vty
, " table-map %s\n",
4907 bgp
->table_map
[afi
][safi
].name
);
4913 DEFUN (bgp_table_map
,
4916 "BGP table to RIB route download filter\n"
4917 "Name of the route map\n")
4920 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4921 argv
[idx_word
]->arg
);
4923 DEFUN (no_bgp_table_map
,
4924 no_bgp_table_map_cmd
,
4925 "no table-map WORD",
4927 "BGP table to RIB route download filter\n"
4928 "Name of the route map\n")
4931 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4932 argv
[idx_word
]->arg
);
4937 "network A.B.C.D/M",
4938 "Specify a network to announce via BGP\n"
4941 int idx_ipv4_prefixlen
= 1;
4942 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4943 bgp_node_safi(vty
), NULL
, 0,
4944 BGP_INVALID_LABEL_INDEX
);
4947 DEFUN (bgp_network_route_map
,
4948 bgp_network_route_map_cmd
,
4949 "network A.B.C.D/M route-map WORD",
4950 "Specify a network to announce via BGP\n"
4952 "Route-map to modify the attributes\n"
4953 "Name of the route map\n")
4955 int idx_ipv4_prefixlen
= 1;
4957 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4958 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
4959 BGP_INVALID_LABEL_INDEX
);
4962 DEFUN (bgp_network_backdoor
,
4963 bgp_network_backdoor_cmd
,
4964 "network A.B.C.D/M backdoor",
4965 "Specify a network to announce via BGP\n"
4967 "Specify a BGP backdoor route\n")
4969 int idx_ipv4_prefixlen
= 1;
4970 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4971 SAFI_UNICAST
, NULL
, 1, BGP_INVALID_LABEL_INDEX
);
4974 DEFUN (bgp_network_mask
,
4975 bgp_network_mask_cmd
,
4976 "network A.B.C.D mask A.B.C.D",
4977 "Specify a network to announce via BGP\n"
4985 char prefix_str
[BUFSIZ
];
4987 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
4990 vty_out(vty
, "%% Inconsistent address and mask\n");
4991 return CMD_WARNING_CONFIG_FAILED
;
4994 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
4995 0, BGP_INVALID_LABEL_INDEX
);
4998 DEFUN (bgp_network_mask_route_map
,
4999 bgp_network_mask_route_map_cmd
,
5000 "network A.B.C.D mask A.B.C.D route-map WORD",
5001 "Specify a network to announce via BGP\n"
5005 "Route-map to modify the attributes\n"
5006 "Name of the route map\n")
5012 char prefix_str
[BUFSIZ
];
5014 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5017 vty_out(vty
, "%% Inconsistent address and mask\n");
5018 return CMD_WARNING_CONFIG_FAILED
;
5021 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5022 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5025 DEFUN (bgp_network_mask_backdoor
,
5026 bgp_network_mask_backdoor_cmd
,
5027 "network A.B.C.D mask A.B.C.D backdoor",
5028 "Specify a network to announce via BGP\n"
5032 "Specify a BGP backdoor route\n")
5037 char prefix_str
[BUFSIZ
];
5039 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5042 vty_out(vty
, "%% Inconsistent address and mask\n");
5043 return CMD_WARNING_CONFIG_FAILED
;
5046 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5047 BGP_INVALID_LABEL_INDEX
);
5050 DEFUN (bgp_network_mask_natural
,
5051 bgp_network_mask_natural_cmd
,
5053 "Specify a network to announce via BGP\n"
5058 char prefix_str
[BUFSIZ
];
5060 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5062 vty_out(vty
, "%% Inconsistent address and mask\n");
5063 return CMD_WARNING_CONFIG_FAILED
;
5066 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5067 0, BGP_INVALID_LABEL_INDEX
);
5070 DEFUN (bgp_network_mask_natural_route_map
,
5071 bgp_network_mask_natural_route_map_cmd
,
5072 "network A.B.C.D route-map WORD",
5073 "Specify a network to announce via BGP\n"
5075 "Route-map to modify the attributes\n"
5076 "Name of the route map\n")
5081 char prefix_str
[BUFSIZ
];
5083 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5085 vty_out(vty
, "%% Inconsistent address and mask\n");
5086 return CMD_WARNING_CONFIG_FAILED
;
5089 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5090 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5093 DEFUN (bgp_network_mask_natural_backdoor
,
5094 bgp_network_mask_natural_backdoor_cmd
,
5095 "network A.B.C.D backdoor",
5096 "Specify a network to announce via BGP\n"
5098 "Specify a BGP backdoor route\n")
5102 char prefix_str
[BUFSIZ
];
5104 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5106 vty_out(vty
, "%% Inconsistent address and mask\n");
5107 return CMD_WARNING_CONFIG_FAILED
;
5110 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5111 BGP_INVALID_LABEL_INDEX
);
5114 DEFUN (bgp_network_label_index
,
5115 bgp_network_label_index_cmd
,
5116 "network A.B.C.D/M label-index (0-1048560)",
5117 "Specify a network to announce via BGP\n"
5118 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5119 "Label index to associate with the prefix\n"
5120 "Label index value\n")
5122 u_int32_t label_index
;
5124 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5125 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5126 NULL
, 0, label_index
);
5129 DEFUN (bgp_network_label_index_route_map
,
5130 bgp_network_label_index_route_map_cmd
,
5131 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
5132 "Specify a network to announce via BGP\n"
5134 "Label index to associate with the prefix\n"
5135 "Label index value\n"
5136 "Route-map to modify the attributes\n"
5137 "Name of the route map\n")
5139 u_int32_t label_index
;
5141 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5142 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5143 argv
[5]->arg
, 0, label_index
);
5146 DEFUN (no_bgp_network
,
5148 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
5150 "Specify a network to announce via BGP\n"
5152 "Specify a BGP backdoor route\n"
5153 "Route-map to modify the attributes\n"
5154 "Name of the route map\n")
5156 int idx_ipv4_prefixlen
= 2;
5157 return bgp_static_unset(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5158 bgp_node_safi(vty
));
5161 DEFUN (no_bgp_network_mask
,
5162 no_bgp_network_mask_cmd
,
5163 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
5165 "Specify a network to announce via BGP\n"
5169 "Specify a BGP backdoor route\n"
5170 "Route-map to modify the attributes\n"
5171 "Name of the route map\n")
5176 char prefix_str
[BUFSIZ
];
5178 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5181 vty_out(vty
, "%% Inconsistent address and mask\n");
5182 return CMD_WARNING_CONFIG_FAILED
;
5185 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5188 DEFUN (no_bgp_network_mask_natural
,
5189 no_bgp_network_mask_natural_cmd
,
5190 "no network A.B.C.D [<backdoor|route-map WORD>]",
5192 "Specify a network to announce via BGP\n"
5194 "Specify a BGP backdoor route\n"
5195 "Route-map to modify the attributes\n"
5196 "Name of the route map\n")
5200 char prefix_str
[BUFSIZ
];
5202 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5204 vty_out(vty
, "%% Inconsistent address and mask\n");
5205 return CMD_WARNING_CONFIG_FAILED
;
5208 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5211 ALIAS(no_bgp_network
, no_bgp_network_label_index_cmd
,
5212 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
5213 "Specify a network to announce via BGP\n"
5214 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5215 "Label index to associate with the prefix\n"
5216 "Label index value\n")
5218 ALIAS(no_bgp_network
, no_bgp_network_label_index_route_map_cmd
,
5219 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
5220 "Specify a network to announce via BGP\n"
5222 "Label index to associate with the prefix\n"
5223 "Label index value\n"
5224 "Route-map to modify the attributes\n"
5225 "Name of the route map\n")
5227 DEFUN (ipv6_bgp_network
,
5228 ipv6_bgp_network_cmd
,
5229 "network X:X::X:X/M",
5230 "Specify a network to announce via BGP\n"
5233 int idx_ipv6_prefixlen
= 1;
5234 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5235 bgp_node_safi(vty
), NULL
, 0,
5236 BGP_INVALID_LABEL_INDEX
);
5239 DEFUN (ipv6_bgp_network_route_map
,
5240 ipv6_bgp_network_route_map_cmd
,
5241 "network X:X::X:X/M route-map WORD",
5242 "Specify a network to announce via BGP\n"
5244 "Route-map to modify the attributes\n"
5245 "Name of the route map\n")
5247 int idx_ipv6_prefixlen
= 1;
5249 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5250 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5251 BGP_INVALID_LABEL_INDEX
);
5254 DEFUN (ipv6_bgp_network_label_index
,
5255 ipv6_bgp_network_label_index_cmd
,
5256 "network X:X::X:X/M label-index (0-1048560)",
5257 "Specify a network to announce via BGP\n"
5258 "IPv6 prefix <network>/<length>\n"
5259 "Label index to associate with the prefix\n"
5260 "Label index value\n")
5262 u_int32_t label_index
;
5264 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5265 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5266 NULL
, 0, label_index
);
5269 DEFUN (ipv6_bgp_network_label_index_route_map
,
5270 ipv6_bgp_network_label_index_route_map_cmd
,
5271 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
5272 "Specify a network to announce via BGP\n"
5274 "Label index to associate with the prefix\n"
5275 "Label index value\n"
5276 "Route-map to modify the attributes\n"
5277 "Name of the route map\n")
5279 u_int32_t label_index
;
5281 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5282 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5283 argv
[5]->arg
, 0, label_index
);
5286 DEFUN (no_ipv6_bgp_network
,
5287 no_ipv6_bgp_network_cmd
,
5288 "no network X:X::X:X/M [route-map WORD]",
5290 "Specify a network to announce via BGP\n"
5292 "Route-map to modify the attributes\n"
5293 "Name of the route map\n")
5295 int idx_ipv6_prefixlen
= 2;
5296 return bgp_static_unset(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5297 bgp_node_safi(vty
));
5300 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_cmd
,
5301 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
5302 "Specify a network to announce via BGP\n"
5303 "IPv6 prefix <network>/<length>\n"
5304 "Label index to associate with the prefix\n"
5305 "Label index value\n")
5307 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_route_map_cmd
,
5308 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
5309 "Specify a network to announce via BGP\n"
5311 "Label index to associate with the prefix\n"
5312 "Label index value\n"
5313 "Route-map to modify the attributes\n"
5314 "Name of the route map\n")
5316 /* Aggreagete address:
5318 advertise-map Set condition to advertise attribute
5319 as-set Generate AS set path information
5320 attribute-map Set attributes of aggregate
5321 route-map Set parameters of aggregate
5322 summary-only Filter more specific routes from updates
5323 suppress-map Conditionally filter more specific routes from updates
5326 struct bgp_aggregate
{
5327 /* Summary-only flag. */
5328 u_char summary_only
;
5330 /* AS set generation. */
5333 /* Route-map for aggregated route. */
5334 struct route_map
*map
;
5336 /* Suppress-count. */
5337 unsigned long count
;
5339 /* SAFI configuration. */
5343 static struct bgp_aggregate
*bgp_aggregate_new(void)
5345 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5348 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5350 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5353 /* Update an aggregate as routes are added/removed from the BGP table */
5354 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5355 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5356 struct bgp_info
*del
,
5357 struct bgp_aggregate
*aggregate
)
5359 struct bgp_table
*table
;
5360 struct bgp_node
*top
;
5361 struct bgp_node
*rn
;
5363 struct aspath
*aspath
= NULL
;
5364 struct aspath
*asmerge
= NULL
;
5365 struct community
*community
= NULL
;
5366 struct community
*commerge
= NULL
;
5367 #if defined(AGGREGATE_NEXTHOP_CHECK)
5368 struct in_addr nexthop
;
5371 struct bgp_info
*ri
;
5372 struct bgp_info
*new;
5374 unsigned long match
= 0;
5375 u_char atomic_aggregate
= 0;
5377 /* Record adding route's nexthop and med. */
5379 #if defined(AGGREGATE_NEXTHOP_CHECK)
5380 nexthop
= rinew
->attr
->nexthop
;
5381 med
= rinew
->attr
->med
;
5385 /* ORIGIN attribute: If at least one route among routes that are
5386 aggregated has ORIGIN with the value INCOMPLETE, then the
5387 aggregated route must have the ORIGIN attribute with the value
5388 INCOMPLETE. Otherwise, if at least one route among routes that
5389 are aggregated has ORIGIN with the value EGP, then the aggregated
5390 route must have the origin attribute with the value EGP. In all
5391 other case the value of the ORIGIN attribute of the aggregated
5392 route is INTERNAL. */
5393 origin
= BGP_ORIGIN_IGP
;
5395 table
= bgp
->rib
[afi
][safi
];
5397 top
= bgp_node_get(table
, p
);
5398 for (rn
= bgp_node_get(table
, p
); rn
;
5399 rn
= bgp_route_next_until(rn
, top
))
5400 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5403 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5404 if (BGP_INFO_HOLDDOWN(ri
))
5407 if (del
&& ri
== del
)
5410 if (!rinew
&& first
) {
5411 #if defined(AGGREGATE_NEXTHOP_CHECK)
5412 nexthop
= ri
->attr
->nexthop
;
5413 med
= ri
->attr
->med
;
5418 #ifdef AGGREGATE_NEXTHOP_CHECK
5419 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5421 || ri
->attr
->med
!= med
) {
5423 aspath_free(aspath
);
5425 community_free(community
);
5426 bgp_unlock_node(rn
);
5427 bgp_unlock_node(top
);
5430 #endif /* AGGREGATE_NEXTHOP_CHECK */
5433 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5434 atomic_aggregate
= 1;
5436 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5437 if (aggregate
->summary_only
) {
5438 (bgp_info_extra_get(ri
))
5442 BGP_INFO_ATTR_CHANGED
);
5448 if (origin
< ri
->attr
->origin
)
5449 origin
= ri
->attr
->origin
;
5451 if (aggregate
->as_set
) {
5453 asmerge
= aspath_aggregate(
5456 aspath_free(aspath
);
5459 aspath
= aspath_dup(
5462 if (ri
->attr
->community
) {
5464 commerge
= community_merge(
5466 ri
->attr
->community
);
5467 community
= community_uniq_sort(
5472 community
= community_dup(
5473 ri
->attr
->community
);
5479 bgp_process(bgp
, rn
, afi
, safi
);
5481 bgp_unlock_node(top
);
5486 if (aggregate
->summary_only
)
5487 (bgp_info_extra_get(rinew
))->suppress
++;
5489 if (origin
< rinew
->attr
->origin
)
5490 origin
= rinew
->attr
->origin
;
5492 if (aggregate
->as_set
) {
5494 asmerge
= aspath_aggregate(aspath
,
5495 rinew
->attr
->aspath
);
5496 aspath_free(aspath
);
5499 aspath
= aspath_dup(rinew
->attr
->aspath
);
5501 if (rinew
->attr
->community
) {
5503 commerge
= community_merge(
5505 rinew
->attr
->community
);
5507 community_uniq_sort(commerge
);
5508 community_free(commerge
);
5510 community
= community_dup(
5511 rinew
->attr
->community
);
5516 if (aggregate
->count
> 0) {
5517 rn
= bgp_node_get(table
, p
);
5519 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5520 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5521 community
, aggregate
->as_set
,
5524 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5526 bgp_info_add(rn
, new);
5527 bgp_unlock_node(rn
);
5528 bgp_process(bgp
, rn
, afi
, safi
);
5531 aspath_free(aspath
);
5533 community_free(community
);
5537 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5538 struct bgp_aggregate
*);
5540 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5541 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5543 struct bgp_node
*child
;
5544 struct bgp_node
*rn
;
5545 struct bgp_aggregate
*aggregate
;
5546 struct bgp_table
*table
;
5548 /* MPLS-VPN aggregation is not yet supported. */
5549 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5550 || (safi
== SAFI_EVPN
))
5553 table
= bgp
->aggregate
[afi
][safi
];
5555 /* No aggregates configured. */
5556 if (bgp_table_top_nolock(table
) == NULL
)
5559 if (p
->prefixlen
== 0)
5562 if (BGP_INFO_HOLDDOWN(ri
))
5565 child
= bgp_node_get(table
, p
);
5567 /* Aggregate address configuration check. */
5568 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5569 if ((aggregate
= rn
->info
) != NULL
5570 && rn
->p
.prefixlen
< p
->prefixlen
) {
5571 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5572 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5575 bgp_unlock_node(child
);
5578 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5579 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5581 struct bgp_node
*child
;
5582 struct bgp_node
*rn
;
5583 struct bgp_aggregate
*aggregate
;
5584 struct bgp_table
*table
;
5586 /* MPLS-VPN aggregation is not yet supported. */
5587 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5588 || (safi
== SAFI_EVPN
))
5591 table
= bgp
->aggregate
[afi
][safi
];
5593 /* No aggregates configured. */
5594 if (bgp_table_top_nolock(table
) == NULL
)
5597 if (p
->prefixlen
== 0)
5600 child
= bgp_node_get(table
, p
);
5602 /* Aggregate address configuration check. */
5603 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5604 if ((aggregate
= rn
->info
) != NULL
5605 && rn
->p
.prefixlen
< p
->prefixlen
) {
5606 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5607 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5610 bgp_unlock_node(child
);
5613 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5614 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5615 safi_t safi
, struct bgp_aggregate
*aggregate
)
5617 struct bgp_table
*table
;
5618 struct bgp_node
*top
;
5619 struct bgp_node
*rn
;
5620 struct bgp_info
*new;
5621 struct bgp_info
*ri
;
5622 unsigned long match
;
5623 u_char origin
= BGP_ORIGIN_IGP
;
5624 struct aspath
*aspath
= NULL
;
5625 struct aspath
*asmerge
= NULL
;
5626 struct community
*community
= NULL
;
5627 struct community
*commerge
= NULL
;
5628 u_char atomic_aggregate
= 0;
5630 table
= bgp
->rib
[afi
][safi
];
5633 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5635 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5638 /* If routes exists below this node, generate aggregate routes. */
5639 top
= bgp_node_get(table
, p
);
5640 for (rn
= bgp_node_get(table
, p
); rn
;
5641 rn
= bgp_route_next_until(rn
, top
))
5642 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5645 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5646 if (BGP_INFO_HOLDDOWN(ri
))
5650 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5651 atomic_aggregate
= 1;
5653 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5654 /* summary-only aggregate route suppress
5656 route announcement. */
5657 if (aggregate
->summary_only
) {
5658 (bgp_info_extra_get(ri
))
5662 BGP_INFO_ATTR_CHANGED
);
5666 /* If at least one route among routes
5667 * that are aggregated has
5668 * ORIGIN with the value INCOMPLETE,
5669 * then the aggregated route
5670 * MUST have the ORIGIN attribute with
5671 * the value INCOMPLETE.
5672 * Otherwise, if at least one route
5673 * among routes that are
5674 * aggregated has ORIGIN with the value
5675 * EGP, then the aggregated
5676 * route MUST have the ORIGIN attribute
5677 * with the value EGP.
5679 if (origin
< ri
->attr
->origin
)
5680 origin
= ri
->attr
->origin
;
5682 /* as-set aggregate route generate
5684 community aggregation. */
5685 if (aggregate
->as_set
) {
5687 asmerge
= aspath_aggregate(
5690 aspath_free(aspath
);
5693 aspath
= aspath_dup(
5696 if (ri
->attr
->community
) {
5698 commerge
= community_merge(
5700 ri
->attr
->community
);
5701 community
= community_uniq_sort(
5706 community
= community_dup(
5707 ri
->attr
->community
);
5714 /* If this node is suppressed, process the change. */
5716 bgp_process(bgp
, rn
, afi
, safi
);
5718 bgp_unlock_node(top
);
5720 /* Add aggregate route to BGP table. */
5721 if (aggregate
->count
) {
5722 rn
= bgp_node_get(table
, p
);
5724 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5725 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5726 community
, aggregate
->as_set
,
5729 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5731 bgp_info_add(rn
, new);
5732 bgp_unlock_node(rn
);
5734 /* Process change. */
5735 bgp_process(bgp
, rn
, afi
, safi
);
5738 aspath_free(aspath
);
5740 community_free(community
);
5744 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5745 safi_t safi
, struct bgp_aggregate
*aggregate
)
5747 struct bgp_table
*table
;
5748 struct bgp_node
*top
;
5749 struct bgp_node
*rn
;
5750 struct bgp_info
*ri
;
5751 unsigned long match
;
5753 table
= bgp
->rib
[afi
][safi
];
5755 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5757 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5760 /* If routes exists below this node, generate aggregate routes. */
5761 top
= bgp_node_get(table
, p
);
5762 for (rn
= bgp_node_get(table
, p
); rn
;
5763 rn
= bgp_route_next_until(rn
, top
))
5764 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5767 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5768 if (BGP_INFO_HOLDDOWN(ri
))
5771 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5772 if (aggregate
->summary_only
5774 ri
->extra
->suppress
--;
5776 if (ri
->extra
->suppress
== 0) {
5779 BGP_INFO_ATTR_CHANGED
);
5787 /* If this node was suppressed, process the change. */
5789 bgp_process(bgp
, rn
, afi
, safi
);
5791 bgp_unlock_node(top
);
5793 /* Delete aggregate route from BGP table. */
5794 rn
= bgp_node_get(table
, p
);
5796 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5797 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5798 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5801 /* Withdraw static BGP route from routing table. */
5803 bgp_info_delete(rn
, ri
);
5804 bgp_process(bgp
, rn
, afi
, safi
);
5807 /* Unlock bgp_node_lookup. */
5808 bgp_unlock_node(rn
);
5811 /* Aggregate route attribute. */
5812 #define AGGREGATE_SUMMARY_ONLY 1
5813 #define AGGREGATE_AS_SET 1
5815 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5816 afi_t afi
, safi_t safi
)
5818 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5821 struct bgp_node
*rn
;
5822 struct bgp_aggregate
*aggregate
;
5824 /* Convert string to prefix structure. */
5825 ret
= str2prefix(prefix_str
, &p
);
5827 vty_out(vty
, "Malformed prefix\n");
5828 return CMD_WARNING_CONFIG_FAILED
;
5832 /* Old configuration check. */
5833 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5836 "%% There is no aggregate-address configuration.\n");
5837 return CMD_WARNING_CONFIG_FAILED
;
5840 aggregate
= rn
->info
;
5841 if (aggregate
->safi
== SAFI_UNICAST
)
5842 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5843 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5844 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5846 if (aggregate
->safi
== SAFI_MULTICAST
)
5847 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5849 /* Unlock aggregate address configuration. */
5851 bgp_aggregate_free(aggregate
);
5852 bgp_unlock_node(rn
);
5853 bgp_unlock_node(rn
);
5858 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5859 safi_t safi
, u_char summary_only
, u_char as_set
)
5861 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5864 struct bgp_node
*rn
;
5865 struct bgp_aggregate
*aggregate
;
5867 /* Convert string to prefix structure. */
5868 ret
= str2prefix(prefix_str
, &p
);
5870 vty_out(vty
, "Malformed prefix\n");
5871 return CMD_WARNING_CONFIG_FAILED
;
5875 /* Old configuration check. */
5876 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5879 vty_out(vty
, "There is already same aggregate network.\n");
5880 /* try to remove the old entry */
5881 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5883 vty_out(vty
, "Error deleting aggregate.\n");
5884 bgp_unlock_node(rn
);
5885 return CMD_WARNING_CONFIG_FAILED
;
5889 /* Make aggregate address structure. */
5890 aggregate
= bgp_aggregate_new();
5891 aggregate
->summary_only
= summary_only
;
5892 aggregate
->as_set
= as_set
;
5893 aggregate
->safi
= safi
;
5894 rn
->info
= aggregate
;
5896 /* Aggregate address insert into BGP routing table. */
5897 if (safi
== SAFI_UNICAST
)
5898 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5899 if (safi
== SAFI_LABELED_UNICAST
)
5900 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5902 if (safi
== SAFI_MULTICAST
)
5903 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5908 DEFUN (aggregate_address
,
5909 aggregate_address_cmd
,
5910 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5911 "Configure BGP aggregate entries\n"
5912 "Aggregate prefix\n"
5913 "Generate AS set path information\n"
5914 "Filter more specific routes from updates\n"
5915 "Filter more specific routes from updates\n"
5916 "Generate AS set path information\n")
5919 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5920 char *prefix
= argv
[idx
]->arg
;
5922 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5924 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5925 ? AGGREGATE_SUMMARY_ONLY
5928 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5929 summary_only
, as_set
);
5932 DEFUN (aggregate_address_mask
,
5933 aggregate_address_mask_cmd
,
5934 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5935 "Configure BGP aggregate entries\n"
5936 "Aggregate address\n"
5938 "Generate AS set path information\n"
5939 "Filter more specific routes from updates\n"
5940 "Filter more specific routes from updates\n"
5941 "Generate AS set path information\n")
5944 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5945 char *prefix
= argv
[idx
]->arg
;
5946 char *mask
= argv
[idx
+ 1]->arg
;
5948 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5950 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5951 ? AGGREGATE_SUMMARY_ONLY
5954 char prefix_str
[BUFSIZ
];
5955 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5958 vty_out(vty
, "%% Inconsistent address and mask\n");
5959 return CMD_WARNING_CONFIG_FAILED
;
5962 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5963 summary_only
, as_set
);
5966 DEFUN (no_aggregate_address
,
5967 no_aggregate_address_cmd
,
5968 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5970 "Configure BGP aggregate entries\n"
5971 "Aggregate prefix\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/M", &idx
);
5979 char *prefix
= argv
[idx
]->arg
;
5980 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5983 DEFUN (no_aggregate_address_mask
,
5984 no_aggregate_address_mask_cmd
,
5985 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5987 "Configure BGP aggregate entries\n"
5988 "Aggregate address\n"
5990 "Generate AS set path information\n"
5991 "Filter more specific routes from updates\n"
5992 "Filter more specific routes from updates\n"
5993 "Generate AS set path information\n")
5996 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5997 char *prefix
= argv
[idx
]->arg
;
5998 char *mask
= argv
[idx
+ 1]->arg
;
6000 char prefix_str
[BUFSIZ
];
6001 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6004 vty_out(vty
, "%% Inconsistent address and mask\n");
6005 return CMD_WARNING_CONFIG_FAILED
;
6008 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6011 DEFUN (ipv6_aggregate_address
,
6012 ipv6_aggregate_address_cmd
,
6013 "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 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6022 ? AGGREGATE_SUMMARY_ONLY
6024 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6028 DEFUN (no_ipv6_aggregate_address
,
6029 no_ipv6_aggregate_address_cmd
,
6030 "no aggregate-address X:X::X:X/M [summary-only]",
6032 "Configure BGP aggregate entries\n"
6033 "Aggregate prefix\n"
6034 "Filter more specific routes from updates\n")
6037 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6038 char *prefix
= argv
[idx
]->arg
;
6039 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6042 /* Redistribute route treatment. */
6043 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6044 const struct in_addr
*nexthop
,
6045 const struct in6_addr
*nexthop6
, unsigned int ifindex
,
6046 u_int32_t metric
, u_char type
, u_short instance
,
6049 struct bgp_info
*new;
6050 struct bgp_info
*bi
;
6051 struct bgp_info info
;
6052 struct bgp_node
*bn
;
6054 struct attr
*new_attr
;
6057 struct bgp_redist
*red
;
6059 /* Make default attribute. */
6060 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6062 attr
.nexthop
= *nexthop
;
6063 attr
.nh_ifindex
= ifindex
;
6066 attr
.mp_nexthop_global
= *nexthop6
;
6067 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6071 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6074 afi
= family2afi(p
->family
);
6076 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6078 struct attr attr_new
;
6080 /* Copy attribute for modification. */
6081 bgp_attr_dup(&attr_new
, &attr
);
6083 if (red
->redist_metric_flag
)
6084 attr_new
.med
= red
->redist_metric
;
6086 /* Apply route-map. */
6087 if (red
->rmap
.name
) {
6088 info
.peer
= bgp
->peer_self
;
6089 info
.attr
= &attr_new
;
6091 SET_FLAG(bgp
->peer_self
->rmap_type
,
6092 PEER_RMAP_TYPE_REDISTRIBUTE
);
6094 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6097 bgp
->peer_self
->rmap_type
= 0;
6099 if (ret
== RMAP_DENYMATCH
) {
6100 /* Free uninterned attribute. */
6101 bgp_attr_flush(&attr_new
);
6103 /* Unintern original. */
6104 aspath_unintern(&attr
.aspath
);
6105 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6110 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6111 SAFI_UNICAST
, p
, NULL
);
6113 new_attr
= bgp_attr_intern(&attr_new
);
6115 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6116 if (bi
->peer
== bgp
->peer_self
6117 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6121 /* Ensure the (source route) type is updated. */
6123 if (attrhash_cmp(bi
->attr
, new_attr
)
6124 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6125 bgp_attr_unintern(&new_attr
);
6126 aspath_unintern(&attr
.aspath
);
6127 bgp_unlock_node(bn
);
6130 /* The attribute is changed. */
6131 bgp_info_set_flag(bn
, bi
,
6132 BGP_INFO_ATTR_CHANGED
);
6134 /* Rewrite BGP route information. */
6135 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6136 bgp_info_restore(bn
, bi
);
6138 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6140 bgp_attr_unintern(&bi
->attr
);
6141 bi
->attr
= new_attr
;
6142 bi
->uptime
= bgp_clock();
6144 /* Process change. */
6145 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6147 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6148 bgp_unlock_node(bn
);
6149 aspath_unintern(&attr
.aspath
);
6154 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6155 bgp
->peer_self
, new_attr
, bn
);
6156 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6158 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6159 bgp_info_add(bn
, new);
6160 bgp_unlock_node(bn
);
6161 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6164 /* Unintern original. */
6165 aspath_unintern(&attr
.aspath
);
6168 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6172 struct bgp_node
*rn
;
6173 struct bgp_info
*ri
;
6174 struct bgp_redist
*red
;
6176 afi
= family2afi(p
->family
);
6178 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6180 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6181 SAFI_UNICAST
, p
, NULL
);
6183 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6184 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6188 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6189 bgp_info_delete(rn
, ri
);
6190 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6192 bgp_unlock_node(rn
);
6196 /* Withdraw specified route type's route. */
6197 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6200 struct bgp_node
*rn
;
6201 struct bgp_info
*ri
;
6202 struct bgp_table
*table
;
6204 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6206 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6207 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6208 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6209 && ri
->instance
== instance
)
6213 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6215 bgp_info_delete(rn
, ri
);
6216 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6221 /* Static function to display route. */
6222 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
)
6225 u_int32_t destination
;
6228 if (p
->family
== AF_INET
) {
6229 len
= vty_out(vty
, "%s",
6230 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
));
6231 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6233 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6234 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6235 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6236 || p
->u
.prefix4
.s_addr
== 0) {
6237 /* When mask is natural, mask is not displayed. */
6239 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6240 } else if (p
->family
== AF_ETHERNET
) {
6241 #if defined(HAVE_CUMULUS)
6242 len
= vty_out(vty
, "%s",
6243 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6246 prefix2str(p
, buf
, PREFIX_STRLEN
);
6247 len
= vty_out(vty
, "%s", buf
);
6250 len
= vty_out(vty
, "%s/%d",
6251 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6256 vty_out(vty
, "\n%*s", 20, " ");
6258 vty_out(vty
, "%*s", len
, " ");
6261 enum bgp_display_type
{
6265 /* Print the short form route status for a bgp_info */
6266 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6267 json_object
*json_path
)
6271 /* Route status display. */
6272 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6273 json_object_boolean_true_add(json_path
, "removed");
6275 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6276 json_object_boolean_true_add(json_path
, "stale");
6278 if (binfo
->extra
&& binfo
->extra
->suppress
)
6279 json_object_boolean_true_add(json_path
, "suppressed");
6281 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6282 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6283 json_object_boolean_true_add(json_path
, "valid");
6286 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6287 json_object_boolean_true_add(json_path
, "history");
6289 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6290 json_object_boolean_true_add(json_path
, "damped");
6292 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6293 json_object_boolean_true_add(json_path
, "bestpath");
6295 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6296 json_object_boolean_true_add(json_path
, "multipath");
6298 /* Internal route. */
6299 if ((binfo
->peer
->as
)
6300 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6301 json_object_string_add(json_path
, "pathFrom",
6304 json_object_string_add(json_path
, "pathFrom",
6310 /* Route status display. */
6311 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6313 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6315 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6317 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6318 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6324 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6326 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6328 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6330 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6335 /* Internal route. */
6336 if (binfo
->peer
&& (binfo
->peer
->as
)
6337 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6343 /* called from terminal list command */
6344 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6345 int display
, safi_t safi
, json_object
*json_paths
)
6348 json_object
*json_path
= NULL
;
6349 json_object
*json_nexthops
= NULL
;
6350 json_object
*json_nexthop_global
= NULL
;
6351 json_object
*json_nexthop_ll
= NULL
;
6354 json_path
= json_object_new_object();
6356 /* short status lead text */
6357 route_vty_short_status_out(vty
, binfo
, json_path
);
6360 /* print prefix and mask */
6362 route_vty_out_route(p
, vty
);
6364 vty_out(vty
, "%*s", 17, " ");
6367 /* Print attribute */
6371 * For ENCAP and EVPN routes, nexthop address family is not
6372 * neccessarily the same as the prefix address family.
6373 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6374 * EVPN routes are also exchanged with a MP nexthop. Currently,
6376 * is only IPv4, the value will be present in either
6378 * attr->mp_nexthop_global_in
6380 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6382 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6388 &attr
->mp_nexthop_global_in
,
6393 inet_ntop(af
, &attr
->mp_nexthop_global
,
6400 } else if (safi
== SAFI_EVPN
) {
6402 json_nexthop_global
= json_object_new_object();
6404 json_object_string_add(
6405 json_nexthop_global
, "ip",
6406 inet_ntoa(attr
->nexthop
));
6407 json_object_string_add(json_nexthop_global
,
6409 json_object_boolean_true_add(
6410 json_nexthop_global
, "used");
6412 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6415 else if (p
->family
== AF_INET
6416 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6418 json_nexthop_global
= json_object_new_object();
6420 if ((safi
== SAFI_MPLS_VPN
)
6421 || (safi
== SAFI_EVPN
))
6422 json_object_string_add(
6423 json_nexthop_global
, "ip",
6425 attr
->mp_nexthop_global_in
));
6427 json_object_string_add(
6428 json_nexthop_global
, "ip",
6429 inet_ntoa(attr
->nexthop
));
6431 json_object_string_add(json_nexthop_global
,
6433 json_object_boolean_true_add(
6434 json_nexthop_global
, "used");
6436 if ((safi
== SAFI_MPLS_VPN
)
6437 || (safi
== SAFI_EVPN
))
6438 vty_out(vty
, "%-16s",
6440 attr
->mp_nexthop_global_in
));
6442 vty_out(vty
, "%-16s",
6443 inet_ntoa(attr
->nexthop
));
6448 else if (p
->family
== AF_INET6
6449 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6454 json_nexthop_global
= json_object_new_object();
6455 json_object_string_add(
6456 json_nexthop_global
, "ip",
6458 &attr
->mp_nexthop_global
, buf
,
6460 json_object_string_add(json_nexthop_global
,
6462 json_object_string_add(json_nexthop_global
,
6465 /* We display both LL & GL if both have been
6467 if ((attr
->mp_nexthop_len
== 32)
6468 || (binfo
->peer
->conf_if
)) {
6470 json_object_new_object();
6471 json_object_string_add(
6472 json_nexthop_ll
, "ip",
6475 &attr
->mp_nexthop_local
,
6477 json_object_string_add(json_nexthop_ll
,
6479 json_object_string_add(json_nexthop_ll
,
6484 &attr
->mp_nexthop_global
,
6485 &attr
->mp_nexthop_local
)
6487 && !attr
->mp_nexthop_prefer_global
)
6488 json_object_boolean_true_add(
6492 json_object_boolean_true_add(
6493 json_nexthop_global
,
6496 json_object_boolean_true_add(
6497 json_nexthop_global
, "used");
6499 /* Display LL if LL/Global both in table unless
6500 * prefer-global is set */
6501 if (((attr
->mp_nexthop_len
== 32)
6502 && !attr
->mp_nexthop_prefer_global
)
6503 || (binfo
->peer
->conf_if
)) {
6504 if (binfo
->peer
->conf_if
) {
6507 binfo
->peer
->conf_if
);
6509 7 - len
; /* len of IPv6
6515 vty_out(vty
, "\n%*s",
6518 vty_out(vty
, "%*s", len
,
6525 &attr
->mp_nexthop_local
,
6530 vty_out(vty
, "\n%*s",
6533 vty_out(vty
, "%*s", len
,
6541 &attr
->mp_nexthop_global
,
6546 vty_out(vty
, "\n%*s", 36, " ");
6548 vty_out(vty
, "%*s", len
, " ");
6554 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6556 json_object_int_add(json_path
, "med",
6559 vty_out(vty
, "%10u", attr
->med
);
6560 else if (!json_paths
)
6564 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6566 json_object_int_add(json_path
, "localpref",
6569 vty_out(vty
, "%7u", attr
->local_pref
);
6570 else if (!json_paths
)
6574 json_object_int_add(json_path
, "weight", attr
->weight
);
6576 vty_out(vty
, "%7u ", attr
->weight
);
6580 json_object_string_add(json_path
, "peerId",
6581 sockunion2str(&binfo
->peer
->su
,
6589 json_object_string_add(json_path
, "aspath",
6592 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6597 json_object_string_add(
6598 json_path
, "origin",
6599 bgp_origin_long_str
[attr
->origin
]);
6601 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6604 json_object_string_add(json_path
, "alert",
6607 vty_out(vty
, "No attributes to print\n");
6611 if (json_nexthop_global
|| json_nexthop_ll
) {
6612 json_nexthops
= json_object_new_array();
6614 if (json_nexthop_global
)
6615 json_object_array_add(json_nexthops
,
6616 json_nexthop_global
);
6618 if (json_nexthop_ll
)
6619 json_object_array_add(json_nexthops
,
6622 json_object_object_add(json_path
, "nexthops",
6626 json_object_array_add(json_paths
, json_path
);
6630 /* prints an additional line, indented, with VNC info, if
6632 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6633 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6638 /* called from terminal list command */
6639 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6640 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6642 json_object
*json_status
= NULL
;
6643 json_object
*json_net
= NULL
;
6645 /* Route status display. */
6647 json_status
= json_object_new_object();
6648 json_net
= json_object_new_object();
6655 /* print prefix and mask */
6657 json_object_string_add(
6658 json_net
, "addrPrefix",
6659 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6661 route_vty_out_route(p
, vty
);
6663 /* Print attribute */
6666 if (p
->family
== AF_INET
6667 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6668 || safi
== SAFI_EVPN
6669 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6670 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6671 || safi
== SAFI_EVPN
)
6672 json_object_string_add(
6673 json_net
, "nextHop",
6675 attr
->mp_nexthop_global_in
));
6677 json_object_string_add(
6678 json_net
, "nextHop",
6679 inet_ntoa(attr
->nexthop
));
6680 } else if (p
->family
== AF_INET6
6681 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6684 json_object_string_add(
6685 json_net
, "netHopGloabal",
6687 &attr
->mp_nexthop_global
, buf
,
6692 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6693 json_object_int_add(json_net
, "metric",
6696 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6697 json_object_int_add(json_net
, "localPref",
6700 json_object_int_add(json_net
, "weight", attr
->weight
);
6704 json_object_string_add(json_net
, "asPath",
6708 json_object_string_add(json_net
, "bgpOriginCode",
6709 bgp_origin_str
[attr
->origin
]);
6711 if (p
->family
== AF_INET
6712 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6713 || safi
== SAFI_EVPN
6714 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6715 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6716 || safi
== SAFI_EVPN
)
6717 vty_out(vty
, "%-16s",
6719 attr
->mp_nexthop_global_in
));
6721 vty_out(vty
, "%-16s",
6722 inet_ntoa(attr
->nexthop
));
6723 } else if (p
->family
== AF_INET6
6724 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6731 &attr
->mp_nexthop_global
, buf
,
6735 vty_out(vty
, "\n%*s", 36, " ");
6737 vty_out(vty
, "%*s", len
, " ");
6740 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6741 vty_out(vty
, "%10u", attr
->med
);
6745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6746 vty_out(vty
, "%7u", attr
->local_pref
);
6750 vty_out(vty
, "%7u ", attr
->weight
);
6754 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6757 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6761 json_object_boolean_true_add(json_status
, "*");
6762 json_object_boolean_true_add(json_status
, ">");
6763 json_object_object_add(json_net
, "appliedStatusSymbols",
6765 char buf_cut
[BUFSIZ
];
6766 json_object_object_add(
6768 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6774 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6775 struct bgp_info
*binfo
, int display
, safi_t safi
,
6778 json_object
*json_out
= NULL
;
6780 mpls_label_t label
= MPLS_INVALID_LABEL
;
6786 json_out
= json_object_new_object();
6788 /* short status lead text */
6789 route_vty_short_status_out(vty
, binfo
, json_out
);
6791 /* print prefix and mask */
6794 route_vty_out_route(p
, vty
);
6796 vty_out(vty
, "%*s", 17, " ");
6799 /* Print attribute */
6802 if (((p
->family
== AF_INET
)
6803 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6804 || (safi
== SAFI_EVPN
&& p
->family
== AF_ETHERNET
6805 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6806 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6807 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6808 || safi
== SAFI_EVPN
) {
6810 json_object_string_add(
6811 json_out
, "mpNexthopGlobalIn",
6813 attr
->mp_nexthop_global_in
));
6815 vty_out(vty
, "%-16s",
6817 attr
->mp_nexthop_global_in
));
6820 json_object_string_add(
6821 json_out
, "nexthop",
6822 inet_ntoa(attr
->nexthop
));
6824 vty_out(vty
, "%-16s",
6825 inet_ntoa(attr
->nexthop
));
6827 } else if (((p
->family
== AF_INET6
)
6828 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6829 || (safi
== SAFI_EVPN
&& p
->family
== AF_ETHERNET
6830 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6831 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6835 if (attr
->mp_nexthop_len
6836 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6838 json_object_string_add(
6839 json_out
, "mpNexthopGlobalIn",
6842 &attr
->mp_nexthop_global
,
6848 &attr
->mp_nexthop_global
,
6850 } else if (attr
->mp_nexthop_len
6851 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6854 &attr
->mp_nexthop_global
,
6857 &attr
->mp_nexthop_local
,
6859 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6860 json_object_string_add(
6862 "mpNexthopGlobalLocal", buf_c
);
6864 vty_out(vty
, "%s(%s)",
6867 &attr
->mp_nexthop_global
,
6871 &attr
->mp_nexthop_local
,
6877 label
= decode_label(&binfo
->extra
->label
);
6879 if (bgp_is_valid_label(&label
)) {
6881 json_object_int_add(json_out
, "notag", label
);
6882 json_object_array_add(json
, json_out
);
6884 vty_out(vty
, "notag/%d", label
);
6890 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6891 struct bgp_info
*binfo
, int display
,
6892 json_object
*json_paths
)
6896 json_object
*json_path
= NULL
;
6899 json_path
= json_object_new_object();
6904 /* short status lead text */
6905 route_vty_short_status_out(vty
, binfo
, json_path
);
6907 /* print prefix and mask */
6909 route_vty_out_route(p
, vty
);
6911 vty_out(vty
, "%*s", 17, " ");
6913 /* Print attribute */
6917 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6921 vty_out(vty
, "%-16s",
6922 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6926 vty_out(vty
, "%s(%s)",
6927 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6929 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
6937 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
6938 char *str
= esi2str(id
);
6939 vty_out(vty
, "%s", str
);
6940 XFREE(MTYPE_TMP
, str
);
6941 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
6942 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
6943 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
6945 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
6948 if (attr
->ecommunity
) {
6950 struct ecommunity_val
*routermac
= ecommunity_lookup(
6951 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
6952 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
6954 mac
= ecom_mac2str((char *)routermac
->val
);
6956 vty_out(vty
, "/%s", (char *)mac
);
6957 XFREE(MTYPE_TMP
, mac
);
6963 /* dampening route */
6964 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6965 struct bgp_info
*binfo
, int display
, safi_t safi
,
6966 u_char use_json
, json_object
*json
)
6970 char timebuf
[BGP_UPTIME_LEN
];
6972 /* short status lead text */
6973 route_vty_short_status_out(vty
, binfo
, json
);
6975 /* print prefix and mask */
6978 route_vty_out_route(p
, vty
);
6980 vty_out(vty
, "%*s", 17, " ");
6983 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6987 vty_out(vty
, "\n%*s", 34, " ");
6990 json_object_int_add(json
, "peerHost", len
);
6992 vty_out(vty
, "%*s", len
, " ");
6996 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
6999 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7003 /* Print attribute */
7009 json_object_string_add(json
, "asPath",
7012 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7017 json_object_string_add(json
, "origin",
7018 bgp_origin_str
[attr
->origin
]);
7020 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7027 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7028 struct bgp_info
*binfo
, int display
, safi_t safi
,
7029 u_char use_json
, json_object
*json
)
7032 struct bgp_damp_info
*bdi
;
7033 char timebuf
[BGP_UPTIME_LEN
];
7039 bdi
= binfo
->extra
->damp_info
;
7041 /* short status lead text */
7042 route_vty_short_status_out(vty
, binfo
, json
);
7044 /* print prefix and mask */
7047 route_vty_out_route(p
, vty
);
7049 vty_out(vty
, "%*s", 17, " ");
7052 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7056 vty_out(vty
, "\n%*s", 33, " ");
7059 json_object_int_add(json
, "peerHost", len
);
7061 vty_out(vty
, "%*s", len
, " ");
7064 len
= vty_out(vty
, "%d", bdi
->flap
);
7071 json_object_int_add(json
, "bdiFlap", len
);
7073 vty_out(vty
, "%*s", len
, " ");
7077 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7080 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7081 BGP_UPTIME_LEN
, 0, NULL
));
7083 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7084 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7086 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7087 BGP_UPTIME_LEN
, use_json
, json
);
7090 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7095 vty_out(vty
, "%*s ", 8, " ");
7098 /* Print attribute */
7104 json_object_string_add(json
, "asPath",
7107 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7112 json_object_string_add(json
, "origin",
7113 bgp_origin_str
[attr
->origin
]);
7115 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7121 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7122 int *first
, const char *header
,
7123 json_object
*json_adv_to
)
7125 char buf1
[INET6_ADDRSTRLEN
];
7126 json_object
*json_peer
= NULL
;
7129 /* 'advertised-to' is a dictionary of peers we have advertised
7131 * prefix too. The key is the peer's IP or swpX, the value is
7133 * hostname if we know it and "" if not.
7135 json_peer
= json_object_new_object();
7138 json_object_string_add(json_peer
, "hostname",
7142 json_object_object_add(json_adv_to
, peer
->conf_if
,
7145 json_object_object_add(
7147 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7151 vty_out(vty
, "%s", header
);
7156 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7158 vty_out(vty
, " %s(%s)", peer
->hostname
,
7161 vty_out(vty
, " %s(%s)", peer
->hostname
,
7162 sockunion2str(&peer
->su
, buf1
,
7166 vty_out(vty
, " %s", peer
->conf_if
);
7169 sockunion2str(&peer
->su
, buf1
,
7175 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7176 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7177 json_object
*json_paths
)
7179 char buf
[INET6_ADDRSTRLEN
];
7181 #if defined(HAVE_CUMULUS)
7182 char buf2
[EVPN_ROUTE_STRLEN
];
7185 int sockunion_vty_out(struct vty
*, union sockunion
*);
7187 json_object
*json_bestpath
= NULL
;
7188 json_object
*json_cluster_list
= NULL
;
7189 json_object
*json_cluster_list_list
= NULL
;
7190 json_object
*json_ext_community
= NULL
;
7191 json_object
*json_last_update
= NULL
;
7192 json_object
*json_nexthop_global
= NULL
;
7193 json_object
*json_nexthop_ll
= NULL
;
7194 json_object
*json_nexthops
= NULL
;
7195 json_object
*json_path
= NULL
;
7196 json_object
*json_peer
= NULL
;
7197 json_object
*json_string
= NULL
;
7198 json_object
*json_adv_to
= NULL
;
7200 struct listnode
*node
, *nnode
;
7202 int addpath_capable
;
7204 unsigned int first_as
;
7207 json_path
= json_object_new_object();
7208 json_peer
= json_object_new_object();
7209 json_nexthop_global
= json_object_new_object();
7212 #if defined(HAVE_CUMULUS)
7213 if (!json_paths
&& safi
== SAFI_EVPN
) {
7216 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7217 vty_out(vty
, " Route %s", buf2
);
7220 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7222 vty_out(vty
, " VNI %s", tag_buf
);
7225 if (binfo
->extra
&& binfo
->extra
->parent
) {
7226 struct bgp_info
*parent_ri
;
7227 struct bgp_node
*rn
, *prn
;
7229 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7230 rn
= parent_ri
->net
;
7231 if (rn
&& rn
->prn
) {
7233 vty_out(vty
, " Imported from %s:%s\n",
7235 (struct prefix_rd
*)&prn
->p
,
7236 buf1
, RD_ADDRSTRLEN
),
7246 /* Line1 display AS-path, Aggregator */
7249 json_object_lock(attr
->aspath
->json
);
7250 json_object_object_add(json_path
, "aspath",
7251 attr
->aspath
->json
);
7253 if (attr
->aspath
->segments
)
7254 aspath_print_vty(vty
, " %s",
7257 vty_out(vty
, " Local");
7261 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7263 json_object_boolean_true_add(json_path
,
7266 vty_out(vty
, ", (removed)");
7269 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7271 json_object_boolean_true_add(json_path
,
7274 vty_out(vty
, ", (stale)");
7277 if (CHECK_FLAG(attr
->flag
,
7278 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7280 json_object_int_add(json_path
, "aggregatorAs",
7281 attr
->aggregator_as
);
7282 json_object_string_add(
7283 json_path
, "aggregatorId",
7284 inet_ntoa(attr
->aggregator_addr
));
7286 vty_out(vty
, ", (aggregated by %u %s)",
7287 attr
->aggregator_as
,
7288 inet_ntoa(attr
->aggregator_addr
));
7292 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7293 PEER_FLAG_REFLECTOR_CLIENT
)) {
7295 json_object_boolean_true_add(
7296 json_path
, "rxedFromRrClient");
7298 vty_out(vty
, ", (Received from a RR-client)");
7301 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7302 PEER_FLAG_RSERVER_CLIENT
)) {
7304 json_object_boolean_true_add(
7305 json_path
, "rxedFromRsClient");
7307 vty_out(vty
, ", (Received from a RS-client)");
7310 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7312 json_object_boolean_true_add(
7313 json_path
, "dampeningHistoryEntry");
7315 vty_out(vty
, ", (history entry)");
7316 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7318 json_object_boolean_true_add(
7319 json_path
, "dampeningSuppressed");
7321 vty_out(vty
, ", (suppressed due to dampening)");
7327 /* Line2 display Next-hop, Neighbor, Router-id */
7328 /* Display the nexthop */
7329 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
)
7330 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7331 || safi
== SAFI_EVPN
7332 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7333 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7334 || safi
== SAFI_EVPN
) {
7336 json_object_string_add(
7337 json_nexthop_global
, "ip",
7339 attr
->mp_nexthop_global_in
));
7343 attr
->mp_nexthop_global_in
));
7346 json_object_string_add(
7347 json_nexthop_global
, "ip",
7348 inet_ntoa(attr
->nexthop
));
7351 inet_ntoa(attr
->nexthop
));
7355 json_object_string_add(json_nexthop_global
,
7359 json_object_string_add(
7360 json_nexthop_global
, "ip",
7362 &attr
->mp_nexthop_global
, buf
,
7364 json_object_string_add(json_nexthop_global
,
7366 json_object_string_add(json_nexthop_global
,
7371 &attr
->mp_nexthop_global
, buf
,
7376 /* Display the IGP cost or 'inaccessible' */
7377 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7379 json_object_boolean_false_add(
7380 json_nexthop_global
, "accessible");
7382 vty_out(vty
, " (inaccessible)");
7384 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7386 json_object_int_add(
7387 json_nexthop_global
, "metric",
7388 binfo
->extra
->igpmetric
);
7390 vty_out(vty
, " (metric %u)",
7391 binfo
->extra
->igpmetric
);
7394 /* IGP cost is 0, display this only for json */
7397 json_object_int_add(json_nexthop_global
,
7402 json_object_boolean_true_add(
7403 json_nexthop_global
, "accessible");
7406 /* Display peer "from" output */
7407 /* This path was originated locally */
7408 if (binfo
->peer
== bgp
->peer_self
) {
7410 if (safi
== SAFI_EVPN
7411 || (p
->family
== AF_INET
7412 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7414 json_object_string_add(
7415 json_peer
, "peerId", "0.0.0.0");
7417 vty_out(vty
, " from 0.0.0.0 ");
7420 json_object_string_add(json_peer
,
7423 vty_out(vty
, " from :: ");
7427 json_object_string_add(
7428 json_peer
, "routerId",
7429 inet_ntoa(bgp
->router_id
));
7431 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7434 /* We RXed this path from one of our peers */
7438 json_object_string_add(
7439 json_peer
, "peerId",
7440 sockunion2str(&binfo
->peer
->su
, buf
,
7442 json_object_string_add(
7443 json_peer
, "routerId",
7445 &binfo
->peer
->remote_id
, buf1
,
7448 if (binfo
->peer
->hostname
)
7449 json_object_string_add(
7450 json_peer
, "hostname",
7451 binfo
->peer
->hostname
);
7453 if (binfo
->peer
->domainname
)
7454 json_object_string_add(
7455 json_peer
, "domainname",
7456 binfo
->peer
->domainname
);
7458 if (binfo
->peer
->conf_if
)
7459 json_object_string_add(
7460 json_peer
, "interface",
7461 binfo
->peer
->conf_if
);
7463 if (binfo
->peer
->conf_if
) {
7464 if (binfo
->peer
->hostname
7467 BGP_FLAG_SHOW_HOSTNAME
))
7468 vty_out(vty
, " from %s(%s)",
7469 binfo
->peer
->hostname
,
7470 binfo
->peer
->conf_if
);
7472 vty_out(vty
, " from %s",
7473 binfo
->peer
->conf_if
);
7475 if (binfo
->peer
->hostname
7478 BGP_FLAG_SHOW_HOSTNAME
))
7479 vty_out(vty
, " from %s(%s)",
7480 binfo
->peer
->hostname
,
7483 vty_out(vty
, " from %s",
7492 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7493 vty_out(vty
, " (%s)",
7494 inet_ntoa(attr
->originator_id
));
7496 vty_out(vty
, " (%s)",
7499 &binfo
->peer
->remote_id
,
7507 /* display the link-local nexthop */
7508 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7510 json_nexthop_ll
= json_object_new_object();
7511 json_object_string_add(
7512 json_nexthop_ll
, "ip",
7514 &attr
->mp_nexthop_local
, buf
,
7516 json_object_string_add(json_nexthop_ll
, "afi",
7518 json_object_string_add(json_nexthop_ll
, "scope",
7521 json_object_boolean_true_add(json_nexthop_ll
,
7524 if (!attr
->mp_nexthop_prefer_global
)
7525 json_object_boolean_true_add(
7526 json_nexthop_ll
, "used");
7528 json_object_boolean_true_add(
7529 json_nexthop_global
, "used");
7531 vty_out(vty
, " (%s) %s\n",
7533 &attr
->mp_nexthop_local
, buf
,
7535 attr
->mp_nexthop_prefer_global
7540 /* If we do not have a link-local nexthop then we must flag the
7544 json_object_boolean_true_add(
7545 json_nexthop_global
, "used");
7548 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7549 * Int/Ext/Local, Atomic, best */
7551 json_object_string_add(
7552 json_path
, "origin",
7553 bgp_origin_long_str
[attr
->origin
]);
7555 vty_out(vty
, " Origin %s",
7556 bgp_origin_long_str
[attr
->origin
]);
7558 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7560 json_object_int_add(json_path
, "med",
7563 vty_out(vty
, ", metric %u", attr
->med
);
7566 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7568 json_object_int_add(json_path
, "localpref",
7571 vty_out(vty
, ", localpref %u",
7575 json_object_int_add(json_path
, "localpref",
7576 bgp
->default_local_pref
);
7578 vty_out(vty
, ", localpref %u",
7579 bgp
->default_local_pref
);
7582 if (attr
->weight
!= 0) {
7584 json_object_int_add(json_path
, "weight",
7587 vty_out(vty
, ", weight %u", attr
->weight
);
7590 if (attr
->tag
!= 0) {
7592 json_object_int_add(json_path
, "tag",
7595 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7599 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7601 json_object_boolean_false_add(json_path
,
7604 vty_out(vty
, ", invalid");
7605 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7607 json_object_boolean_true_add(json_path
,
7610 vty_out(vty
, ", valid");
7613 if (binfo
->peer
!= bgp
->peer_self
) {
7614 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7615 if (CHECK_FLAG(bgp
->config
,
7616 BGP_CONFIG_CONFEDERATION
)) {
7618 json_object_string_add(
7623 ", confed-internal");
7626 json_object_string_add(
7630 vty_out(vty
, ", internal");
7633 if (bgp_confederation_peers_check(
7634 bgp
, binfo
->peer
->as
)) {
7636 json_object_string_add(
7641 ", confed-external");
7644 json_object_string_add(
7648 vty_out(vty
, ", external");
7651 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7653 json_object_boolean_true_add(json_path
,
7655 json_object_boolean_true_add(json_path
,
7658 vty_out(vty
, ", aggregated, local");
7660 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7662 json_object_boolean_true_add(json_path
,
7665 vty_out(vty
, ", sourced");
7668 json_object_boolean_true_add(json_path
,
7670 json_object_boolean_true_add(json_path
,
7673 vty_out(vty
, ", sourced, local");
7677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7679 json_object_boolean_true_add(json_path
,
7682 vty_out(vty
, ", atomic-aggregate");
7685 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7686 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7687 && bgp_info_mpath_count(binfo
))) {
7689 json_object_boolean_true_add(json_path
,
7692 vty_out(vty
, ", multipath");
7695 // Mark the bestpath(s)
7696 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7697 first_as
= aspath_get_first_as(attr
->aspath
);
7702 json_object_new_object();
7703 json_object_int_add(json_bestpath
,
7704 "bestpathFromAs", first_as
);
7707 vty_out(vty
, ", bestpath-from-AS %d",
7711 ", bestpath-from-AS Local");
7715 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7719 json_object_new_object();
7720 json_object_boolean_true_add(json_bestpath
,
7723 vty_out(vty
, ", best");
7727 json_object_object_add(json_path
, "bestpath",
7733 /* Line 4 display Community */
7734 if (attr
->community
) {
7736 json_object_lock(attr
->community
->json
);
7737 json_object_object_add(json_path
, "community",
7738 attr
->community
->json
);
7740 vty_out(vty
, " Community: %s\n",
7741 attr
->community
->str
);
7745 /* Line 5 display Extended-community */
7746 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7748 json_ext_community
= json_object_new_object();
7749 json_object_string_add(json_ext_community
,
7751 attr
->ecommunity
->str
);
7752 json_object_object_add(json_path
,
7753 "extendedCommunity",
7754 json_ext_community
);
7756 vty_out(vty
, " Extended Community: %s\n",
7757 attr
->ecommunity
->str
);
7761 /* Line 6 display Large community */
7762 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))
7763 vty_out(vty
, " Large Community: %s\n",
7764 attr
->lcommunity
->str
);
7766 /* Line 7 display Originator, Cluster-id */
7767 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7768 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7770 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7772 json_object_string_add(
7773 json_path
, "originatorId",
7774 inet_ntoa(attr
->originator_id
));
7776 vty_out(vty
, " Originator: %s",
7777 inet_ntoa(attr
->originator_id
));
7780 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7785 json_object_new_object();
7786 json_cluster_list_list
=
7787 json_object_new_array();
7790 i
< attr
->cluster
->length
/ 4;
7792 json_string
= json_object_new_string(
7796 json_object_array_add(
7797 json_cluster_list_list
,
7801 /* struct cluster_list does not have
7803 * aspath and community do. Add this
7806 json_object_string_add(json_cluster_list,
7807 "string", attr->cluster->str);
7809 json_object_object_add(
7810 json_cluster_list
, "list",
7811 json_cluster_list_list
);
7812 json_object_object_add(
7813 json_path
, "clusterList",
7816 vty_out(vty
, ", Cluster list: ");
7819 i
< attr
->cluster
->length
/ 4;
7833 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7834 bgp_damp_info_vty(vty
, binfo
, json_path
);
7837 #if defined(HAVE_CUMULUS)
7838 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7839 && safi
!= SAFI_EVPN
)
7841 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
7844 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
7846 json_object_int_add(json_path
, "remoteLabel",
7849 vty_out(vty
, " Remote label: %d\n", label
);
7853 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7855 json_object_int_add(json_path
, "labelIndex",
7858 vty_out(vty
, " Label Index: %d\n",
7862 /* Line 8 display Addpath IDs */
7863 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7865 json_object_int_add(json_path
, "addpathRxId",
7866 binfo
->addpath_rx_id
);
7867 json_object_int_add(json_path
, "addpathTxId",
7868 binfo
->addpath_tx_id
);
7870 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7871 binfo
->addpath_rx_id
,
7872 binfo
->addpath_tx_id
);
7876 /* If we used addpath to TX a non-bestpath we need to display
7877 * "Advertised to" on a path-by-path basis */
7878 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7881 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7883 bgp_addpath_encode_tx(peer
, afi
, safi
);
7884 has_adj
= bgp_adj_out_lookup(
7885 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7887 if ((addpath_capable
&& has_adj
)
7888 || (!addpath_capable
&& has_adj
7889 && CHECK_FLAG(binfo
->flags
,
7890 BGP_INFO_SELECTED
))) {
7891 if (json_path
&& !json_adv_to
)
7893 json_object_new_object();
7895 route_vty_out_advertised_to(
7904 json_object_object_add(json_path
,
7915 /* Line 9 display Uptime */
7916 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
7918 json_last_update
= json_object_new_object();
7919 json_object_int_add(json_last_update
, "epoch", tbuf
);
7920 json_object_string_add(json_last_update
, "string",
7922 json_object_object_add(json_path
, "lastUpdate",
7925 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
7928 /* We've constructed the json object for this path, add it to the json
7932 if (json_nexthop_global
|| json_nexthop_ll
) {
7933 json_nexthops
= json_object_new_array();
7935 if (json_nexthop_global
)
7936 json_object_array_add(json_nexthops
,
7937 json_nexthop_global
);
7939 if (json_nexthop_ll
)
7940 json_object_array_add(json_nexthops
,
7943 json_object_object_add(json_path
, "nexthops",
7947 json_object_object_add(json_path
, "peer", json_peer
);
7948 json_object_array_add(json_paths
, json_path
);
7953 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7954 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7955 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
7957 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
7958 const char *prefix_list_str
, afi_t afi
,
7959 safi_t safi
, enum bgp_show_type type
);
7960 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
7961 const char *filter
, afi_t afi
, safi_t safi
,
7962 enum bgp_show_type type
);
7963 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
7964 const char *rmap_str
, afi_t afi
, safi_t safi
,
7965 enum bgp_show_type type
);
7966 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
7967 const char *com
, int exact
, afi_t afi
,
7969 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
7970 const char *prefix
, afi_t afi
, safi_t safi
,
7971 enum bgp_show_type type
);
7972 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
7973 safi_t safi
, enum bgp_show_type type
);
7974 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
7975 struct cmd_token
**argv
, int exact
, afi_t afi
,
7978 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
,
7979 struct bgp_table
*table
, enum bgp_show_type type
,
7980 void *output_arg
, u_char use_json
)
7982 struct bgp_info
*ri
;
7983 struct bgp_node
*rn
;
7986 unsigned long output_count
;
7987 unsigned long total_count
;
7991 json_object
*json_paths
= NULL
;
7996 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
7997 ", \"routerId\": \"%s\", \"routes\": { ",
7998 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
7999 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8001 table
->version
, inet_ntoa(bgp
->router_id
));
8002 json_paths
= json_object_new_object();
8005 /* This is first entry point, so reset total line. */
8009 /* Start processing of routes. */
8010 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
8011 if (rn
->info
!= NULL
) {
8013 if (!first
&& use_json
) {
8017 json_paths
= json_object_new_array();
8021 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8023 if (type
== bgp_show_type_flap_statistics
8024 || type
== bgp_show_type_flap_neighbor
8025 || type
== bgp_show_type_dampend_paths
8026 || type
== bgp_show_type_damp_neighbor
) {
8028 && ri
->extra
->damp_info
))
8031 if (type
== bgp_show_type_regexp
) {
8032 regex_t
*regex
= output_arg
;
8034 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8038 if (type
== bgp_show_type_prefix_list
) {
8039 struct prefix_list
*plist
= output_arg
;
8041 if (prefix_list_apply(plist
, &rn
->p
)
8045 if (type
== bgp_show_type_filter_list
) {
8046 struct as_list
*as_list
= output_arg
;
8048 if (as_list_apply(as_list
,
8050 != AS_FILTER_PERMIT
)
8053 if (type
== bgp_show_type_route_map
) {
8054 struct route_map
*rmap
= output_arg
;
8055 struct bgp_info binfo
;
8056 struct attr dummy_attr
;
8059 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8061 binfo
.peer
= ri
->peer
;
8062 binfo
.attr
= &dummy_attr
;
8064 ret
= route_map_apply(rmap
, &rn
->p
,
8066 if (ret
== RMAP_DENYMATCH
)
8069 if (type
== bgp_show_type_neighbor
8070 || type
== bgp_show_type_flap_neighbor
8071 || type
== bgp_show_type_damp_neighbor
) {
8072 union sockunion
*su
= output_arg
;
8074 if (ri
->peer
== NULL
8075 || ri
->peer
->su_remote
== NULL
8077 ri
->peer
->su_remote
, su
))
8080 if (type
== bgp_show_type_cidr_only
) {
8081 u_int32_t destination
;
8084 ntohl(rn
->p
.u
.prefix4
.s_addr
);
8085 if (IN_CLASSC(destination
)
8086 && rn
->p
.prefixlen
== 24)
8088 if (IN_CLASSB(destination
)
8089 && rn
->p
.prefixlen
== 16)
8091 if (IN_CLASSA(destination
)
8092 && rn
->p
.prefixlen
== 8)
8095 if (type
== bgp_show_type_prefix_longer
) {
8096 struct prefix
*p
= output_arg
;
8098 if (!prefix_match(p
, &rn
->p
))
8101 if (type
== bgp_show_type_community_all
) {
8102 if (!ri
->attr
->community
)
8105 if (type
== bgp_show_type_community
) {
8106 struct community
*com
= output_arg
;
8108 if (!ri
->attr
->community
8109 || !community_match(
8110 ri
->attr
->community
,
8114 if (type
== bgp_show_type_community_exact
) {
8115 struct community
*com
= output_arg
;
8117 if (!ri
->attr
->community
8119 ri
->attr
->community
,
8123 if (type
== bgp_show_type_community_list
) {
8124 struct community_list
*list
=
8127 if (!community_list_match(
8128 ri
->attr
->community
, list
))
8132 == bgp_show_type_community_list_exact
) {
8133 struct community_list
*list
=
8136 if (!community_list_exact_match(
8137 ri
->attr
->community
, list
))
8140 if (type
== bgp_show_type_lcommunity
) {
8141 struct lcommunity
*lcom
= output_arg
;
8143 if (!ri
->attr
->lcommunity
8144 || !lcommunity_match(
8145 ri
->attr
->lcommunity
,
8149 if (type
== bgp_show_type_lcommunity_list
) {
8150 struct community_list
*list
=
8153 if (!lcommunity_list_match(
8154 ri
->attr
->lcommunity
, list
))
8157 if (type
== bgp_show_type_lcommunity_all
) {
8158 if (!ri
->attr
->lcommunity
)
8161 if (type
== bgp_show_type_dampend_paths
8162 || type
== bgp_show_type_damp_neighbor
) {
8163 if (!CHECK_FLAG(ri
->flags
,
8165 || CHECK_FLAG(ri
->flags
,
8170 if (!use_json
&& header
) {
8172 "BGP table version is %" PRIu64
8173 ", local router ID is %s\n",
8175 inet_ntoa(bgp
->router_id
));
8176 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8177 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8178 if (type
== bgp_show_type_dampend_paths
8179 || type
== bgp_show_type_damp_neighbor
)
8181 BGP_SHOW_DAMP_HEADER
);
8183 type
== bgp_show_type_flap_statistics
8184 || type
== bgp_show_type_flap_neighbor
)
8186 BGP_SHOW_FLAP_HEADER
);
8188 vty_out(vty
, BGP_SHOW_HEADER
);
8192 if (type
== bgp_show_type_dampend_paths
8193 || type
== bgp_show_type_damp_neighbor
)
8195 vty
, &rn
->p
, ri
, display
,
8196 SAFI_UNICAST
, use_json
,
8198 else if (type
== bgp_show_type_flap_statistics
8199 || type
== bgp_show_type_flap_neighbor
)
8201 vty
, &rn
->p
, ri
, display
,
8202 SAFI_UNICAST
, use_json
,
8205 route_vty_out(vty
, &rn
->p
, ri
, display
,
8206 SAFI_UNICAST
, json_paths
);
8214 sprintf(buf2
, "%s/%d",
8215 inet_ntop(p
->family
,
8219 vty_out(vty
, "\"%s\": ", buf2
);
8221 json_object_to_json_string(
8223 json_object_free(json_paths
);
8230 json_object_free(json_paths
);
8231 vty_out(vty
, " } }\n");
8233 /* No route is displayed */
8234 if (output_count
== 0) {
8235 if (type
== bgp_show_type_normal
)
8237 "No BGP prefixes displayed, %ld exist\n",
8241 "\nDisplayed %ld routes and %ld total paths\n",
8242 output_count
, total_count
);
8248 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8249 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8251 struct bgp_table
*table
;
8254 bgp
= bgp_get_default();
8259 vty_out(vty
, "No BGP process is configured\n");
8263 /* use MPLS and ENCAP specific shows until they are merged */
8264 if (safi
== SAFI_MPLS_VPN
) {
8265 return bgp_show_mpls_vpn(vty
, afi
, NULL
, type
, output_arg
, 0,
8268 /* labeled-unicast routes live in the unicast table */
8269 else if (safi
== SAFI_LABELED_UNICAST
)
8270 safi
= SAFI_UNICAST
;
8272 table
= bgp
->rib
[afi
][safi
];
8274 return bgp_show_table(vty
, bgp
, table
, type
, output_arg
, use_json
);
8277 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8278 safi_t safi
, u_char use_json
)
8280 struct listnode
*node
, *nnode
;
8285 vty_out(vty
, "{\n");
8287 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8290 vty_out(vty
, ",\n");
8294 vty_out(vty
, "\"%s\":",
8295 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8299 vty_out(vty
, "\nInstance %s:\n",
8300 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8304 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8309 vty_out(vty
, "}\n");
8312 /* Header of detailed BGP route information */
8313 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8314 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8315 afi_t afi
, safi_t safi
, json_object
*json
)
8317 struct bgp_info
*ri
;
8320 struct listnode
*node
, *nnode
;
8321 char buf1
[INET6_ADDRSTRLEN
];
8322 char buf2
[INET6_ADDRSTRLEN
];
8323 #if defined(HAVE_CUMULUS)
8324 char buf3
[EVPN_ROUTE_STRLEN
];
8330 int no_advertise
= 0;
8333 int has_valid_label
= 0;
8334 mpls_label_t label
= 0;
8335 json_object
*json_adv_to
= NULL
;
8338 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8340 if (has_valid_label
)
8341 label
= label_pton(&rn
->local_label
);
8344 if (has_valid_label
)
8345 json_object_int_add(json
, "localLabel", label
);
8347 json_object_string_add(json
, "prefix",
8348 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8350 json_object_int_add(json
, "prefixlen", p
->prefixlen
);
8352 #if defined(HAVE_CUMULUS)
8353 if (safi
== SAFI_EVPN
)
8354 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8355 prd
? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8358 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8359 buf3
, sizeof(buf3
)));
8361 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8362 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8363 ? prefix_rd2str(prd
, buf1
,
8366 safi
== SAFI_MPLS_VPN
? ":" : "",
8367 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8371 if (p
->family
== AF_ETHERNET
)
8372 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8374 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8376 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8377 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8378 || safi
== SAFI_EVPN
)
8379 ? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8381 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8383 buf2
, p
->prefixlen
);
8386 if (has_valid_label
)
8387 vty_out(vty
, "Local label: %d\n", label
);
8388 #if defined(HAVE_CUMULUS)
8389 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8391 if (bgp_labeled_safi(safi
))
8393 vty_out(vty
, "not allocated\n");
8396 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8398 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8400 if (ri
->extra
&& ri
->extra
->suppress
)
8402 if (ri
->attr
->community
!= NULL
) {
8403 if (community_include(ri
->attr
->community
,
8404 COMMUNITY_NO_ADVERTISE
))
8406 if (community_include(ri
->attr
->community
,
8407 COMMUNITY_NO_EXPORT
))
8409 if (community_include(ri
->attr
->community
,
8410 COMMUNITY_LOCAL_AS
))
8417 vty_out(vty
, "Paths: (%d available", count
);
8419 vty_out(vty
, ", best #%d", best
);
8420 if (safi
== SAFI_UNICAST
)
8421 vty_out(vty
, ", table %s",
8423 == BGP_INSTANCE_TYPE_DEFAULT
)
8424 ? "Default-IP-Routing-Table"
8427 vty_out(vty
, ", no best path");
8430 vty_out(vty
, ", not advertised to any peer");
8432 vty_out(vty
, ", not advertised to EBGP peer");
8434 vty_out(vty
, ", not advertised outside local AS");
8438 ", Advertisements suppressed by an aggregate.");
8439 vty_out(vty
, ")\n");
8442 /* If we are not using addpath then we can display Advertised to and
8444 * show what peers we advertised the bestpath to. If we are using
8446 * though then we must display Advertised to on a path-by-path basis. */
8447 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8448 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8449 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8450 if (json
&& !json_adv_to
)
8451 json_adv_to
= json_object_new_object();
8453 route_vty_out_advertised_to(
8455 " Advertised to non peer-group peers:\n ",
8462 json_object_object_add(json
, "advertisedTo",
8467 vty_out(vty
, " Not advertised to any peer");
8473 /* Display specified route of BGP table. */
8474 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8475 struct bgp_table
*rib
, const char *ip_str
,
8476 afi_t afi
, safi_t safi
,
8477 struct prefix_rd
*prd
, int prefix_check
,
8478 enum bgp_path_type pathtype
, u_char use_json
)
8483 struct prefix match
;
8484 struct bgp_node
*rn
;
8485 struct bgp_node
*rm
;
8486 struct bgp_info
*ri
;
8487 struct bgp_table
*table
;
8488 json_object
*json
= NULL
;
8489 json_object
*json_paths
= NULL
;
8491 /* Check IP address argument. */
8492 ret
= str2prefix(ip_str
, &match
);
8494 vty_out(vty
, "address is malformed\n");
8498 match
.family
= afi2family(afi
);
8501 json
= json_object_new_object();
8502 json_paths
= json_object_new_array();
8505 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8506 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8507 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8510 if ((table
= rn
->info
) != NULL
) {
8513 if ((rm
= bgp_node_match(table
, &match
))
8517 != match
.prefixlen
) {
8518 bgp_unlock_node(rm
);
8522 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8524 route_vty_out_detail_header(
8535 if (pathtype
== BGP_PATH_ALL
8537 == BGP_PATH_BESTPATH
8542 == BGP_PATH_MULTIPATH
8548 BGP_INFO_SELECTED
))))
8549 route_vty_out_detail(
8556 bgp_unlock_node(rm
);
8563 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8565 || rn
->p
.prefixlen
== match
.prefixlen
) {
8566 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8568 route_vty_out_detail_header(
8569 vty
, bgp
, rn
, NULL
, afi
,
8575 if (pathtype
== BGP_PATH_ALL
8576 || (pathtype
== BGP_PATH_BESTPATH
8580 || (pathtype
== BGP_PATH_MULTIPATH
8586 BGP_INFO_SELECTED
))))
8587 route_vty_out_detail(
8588 vty
, bgp
, &rn
->p
, ri
,
8589 afi
, safi
, json_paths
);
8593 bgp_unlock_node(rn
);
8599 json_object_object_add(json
, "paths", json_paths
);
8601 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8602 json
, JSON_C_TO_STRING_PRETTY
));
8603 json_object_free(json
);
8606 vty_out(vty
, "%% Network not in table\n");
8614 /* Display specified route of Main RIB */
8615 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8616 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8617 int prefix_check
, enum bgp_path_type pathtype
,
8621 bgp
= bgp_get_default();
8623 /* labeled-unicast routes live in the unicast table */
8624 if (safi
== SAFI_LABELED_UNICAST
)
8625 safi
= SAFI_UNICAST
;
8627 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8628 afi
, safi
, prd
, prefix_check
, pathtype
,
8632 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8633 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8636 struct lcommunity
*lcom
;
8642 b
= buffer_new(1024);
8643 for (i
= 0; i
< argc
; i
++) {
8645 buffer_putc(b
, ' ');
8647 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8649 buffer_putstr(b
, argv
[i
]->arg
);
8653 buffer_putc(b
, '\0');
8655 str
= buffer_getstr(b
);
8658 lcom
= lcommunity_str2com(str
);
8659 XFREE(MTYPE_TMP
, str
);
8661 vty_out(vty
, "%% Large-community malformed\n");
8665 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8669 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8670 const char *lcom
, afi_t afi
, safi_t safi
,
8673 struct community_list
*list
;
8675 list
= community_list_lookup(bgp_clist
, lcom
,
8676 LARGE_COMMUNITY_LIST_MASTER
);
8678 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8683 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8687 DEFUN (show_ip_bgp_large_community_list
,
8688 show_ip_bgp_large_community_list_cmd
,
8689 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8693 BGP_INSTANCE_HELP_STR
8695 BGP_SAFI_WITH_LABEL_HELP_STR
8696 "Display routes matching the large-community-list\n"
8697 "large-community-list number\n"
8698 "large-community-list name\n"
8702 afi_t afi
= AFI_IP6
;
8703 safi_t safi
= SAFI_UNICAST
;
8706 if (argv_find(argv
, argc
, "ip", &idx
))
8708 if (argv_find(argv
, argc
, "view", &idx
)
8709 || argv_find(argv
, argc
, "vrf", &idx
))
8710 vrf
= argv
[++idx
]->arg
;
8711 if (argv_find(argv
, argc
, "ipv4", &idx
)
8712 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8713 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8714 if (argv_find(argv
, argc
, "unicast", &idx
)
8715 || argv_find(argv
, argc
, "multicast", &idx
))
8716 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8719 int uj
= use_json(argc
, argv
);
8721 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8723 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8727 argv_find(argv
, argc
, "large-community-list", &idx
);
8728 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8731 DEFUN (show_ip_bgp_large_community
,
8732 show_ip_bgp_large_community_cmd
,
8733 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8737 BGP_INSTANCE_HELP_STR
8739 BGP_SAFI_WITH_LABEL_HELP_STR
8740 "Display routes matching the large-communities\n"
8741 "List of large-community numbers\n"
8745 afi_t afi
= AFI_IP6
;
8746 safi_t safi
= SAFI_UNICAST
;
8749 if (argv_find(argv
, argc
, "ip", &idx
))
8751 if (argv_find(argv
, argc
, "view", &idx
)
8752 || argv_find(argv
, argc
, "vrf", &idx
))
8753 vrf
= argv
[++idx
]->arg
;
8754 if (argv_find(argv
, argc
, "ipv4", &idx
)
8755 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8756 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8757 if (argv_find(argv
, argc
, "unicast", &idx
)
8758 || argv_find(argv
, argc
, "multicast", &idx
))
8759 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8762 int uj
= use_json(argc
, argv
);
8764 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8766 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8770 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8771 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8773 return bgp_show(vty
, bgp
, afi
, safi
,
8774 bgp_show_type_lcommunity_all
, NULL
, uj
);
8777 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8780 /* BGP route print out function. */
8783 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8786 |dampening <flap-statistics|dampened-paths|parameters>\
8791 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
8792 |community-list <(1-500)|WORD> [exact-match]\
8793 |A.B.C.D/M longer-prefixes\
8794 |X:X::X:X/M longer-prefixes>\
8799 BGP_INSTANCE_HELP_STR
8801 BGP_SAFI_WITH_LABEL_HELP_STR
8802 "Display only routes with non-natural netmasks\n"
8803 "Display detailed information about dampening\n"
8804 "Display flap statistics of routes\n"
8805 "Display paths suppressed due to dampening\n"
8806 "Display detail of configured dampening parameters\n"
8807 "Display routes matching the route-map\n"
8808 "A route-map to match on\n"
8809 "Display routes conforming to the prefix-list\n"
8810 "Prefix-list name\n"
8811 "Display routes conforming to the filter-list\n"
8812 "Regular expression access list name\n"
8813 "BGP RIB advertisement statistics\n"
8814 "Display routes matching the communities\n"
8816 "Do not send outside local AS (well-known community)\n"
8817 "Do not advertise to any peer (well-known community)\n"
8818 "Do not export to next AS (well-known community)\n"
8819 "Exact match of the communities\n"
8820 "Display routes matching the community-list\n"
8821 "community-list number\n"
8822 "community-list name\n"
8823 "Exact match of the communities\n"
8825 "Display route and more specific routes\n"
8827 "Display route and more specific routes\n"
8830 afi_t afi
= AFI_IP6
;
8831 safi_t safi
= SAFI_UNICAST
;
8832 int exact_match
= 0;
8833 enum bgp_show_type sh_type
= bgp_show_type_normal
;
8834 struct bgp
*bgp
= NULL
;
8837 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8842 int uj
= use_json(argc
, argv
);
8846 if (argv_find(argv
, argc
, "cidr-only", &idx
))
8847 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
8850 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8851 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
8852 return bgp_show(vty
, bgp
, afi
, safi
,
8853 bgp_show_type_dampend_paths
, NULL
, uj
);
8854 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
8855 return bgp_show(vty
, bgp
, afi
, safi
,
8856 bgp_show_type_flap_statistics
, NULL
,
8858 else if (argv_find(argv
, argc
, "parameters", &idx
))
8859 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8862 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8863 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8864 safi
, bgp_show_type_prefix_list
);
8866 if (argv_find(argv
, argc
, "filter-list", &idx
))
8867 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8868 safi
, bgp_show_type_filter_list
);
8870 if (argv_find(argv
, argc
, "statistics", &idx
))
8871 return bgp_table_stats(vty
, bgp
, afi
, safi
);
8873 if (argv_find(argv
, argc
, "route-map", &idx
))
8874 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8875 safi
, bgp_show_type_route_map
);
8877 if (argv_find(argv
, argc
, "community", &idx
)) {
8878 /* show a specific community */
8879 if (argv_find(argv
, argc
, "local-AS", &idx
)
8880 || argv_find(argv
, argc
, "no-advertise", &idx
)
8881 || argv_find(argv
, argc
, "no-export", &idx
)) {
8882 if (argv_find(argv
, argc
, "exact_match", &idx
))
8884 return bgp_show_community(vty
, bgp
, argc
, argv
,
8885 exact_match
, afi
, safi
);
8887 /* show all communities */
8889 return bgp_show(vty
, bgp
, afi
, safi
,
8890 bgp_show_type_community_all
, NULL
, uj
);
8893 if (argv_find(argv
, argc
, "community-list", &idx
)) {
8894 const char *clist_number_or_name
= argv
[++idx
]->arg
;
8895 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
8897 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
8898 exact_match
, afi
, safi
);
8901 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8902 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8903 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
8905 bgp_show_type_prefix_longer
);
8907 if (safi
== SAFI_MPLS_VPN
)
8908 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
8911 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
8914 DEFUN (show_ip_bgp_route
,
8915 show_ip_bgp_route_cmd
,
8916 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
8917 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
8921 BGP_INSTANCE_HELP_STR
8923 BGP_SAFI_WITH_LABEL_HELP_STR
8924 "Network in the BGP routing table to display\n"
8926 "Network in the BGP routing table to display\n"
8928 "Display only the bestpath\n"
8929 "Display only multipaths\n"
8932 int prefix_check
= 0;
8934 afi_t afi
= AFI_IP6
;
8935 safi_t safi
= SAFI_UNICAST
;
8936 char *prefix
= NULL
;
8937 struct bgp
*bgp
= NULL
;
8938 enum bgp_path_type path_type
;
8939 u_char uj
= use_json(argc
, argv
);
8943 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8950 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8954 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8955 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
8956 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
8958 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8959 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8962 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
8963 && afi
!= AFI_IP6
) {
8965 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
8968 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
8971 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
8975 prefix
= argv
[idx
]->arg
;
8977 /* [<bestpath|multipath>] */
8978 if (argv_find(argv
, argc
, "bestpath", &idx
))
8979 path_type
= BGP_PATH_BESTPATH
;
8980 else if (argv_find(argv
, argc
, "multipath", &idx
))
8981 path_type
= BGP_PATH_MULTIPATH
;
8983 path_type
= BGP_PATH_ALL
;
8985 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
8989 DEFUN (show_ip_bgp_regexp
,
8990 show_ip_bgp_regexp_cmd
,
8991 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
8995 BGP_INSTANCE_HELP_STR
8997 BGP_SAFI_WITH_LABEL_HELP_STR
8998 "Display routes matching the AS path regular expression\n"
8999 "A regular-expression to match the BGP AS paths\n")
9001 afi_t afi
= AFI_IP6
;
9002 safi_t safi
= SAFI_UNICAST
;
9003 struct bgp
*bgp
= NULL
;
9006 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9011 // get index of regex
9012 argv_find(argv
, argc
, "regexp", &idx
);
9015 char *regstr
= argv_concat(argv
, argc
, idx
);
9016 int rc
= bgp_show_regexp(vty
, (const char *)regstr
, afi
, safi
,
9017 bgp_show_type_regexp
);
9018 XFREE(MTYPE_TMP
, regstr
);
9022 DEFUN (show_ip_bgp_instance_all
,
9023 show_ip_bgp_instance_all_cmd
,
9024 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9028 BGP_INSTANCE_ALL_HELP_STR
9030 BGP_SAFI_WITH_LABEL_HELP_STR
9034 safi_t safi
= SAFI_UNICAST
;
9035 struct bgp
*bgp
= NULL
;
9038 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9043 int uj
= use_json(argc
, argv
);
9047 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9051 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
9052 safi_t safi
, enum bgp_show_type type
)
9057 regex
= bgp_regcomp(regstr
);
9059 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9063 rc
= bgp_show(vty
, NULL
, afi
, safi
, type
, regex
, 0);
9064 bgp_regex_free(regex
);
9068 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9069 const char *prefix_list_str
, afi_t afi
,
9070 safi_t safi
, enum bgp_show_type type
)
9072 struct prefix_list
*plist
;
9074 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9075 if (plist
== NULL
) {
9076 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9081 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9084 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9085 const char *filter
, afi_t afi
, safi_t safi
,
9086 enum bgp_show_type type
)
9088 struct as_list
*as_list
;
9090 as_list
= as_list_lookup(filter
);
9091 if (as_list
== NULL
) {
9092 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9097 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9100 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9101 const char *rmap_str
, afi_t afi
, safi_t safi
,
9102 enum bgp_show_type type
)
9104 struct route_map
*rmap
;
9106 rmap
= route_map_lookup_by_name(rmap_str
);
9108 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9112 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9115 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9116 struct cmd_token
**argv
, int exact
, afi_t afi
,
9119 struct community
*com
;
9126 b
= buffer_new(1024);
9127 for (i
= 0; i
< argc
; i
++) {
9129 buffer_putc(b
, ' ');
9131 if (strmatch(argv
[i
]->text
, "unicast")
9132 || strmatch(argv
[i
]->text
, "multicast"))
9137 buffer_putstr(b
, argv
[i
]->arg
);
9139 buffer_putc(b
, '\0');
9141 str
= buffer_getstr(b
);
9144 com
= community_str2com(str
);
9145 XFREE(MTYPE_TMP
, str
);
9147 vty_out(vty
, "%% Community malformed: \n");
9151 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9152 (exact
? bgp_show_type_community_exact
9153 : bgp_show_type_community
),
9155 community_free(com
);
9160 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9161 const char *com
, int exact
, afi_t afi
,
9164 struct community_list
*list
;
9166 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9168 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9172 return bgp_show(vty
, bgp
, afi
, safi
,
9173 (exact
? bgp_show_type_community_list_exact
9174 : bgp_show_type_community_list
),
9178 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9179 const char *prefix
, afi_t afi
, safi_t safi
,
9180 enum bgp_show_type type
)
9187 ret
= str2prefix(prefix
, p
);
9189 vty_out(vty
, "%% Malformed Prefix\n");
9193 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9198 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9199 const char *ip_str
, u_char use_json
)
9205 /* Get peer sockunion. */
9206 ret
= str2sockunion(ip_str
, &su
);
9208 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9210 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9214 json_object
*json_no
= NULL
;
9215 json_no
= json_object_new_object();
9216 json_object_string_add(
9218 "malformedAddressOrName",
9220 vty_out(vty
, "%s\n",
9221 json_object_to_json_string(
9223 json_object_free(json_no
);
9226 "%% Malformed address or name: %s\n",
9234 /* Peer structure lookup. */
9235 peer
= peer_lookup(bgp
, &su
);
9238 json_object
*json_no
= NULL
;
9239 json_no
= json_object_new_object();
9240 json_object_string_add(json_no
, "warning",
9241 "No such neighbor");
9242 vty_out(vty
, "%s\n",
9243 json_object_to_json_string(json_no
));
9244 json_object_free(json_no
);
9246 vty_out(vty
, "No such neighbor\n");
9254 BGP_STATS_MAXBITLEN
= 0,
9258 BGP_STATS_UNAGGREGATEABLE
,
9259 BGP_STATS_MAX_AGGREGATEABLE
,
9260 BGP_STATS_AGGREGATES
,
9262 BGP_STATS_ASPATH_COUNT
,
9263 BGP_STATS_ASPATH_MAXHOPS
,
9264 BGP_STATS_ASPATH_TOTHOPS
,
9265 BGP_STATS_ASPATH_MAXSIZE
,
9266 BGP_STATS_ASPATH_TOTSIZE
,
9267 BGP_STATS_ASN_HIGHEST
,
9271 static const char *table_stats_strs
[] = {
9272 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9273 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9274 [BGP_STATS_RIB
] = "Total Advertisements",
9275 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9276 [BGP_STATS_MAX_AGGREGATEABLE
] =
9277 "Maximum aggregateable prefixes",
9278 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9279 [BGP_STATS_SPACE
] = "Address space advertised",
9280 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9281 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9282 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9283 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9284 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9285 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9286 [BGP_STATS_MAX
] = NULL
,
9289 struct bgp_table_stats
{
9290 struct bgp_table
*table
;
9291 unsigned long long counts
[BGP_STATS_MAX
];
9295 #define TALLY_SIGFIG 100000
9296 static unsigned long
9297 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9299 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9300 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9301 unsigned long ret
= newtot
/ count
;
9303 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9310 static int bgp_table_stats_walker(struct thread
*t
)
9312 struct bgp_node
*rn
;
9313 struct bgp_node
*top
;
9314 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9315 unsigned int space
= 0;
9317 if (!(top
= bgp_table_top(ts
->table
)))
9320 switch (top
->p
.family
) {
9322 space
= IPV4_MAX_BITLEN
;
9325 space
= IPV6_MAX_BITLEN
;
9329 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9331 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9332 struct bgp_info
*ri
;
9333 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9334 unsigned int rinum
= 0;
9342 ts
->counts
[BGP_STATS_PREFIXES
]++;
9343 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9346 ts
->counts
[BGP_STATS_AVGPLEN
]
9347 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9348 ts
->counts
[BGP_STATS_AVGPLEN
],
9352 /* check if the prefix is included by any other announcements */
9353 while (prn
&& !prn
->info
)
9354 prn
= bgp_node_parent_nolock(prn
);
9356 if (prn
== NULL
|| prn
== top
) {
9357 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9358 /* announced address space */
9360 ts
->counts
[BGP_STATS_SPACE
] +=
9361 1 << (space
- rn
->p
.prefixlen
);
9362 } else if (prn
->info
)
9363 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9365 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9367 ts
->counts
[BGP_STATS_RIB
]++;
9370 && (CHECK_FLAG(ri
->attr
->flag
,
9372 BGP_ATTR_ATOMIC_AGGREGATE
))))
9373 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9376 if (ri
->attr
&& ri
->attr
->aspath
) {
9378 aspath_count_hops(ri
->attr
->aspath
);
9380 aspath_size(ri
->attr
->aspath
);
9381 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9383 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9385 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9386 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9389 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9390 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9393 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9394 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9396 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9397 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9398 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9400 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9401 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9402 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9405 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9406 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9414 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9417 struct bgp_table_stats ts
;
9420 if (!bgp
->rib
[afi
][safi
]) {
9421 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9426 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9428 /* labeled-unicast routes live in the unicast table */
9429 if (safi
== SAFI_LABELED_UNICAST
)
9430 safi
= SAFI_UNICAST
;
9432 memset(&ts
, 0, sizeof(ts
));
9433 ts
.table
= bgp
->rib
[afi
][safi
];
9434 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9436 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9437 if (!table_stats_strs
[i
])
9442 case BGP_STATS_ASPATH_AVGHOPS
:
9443 case BGP_STATS_ASPATH_AVGSIZE
:
9444 case BGP_STATS_AVGPLEN
:
9445 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9446 vty_out (vty
, "%12.2f",
9447 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9450 case BGP_STATS_ASPATH_TOTHOPS
:
9451 case BGP_STATS_ASPATH_TOTSIZE
:
9452 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9453 vty_out(vty
, "%12.2f",
9455 ? (float)ts
.counts
[i
]
9457 [BGP_STATS_ASPATH_COUNT
]
9460 case BGP_STATS_TOTPLEN
:
9461 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9462 vty_out(vty
, "%12.2f",
9464 ? (float)ts
.counts
[i
]
9466 [BGP_STATS_PREFIXES
]
9469 case BGP_STATS_SPACE
:
9470 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9471 vty_out(vty
, "%12llu\n", ts
.counts
[i
]);
9472 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 9)
9474 vty_out(vty
, "%30s: ", "%% announced ");
9475 vty_out(vty
, "%12.2f\n",
9476 100 * (float)ts
.counts
[BGP_STATS_SPACE
]
9477 / (float)((uint64_t)1UL
9479 [BGP_STATS_MAXBITLEN
]));
9480 vty_out(vty
, "%30s: ", "/8 equivalent ");
9481 vty_out(vty
, "%12.2f\n",
9482 (float)ts
.counts
[BGP_STATS_SPACE
]
9485 [BGP_STATS_MAXBITLEN
]
9487 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 25)
9489 vty_out(vty
, "%30s: ", "/24 equivalent ");
9490 vty_out(vty
, "%12.2f",
9491 (float)ts
.counts
[BGP_STATS_SPACE
]
9494 [BGP_STATS_MAXBITLEN
]
9498 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9499 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9516 PCOUNT_PFCNT
, /* the figure we display to users */
9520 static const char *pcount_strs
[] = {
9521 [PCOUNT_ADJ_IN
] = "Adj-in",
9522 [PCOUNT_DAMPED
] = "Damped",
9523 [PCOUNT_REMOVED
] = "Removed",
9524 [PCOUNT_HISTORY
] = "History",
9525 [PCOUNT_STALE
] = "Stale",
9526 [PCOUNT_VALID
] = "Valid",
9527 [PCOUNT_ALL
] = "All RIB",
9528 [PCOUNT_COUNTED
] = "PfxCt counted",
9529 [PCOUNT_PFCNT
] = "Useable",
9530 [PCOUNT_MAX
] = NULL
,
9533 struct peer_pcounts
{
9534 unsigned int count
[PCOUNT_MAX
];
9535 const struct peer
*peer
;
9536 const struct bgp_table
*table
;
9539 static int bgp_peer_count_walker(struct thread
*t
)
9541 struct bgp_node
*rn
;
9542 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9543 const struct peer
*peer
= pc
->peer
;
9545 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9546 struct bgp_adj_in
*ain
;
9547 struct bgp_info
*ri
;
9549 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9550 if (ain
->peer
== peer
)
9551 pc
->count
[PCOUNT_ADJ_IN
]++;
9553 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9554 char buf
[SU_ADDRSTRLEN
];
9556 if (ri
->peer
!= peer
)
9559 pc
->count
[PCOUNT_ALL
]++;
9561 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9562 pc
->count
[PCOUNT_DAMPED
]++;
9563 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9564 pc
->count
[PCOUNT_HISTORY
]++;
9565 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9566 pc
->count
[PCOUNT_REMOVED
]++;
9567 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9568 pc
->count
[PCOUNT_STALE
]++;
9569 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9570 pc
->count
[PCOUNT_VALID
]++;
9571 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9572 pc
->count
[PCOUNT_PFCNT
]++;
9574 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9575 pc
->count
[PCOUNT_COUNTED
]++;
9576 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9578 "%s [pcount] %s/%d is counted but flags 0x%x",
9580 inet_ntop(rn
->p
.family
,
9581 &rn
->p
.u
.prefix
, buf
,
9583 rn
->p
.prefixlen
, ri
->flags
);
9585 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9587 "%s [pcount] %s/%d not counted but flags 0x%x",
9589 inet_ntop(rn
->p
.family
,
9590 &rn
->p
.u
.prefix
, buf
,
9592 rn
->p
.prefixlen
, ri
->flags
);
9599 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9600 safi_t safi
, u_char use_json
)
9602 struct peer_pcounts pcounts
= {.peer
= peer
};
9604 json_object
*json
= NULL
;
9605 json_object
*json_loop
= NULL
;
9608 json
= json_object_new_object();
9609 json_loop
= json_object_new_object();
9612 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9613 || !peer
->bgp
->rib
[afi
][safi
]) {
9615 json_object_string_add(
9617 "No such neighbor or address family");
9618 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9619 json_object_free(json
);
9621 vty_out(vty
, "%% No such neighbor or address family\n");
9626 memset(&pcounts
, 0, sizeof(pcounts
));
9627 pcounts
.peer
= peer
;
9628 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9630 /* in-place call via thread subsystem so as to record execution time
9631 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9632 * * on just vty_read()).
9634 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9637 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9638 json_object_string_add(json
, "multiProtocol",
9639 afi_safi_print(afi
, safi
));
9640 json_object_int_add(json
, "pfxCounter",
9641 peer
->pcount
[afi
][safi
]);
9643 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9644 json_object_int_add(json_loop
, pcount_strs
[i
],
9647 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9649 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9650 json_object_string_add(json
, "pfxctDriftFor",
9652 json_object_string_add(
9653 json
, "recommended",
9654 "Please report this bug, with the above command output");
9656 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9657 json_object_free(json
);
9661 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9662 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9663 peer
->hostname
, peer
->host
,
9664 afi_safi_print(afi
, safi
));
9666 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9667 afi_safi_print(afi
, safi
));
9670 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9671 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9673 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9674 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9677 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9678 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9680 "Please report this bug, with the above command output\n");
9687 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9688 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9689 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9690 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9694 BGP_INSTANCE_HELP_STR
9697 "Detailed information on TCP and BGP neighbor connections\n"
9698 "Neighbor to display information about\n"
9699 "Neighbor to display information about\n"
9700 "Neighbor on BGP configured interface\n"
9701 "Display detailed prefix count information\n"
9704 afi_t afi
= AFI_IP6
;
9705 safi_t safi
= SAFI_UNICAST
;
9708 struct bgp
*bgp
= NULL
;
9710 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9715 int uj
= use_json(argc
, argv
);
9719 argv_find(argv
, argc
, "neighbors", &idx
);
9720 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9724 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9727 #ifdef KEEP_OLD_VPN_COMMANDS
9728 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9729 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9730 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9735 "Display information about all VPNv4 NLRIs\n"
9736 "Detailed information on TCP and BGP neighbor connections\n"
9737 "Neighbor to display information about\n"
9738 "Neighbor to display information about\n"
9739 "Neighbor on BGP configured interface\n"
9740 "Display detailed prefix count information\n"
9745 u_char uj
= use_json(argc
, argv
);
9747 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9751 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9754 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9755 show_ip_bgp_vpn_all_route_prefix_cmd
,
9756 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9761 "Display information about all VPNv4 NLRIs\n"
9762 "Network in the BGP routing table to display\n"
9763 "Network in the BGP routing table to display\n"
9767 char *network
= NULL
;
9768 struct bgp
*bgp
= bgp_get_default();
9770 vty_out(vty
, "Can't find default instance\n");
9774 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9775 network
= argv
[idx
]->arg
;
9776 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9777 network
= argv
[idx
]->arg
;
9779 vty_out(vty
, "Unable to figure out Network\n");
9783 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9784 BGP_PATH_ALL
, use_json(argc
, argv
));
9786 #endif /* KEEP_OLD_VPN_COMMANDS */
9788 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9789 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9790 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9796 "Display information about all EVPN NLRIs\n"
9797 "Network in the BGP routing table to display\n"
9798 "Network in the BGP routing table to display\n"
9802 char *network
= NULL
;
9804 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9805 network
= argv
[idx
]->arg
;
9806 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9807 network
= argv
[idx
]->arg
;
9809 vty_out(vty
, "Unable to figure out Network\n");
9812 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9813 BGP_PATH_ALL
, use_json(argc
, argv
));
9816 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9817 safi_t safi
, int in
, const char *rmap_name
,
9818 u_char use_json
, json_object
*json
)
9820 struct bgp_table
*table
;
9821 struct bgp_adj_in
*ain
;
9822 struct bgp_adj_out
*adj
;
9823 unsigned long output_count
;
9824 unsigned long filtered_count
;
9825 struct bgp_node
*rn
;
9831 struct update_subgroup
*subgrp
;
9832 json_object
*json_scode
= NULL
;
9833 json_object
*json_ocode
= NULL
;
9834 json_object
*json_ar
= NULL
;
9835 struct peer_af
*paf
;
9838 json_scode
= json_object_new_object();
9839 json_ocode
= json_object_new_object();
9840 json_ar
= json_object_new_object();
9842 json_object_string_add(json_scode
, "suppressed", "s");
9843 json_object_string_add(json_scode
, "damped", "d");
9844 json_object_string_add(json_scode
, "history", "h");
9845 json_object_string_add(json_scode
, "valid", "*");
9846 json_object_string_add(json_scode
, "best", ">");
9847 json_object_string_add(json_scode
, "multipath", "=");
9848 json_object_string_add(json_scode
, "internal", "i");
9849 json_object_string_add(json_scode
, "ribFailure", "r");
9850 json_object_string_add(json_scode
, "stale", "S");
9851 json_object_string_add(json_scode
, "removed", "R");
9853 json_object_string_add(json_ocode
, "igp", "i");
9854 json_object_string_add(json_ocode
, "egp", "e");
9855 json_object_string_add(json_ocode
, "incomplete", "?");
9862 json_object_string_add(json
, "alert", "no BGP");
9863 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9864 json_object_free(json
);
9866 vty_out(vty
, "%% No bgp\n");
9870 table
= bgp
->rib
[afi
][safi
];
9872 output_count
= filtered_count
= 0;
9873 subgrp
= peer_subgroup(peer
, afi
, safi
);
9876 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
9878 json_object_int_add(json
, "bgpTableVersion",
9880 json_object_string_add(json
, "bgpLocalRouterId",
9881 inet_ntoa(bgp
->router_id
));
9882 json_object_object_add(json
, "bgpStatusCodes",
9884 json_object_object_add(json
, "bgpOriginCodes",
9886 json_object_string_add(json
,
9887 "bgpOriginatingDefaultNetwork",
9890 vty_out(vty
, "BGP table version is %" PRIu64
9891 ", local router ID is %s\n",
9892 table
->version
, inet_ntoa(bgp
->router_id
));
9893 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9894 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9896 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
9901 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9903 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
9904 if (ain
->peer
== peer
) {
9907 json_object_int_add(
9911 json_object_string_add(
9916 json_object_object_add(
9920 json_object_object_add(
9926 "BGP table version is 0, local router ID is %s\n",
9930 BGP_SHOW_SCODE_HEADER
);
9932 BGP_SHOW_OCODE_HEADER
);
9943 bgp_attr_dup(&attr
, ain
->attr
);
9944 if (bgp_input_modifier(
9945 peer
, &rn
->p
, &attr
,
9961 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
9962 SUBGRP_FOREACH_PEER(adj
->subgroup
, paf
)
9963 if (paf
->peer
== peer
) {
9966 json_object_int_add(
9967 json
, "bgpTableVersion",
9969 json_object_string_add(
9974 json_object_object_add(
9975 json
, "bgpStatusCodes",
9977 json_object_object_add(
9978 json
, "bgpOriginCodes",
9982 "BGP table version is %" PRIu64
9983 ", local router ID is %s\n",
9988 BGP_SHOW_SCODE_HEADER
);
9990 BGP_SHOW_OCODE_HEADER
);
9997 vty_out(vty
, BGP_SHOW_HEADER
);
10002 bgp_attr_dup(&attr
, adj
->attr
);
10003 ret
= bgp_output_modifier(
10004 peer
, &rn
->p
, &attr
, afi
, safi
,
10006 if (ret
!= RMAP_DENY
) {
10007 route_vty_out_tmp(vty
, &rn
->p
,
10019 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10021 if (output_count
!= 0) {
10023 json_object_int_add(json
, "totalPrefixCounter",
10026 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10030 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10031 json_object_free(json
);
10035 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10036 safi_t safi
, int in
, const char *rmap_name
,
10039 json_object
*json
= NULL
;
10042 json
= json_object_new_object();
10044 /* labeled-unicast routes live in the unicast table */
10045 if (safi
== SAFI_LABELED_UNICAST
)
10046 safi
= SAFI_UNICAST
;
10048 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10050 json_object_string_add(
10052 "No such neighbor or address family");
10053 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10054 json_object_free(json
);
10056 vty_out(vty
, "%% No such neighbor or address family\n");
10058 return CMD_WARNING
;
10062 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10063 PEER_FLAG_SOFT_RECONFIG
)) {
10065 json_object_string_add(
10067 "Inbound soft reconfiguration not enabled");
10068 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10069 json_object_free(json
);
10072 "%% Inbound soft reconfiguration not enabled\n");
10074 return CMD_WARNING
;
10077 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10079 return CMD_SUCCESS
;
10082 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10083 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10084 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10085 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10089 BGP_INSTANCE_HELP_STR
10091 BGP_SAFI_WITH_LABEL_HELP_STR
10092 "Detailed information on TCP and BGP neighbor connections\n"
10093 "Neighbor to display information about\n"
10094 "Neighbor to display information about\n"
10095 "Neighbor on BGP configured interface\n"
10096 "Display the received routes from neighbor\n"
10097 "Display the routes advertised to a BGP neighbor\n"
10098 "Route-map to modify the attributes\n"
10099 "Name of the route map\n"
10102 afi_t afi
= AFI_IP6
;
10103 safi_t safi
= SAFI_UNICAST
;
10104 char *rmap_name
= NULL
;
10105 char *peerstr
= NULL
;
10107 struct bgp
*bgp
= NULL
;
10112 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10115 return CMD_WARNING
;
10117 int uj
= use_json(argc
, argv
);
10121 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10122 argv_find(argv
, argc
, "neighbors", &idx
);
10123 peerstr
= argv
[++idx
]->arg
;
10125 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10127 return CMD_WARNING
;
10129 if (argv_find(argv
, argc
, "received-routes", &idx
))
10131 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10133 if (argv_find(argv
, argc
, "route-map", &idx
))
10134 rmap_name
= argv
[++idx
]->arg
;
10136 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10139 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10140 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10141 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10147 "Address Family modifier\n"
10148 "Detailed information on TCP and BGP neighbor connections\n"
10149 "Neighbor to display information about\n"
10150 "Neighbor to display information about\n"
10151 "Neighbor on BGP configured interface\n"
10152 "Display information received from a BGP neighbor\n"
10153 "Display the prefixlist filter\n"
10156 afi_t afi
= AFI_IP6
;
10157 safi_t safi
= SAFI_UNICAST
;
10158 char *peerstr
= NULL
;
10161 union sockunion su
;
10167 /* show [ip] bgp */
10168 if (argv_find(argv
, argc
, "ip", &idx
))
10170 /* [<ipv4|ipv6> [unicast]] */
10171 if (argv_find(argv
, argc
, "ipv4", &idx
))
10173 if (argv_find(argv
, argc
, "ipv6", &idx
))
10175 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10176 argv_find(argv
, argc
, "neighbors", &idx
);
10177 peerstr
= argv
[++idx
]->arg
;
10179 u_char uj
= use_json(argc
, argv
);
10181 ret
= str2sockunion(peerstr
, &su
);
10183 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10186 vty_out(vty
, "{}\n");
10189 "%% Malformed address or name: %s\n",
10191 return CMD_WARNING
;
10194 peer
= peer_lookup(NULL
, &su
);
10197 vty_out(vty
, "{}\n");
10199 vty_out(vty
, "No peer\n");
10200 return CMD_WARNING
;
10204 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10205 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10208 vty_out(vty
, "Address Family: %s\n",
10209 afi_safi_print(afi
, safi
));
10210 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10213 vty_out(vty
, "{}\n");
10215 vty_out(vty
, "No functional output\n");
10218 return CMD_SUCCESS
;
10221 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10222 afi_t afi
, safi_t safi
,
10223 enum bgp_show_type type
, u_char use_json
)
10225 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10227 json_object
*json_no
= NULL
;
10228 json_no
= json_object_new_object();
10229 json_object_string_add(
10230 json_no
, "warning",
10231 "No such neighbor or address family");
10232 vty_out(vty
, "%s\n",
10233 json_object_to_json_string(json_no
));
10234 json_object_free(json_no
);
10236 vty_out(vty
, "%% No such neighbor or address family\n");
10237 return CMD_WARNING
;
10240 /* labeled-unicast routes live in the unicast table */
10241 if (safi
== SAFI_LABELED_UNICAST
)
10242 safi
= SAFI_UNICAST
;
10244 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10247 DEFUN (show_ip_bgp_neighbor_routes
,
10248 show_ip_bgp_neighbor_routes_cmd
,
10249 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10250 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10254 BGP_INSTANCE_HELP_STR
10256 BGP_SAFI_WITH_LABEL_HELP_STR
10257 "Detailed information on TCP and BGP neighbor connections\n"
10258 "Neighbor to display information about\n"
10259 "Neighbor to display information about\n"
10260 "Neighbor on BGP configured interface\n"
10261 "Display flap statistics of the routes learned from neighbor\n"
10262 "Display the dampened routes received from neighbor\n"
10263 "Display routes learned from neighbor\n"
10266 char *peerstr
= NULL
;
10267 struct bgp
*bgp
= NULL
;
10268 afi_t afi
= AFI_IP6
;
10269 safi_t safi
= SAFI_UNICAST
;
10271 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10275 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10278 return CMD_WARNING
;
10280 int uj
= use_json(argc
, argv
);
10284 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10285 argv_find(argv
, argc
, "neighbors", &idx
);
10286 peerstr
= argv
[++idx
]->arg
;
10288 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10290 vty_out(vty
, "No such neighbor\n");
10291 return CMD_WARNING
;
10294 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10295 sh_type
= bgp_show_type_flap_neighbor
;
10296 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10297 sh_type
= bgp_show_type_damp_neighbor
;
10298 else if (argv_find(argv
, argc
, "routes", &idx
))
10299 sh_type
= bgp_show_type_neighbor
;
10301 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10304 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10306 struct bgp_distance
{
10307 /* Distance value for the IP source prefix. */
10310 /* Name of the access-list to be matched. */
10314 DEFUN (show_bgp_afi_vpn_rd_route
,
10315 show_bgp_afi_vpn_rd_route_cmd
,
10316 "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]",
10320 "Address Family modifier\n"
10321 "Display information for a route distinguisher\n"
10322 "Route Distinguisher\n"
10323 "Network in the BGP routing table to display\n"
10324 "Network in the BGP routing table to display\n"
10328 struct prefix_rd prd
;
10329 afi_t afi
= AFI_MAX
;
10332 argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
);
10333 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10335 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10336 return CMD_WARNING
;
10338 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10339 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10342 static struct bgp_distance
*bgp_distance_new(void)
10344 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10347 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10349 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10352 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10353 const char *ip_str
, const char *access_list_str
)
10360 struct bgp_node
*rn
;
10361 struct bgp_distance
*bdistance
;
10363 afi
= bgp_node_afi(vty
);
10364 safi
= bgp_node_safi(vty
);
10366 ret
= str2prefix(ip_str
, &p
);
10368 vty_out(vty
, "Malformed prefix\n");
10369 return CMD_WARNING_CONFIG_FAILED
;
10372 distance
= atoi(distance_str
);
10374 /* Get BGP distance node. */
10375 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10377 bdistance
= rn
->info
;
10378 bgp_unlock_node(rn
);
10380 bdistance
= bgp_distance_new();
10381 rn
->info
= bdistance
;
10384 /* Set distance value. */
10385 bdistance
->distance
= distance
;
10387 /* Reset access-list configuration. */
10388 if (bdistance
->access_list
) {
10389 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10390 bdistance
->access_list
= NULL
;
10392 if (access_list_str
)
10393 bdistance
->access_list
=
10394 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10396 return CMD_SUCCESS
;
10399 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10400 const char *ip_str
, const char *access_list_str
)
10407 struct bgp_node
*rn
;
10408 struct bgp_distance
*bdistance
;
10410 afi
= bgp_node_afi(vty
);
10411 safi
= bgp_node_safi(vty
);
10413 ret
= str2prefix(ip_str
, &p
);
10415 vty_out(vty
, "Malformed prefix\n");
10416 return CMD_WARNING_CONFIG_FAILED
;
10419 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10420 (struct prefix
*)&p
);
10422 vty_out(vty
, "Can't find specified prefix\n");
10423 return CMD_WARNING_CONFIG_FAILED
;
10426 bdistance
= rn
->info
;
10427 distance
= atoi(distance_str
);
10429 if (bdistance
->distance
!= distance
) {
10430 vty_out(vty
, "Distance does not match configured\n");
10431 return CMD_WARNING_CONFIG_FAILED
;
10434 if (bdistance
->access_list
)
10435 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10436 bgp_distance_free(bdistance
);
10439 bgp_unlock_node(rn
);
10440 bgp_unlock_node(rn
);
10442 return CMD_SUCCESS
;
10445 /* Apply BGP information to distance method. */
10446 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10447 safi_t safi
, struct bgp
*bgp
)
10449 struct bgp_node
*rn
;
10452 struct bgp_distance
*bdistance
;
10453 struct access_list
*alist
;
10454 struct bgp_static
*bgp_static
;
10459 peer
= rinfo
->peer
;
10461 /* Check source address. */
10462 sockunion2hostprefix(&peer
->su
, &q
);
10463 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10465 bdistance
= rn
->info
;
10466 bgp_unlock_node(rn
);
10468 if (bdistance
->access_list
) {
10469 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10471 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10472 return bdistance
->distance
;
10474 return bdistance
->distance
;
10477 /* Backdoor check. */
10478 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10480 bgp_static
= rn
->info
;
10481 bgp_unlock_node(rn
);
10483 if (bgp_static
->backdoor
) {
10484 if (bgp
->distance_local
[afi
][safi
])
10485 return bgp
->distance_local
[afi
][safi
];
10487 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10491 if (peer
->sort
== BGP_PEER_EBGP
) {
10492 if (bgp
->distance_ebgp
[afi
][safi
])
10493 return bgp
->distance_ebgp
[afi
][safi
];
10494 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10496 if (bgp
->distance_ibgp
[afi
][safi
])
10497 return bgp
->distance_ibgp
[afi
][safi
];
10498 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10502 DEFUN (bgp_distance
,
10504 "distance bgp (1-255) (1-255) (1-255)",
10505 "Define an administrative distance\n"
10507 "Distance for routes external to the AS\n"
10508 "Distance for routes internal to the AS\n"
10509 "Distance for local routes\n")
10511 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10512 int idx_number
= 2;
10513 int idx_number_2
= 3;
10514 int idx_number_3
= 4;
10518 afi
= bgp_node_afi(vty
);
10519 safi
= bgp_node_safi(vty
);
10521 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10522 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10523 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10524 return CMD_SUCCESS
;
10527 DEFUN (no_bgp_distance
,
10528 no_bgp_distance_cmd
,
10529 "no distance bgp [(1-255) (1-255) (1-255)]",
10531 "Define an administrative distance\n"
10533 "Distance for routes external to the AS\n"
10534 "Distance for routes internal to the AS\n"
10535 "Distance for local routes\n")
10537 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10541 afi
= bgp_node_afi(vty
);
10542 safi
= bgp_node_safi(vty
);
10544 bgp
->distance_ebgp
[afi
][safi
] = 0;
10545 bgp
->distance_ibgp
[afi
][safi
] = 0;
10546 bgp
->distance_local
[afi
][safi
] = 0;
10547 return CMD_SUCCESS
;
10551 DEFUN (bgp_distance_source
,
10552 bgp_distance_source_cmd
,
10553 "distance (1-255) A.B.C.D/M",
10554 "Define an administrative distance\n"
10555 "Administrative distance\n"
10556 "IP source prefix\n")
10558 int idx_number
= 1;
10559 int idx_ipv4_prefixlen
= 2;
10560 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10561 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10562 return CMD_SUCCESS
;
10565 DEFUN (no_bgp_distance_source
,
10566 no_bgp_distance_source_cmd
,
10567 "no distance (1-255) A.B.C.D/M",
10569 "Define an administrative distance\n"
10570 "Administrative distance\n"
10571 "IP source prefix\n")
10573 int idx_number
= 2;
10574 int idx_ipv4_prefixlen
= 3;
10575 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10576 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10577 return CMD_SUCCESS
;
10580 DEFUN (bgp_distance_source_access_list
,
10581 bgp_distance_source_access_list_cmd
,
10582 "distance (1-255) A.B.C.D/M WORD",
10583 "Define an administrative distance\n"
10584 "Administrative distance\n"
10585 "IP source prefix\n"
10586 "Access list name\n")
10588 int idx_number
= 1;
10589 int idx_ipv4_prefixlen
= 2;
10591 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10592 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10593 return CMD_SUCCESS
;
10596 DEFUN (no_bgp_distance_source_access_list
,
10597 no_bgp_distance_source_access_list_cmd
,
10598 "no distance (1-255) A.B.C.D/M WORD",
10600 "Define an administrative distance\n"
10601 "Administrative distance\n"
10602 "IP source prefix\n"
10603 "Access list name\n")
10605 int idx_number
= 2;
10606 int idx_ipv4_prefixlen
= 3;
10608 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10609 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10610 return CMD_SUCCESS
;
10613 DEFUN (ipv6_bgp_distance_source
,
10614 ipv6_bgp_distance_source_cmd
,
10615 "distance (1-255) X:X::X:X/M",
10616 "Define an administrative distance\n"
10617 "Administrative distance\n"
10618 "IP source prefix\n")
10620 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10621 return CMD_SUCCESS
;
10624 DEFUN (no_ipv6_bgp_distance_source
,
10625 no_ipv6_bgp_distance_source_cmd
,
10626 "no distance (1-255) X:X::X:X/M",
10628 "Define an administrative distance\n"
10629 "Administrative distance\n"
10630 "IP source prefix\n")
10632 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10633 return CMD_SUCCESS
;
10636 DEFUN (ipv6_bgp_distance_source_access_list
,
10637 ipv6_bgp_distance_source_access_list_cmd
,
10638 "distance (1-255) X:X::X:X/M WORD",
10639 "Define an administrative distance\n"
10640 "Administrative distance\n"
10641 "IP source prefix\n"
10642 "Access list name\n")
10644 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10645 return CMD_SUCCESS
;
10648 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10649 no_ipv6_bgp_distance_source_access_list_cmd
,
10650 "no distance (1-255) X:X::X:X/M WORD",
10652 "Define an administrative distance\n"
10653 "Administrative distance\n"
10654 "IP source prefix\n"
10655 "Access list name\n")
10657 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10658 return CMD_SUCCESS
;
10661 DEFUN (bgp_damp_set
,
10663 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10664 "BGP Specific commands\n"
10665 "Enable route-flap dampening\n"
10666 "Half-life time for the penalty\n"
10667 "Value to start reusing a route\n"
10668 "Value to start suppressing a route\n"
10669 "Maximum duration to suppress a stable route\n")
10671 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10672 int idx_half_life
= 2;
10674 int idx_suppress
= 4;
10675 int idx_max_suppress
= 5;
10676 int half
= DEFAULT_HALF_LIFE
* 60;
10677 int reuse
= DEFAULT_REUSE
;
10678 int suppress
= DEFAULT_SUPPRESS
;
10679 int max
= 4 * half
;
10682 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10683 reuse
= atoi(argv
[idx_reuse
]->arg
);
10684 suppress
= atoi(argv
[idx_suppress
]->arg
);
10685 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10686 } else if (argc
== 3) {
10687 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10691 if (suppress
< reuse
) {
10693 "Suppress value cannot be less than reuse value \n");
10697 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10698 reuse
, suppress
, max
);
10701 DEFUN (bgp_damp_unset
,
10702 bgp_damp_unset_cmd
,
10703 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10705 "BGP Specific commands\n"
10706 "Enable route-flap dampening\n"
10707 "Half-life time for the penalty\n"
10708 "Value to start reusing a route\n"
10709 "Value to start suppressing a route\n"
10710 "Maximum duration to suppress a stable route\n")
10712 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10713 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10716 /* Display specified route of BGP table. */
10717 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10718 const char *ip_str
, afi_t afi
, safi_t safi
,
10719 struct prefix_rd
*prd
, int prefix_check
)
10722 struct prefix match
;
10723 struct bgp_node
*rn
;
10724 struct bgp_node
*rm
;
10725 struct bgp_info
*ri
;
10726 struct bgp_info
*ri_temp
;
10728 struct bgp_table
*table
;
10730 /* BGP structure lookup. */
10732 bgp
= bgp_lookup_by_name(view_name
);
10734 vty_out(vty
, "%% Can't find BGP instance %s\n",
10736 return CMD_WARNING
;
10739 bgp
= bgp_get_default();
10741 vty_out(vty
, "%% No BGP process is configured\n");
10742 return CMD_WARNING
;
10746 /* Check IP address argument. */
10747 ret
= str2prefix(ip_str
, &match
);
10749 vty_out(vty
, "%% address is malformed\n");
10750 return CMD_WARNING
;
10753 match
.family
= afi2family(afi
);
10755 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10756 || (safi
== SAFI_EVPN
)) {
10757 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10758 rn
= bgp_route_next(rn
)) {
10759 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10762 if ((table
= rn
->info
) != NULL
)
10763 if ((rm
= bgp_node_match(table
, &match
))
10767 == match
.prefixlen
) {
10775 bgp_damp_info_free(
10785 bgp_unlock_node(rm
);
10789 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10792 || rn
->p
.prefixlen
== match
.prefixlen
) {
10795 if (ri
->extra
&& ri
->extra
->damp_info
) {
10796 ri_temp
= ri
->next
;
10797 bgp_damp_info_free(
10798 ri
->extra
->damp_info
,
10806 bgp_unlock_node(rn
);
10810 return CMD_SUCCESS
;
10813 DEFUN (clear_ip_bgp_dampening
,
10814 clear_ip_bgp_dampening_cmd
,
10815 "clear ip bgp dampening",
10819 "Clear route flap dampening information\n")
10821 bgp_damp_info_clean();
10822 return CMD_SUCCESS
;
10825 DEFUN (clear_ip_bgp_dampening_prefix
,
10826 clear_ip_bgp_dampening_prefix_cmd
,
10827 "clear ip bgp dampening A.B.C.D/M",
10831 "Clear route flap dampening information\n"
10834 int idx_ipv4_prefixlen
= 4;
10835 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10836 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
10839 DEFUN (clear_ip_bgp_dampening_address
,
10840 clear_ip_bgp_dampening_address_cmd
,
10841 "clear ip bgp dampening A.B.C.D",
10845 "Clear route flap dampening information\n"
10846 "Network to clear damping information\n")
10849 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
10850 SAFI_UNICAST
, NULL
, 0);
10853 DEFUN (clear_ip_bgp_dampening_address_mask
,
10854 clear_ip_bgp_dampening_address_mask_cmd
,
10855 "clear ip bgp dampening A.B.C.D A.B.C.D",
10859 "Clear route flap dampening information\n"
10860 "Network to clear damping information\n"
10864 int idx_ipv4_2
= 5;
10866 char prefix_str
[BUFSIZ
];
10868 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
10871 vty_out(vty
, "%% Inconsistent address and mask\n");
10872 return CMD_WARNING
;
10875 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
10879 /* also used for encap safi */
10880 static int bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
10881 afi_t afi
, safi_t safi
, int *write
)
10883 struct bgp_node
*prn
;
10884 struct bgp_node
*rn
;
10885 struct bgp_table
*table
;
10887 struct prefix_rd
*prd
;
10888 struct bgp_static
*bgp_static
;
10889 mpls_label_t label
;
10890 char buf
[SU_ADDRSTRLEN
];
10891 char rdbuf
[RD_ADDRSTRLEN
];
10893 /* Network configuration. */
10894 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10895 prn
= bgp_route_next(prn
))
10896 if ((table
= prn
->info
) != NULL
)
10897 for (rn
= bgp_table_top(table
); rn
;
10898 rn
= bgp_route_next(rn
))
10899 if ((bgp_static
= rn
->info
) != NULL
) {
10901 prd
= (struct prefix_rd
*)&prn
->p
;
10903 /* "address-family" display. */
10904 bgp_config_write_family_header(
10905 vty
, afi
, safi
, write
);
10907 /* "network" configuration display. */
10908 prefix_rd2str(prd
, rdbuf
,
10910 label
= decode_label(
10911 &bgp_static
->label
);
10913 vty_out(vty
, " network %s/%d rd %s",
10914 inet_ntop(p
->family
,
10917 p
->prefixlen
, rdbuf
);
10918 if (safi
== SAFI_MPLS_VPN
)
10919 vty_out(vty
, " label %u",
10922 if (bgp_static
->rmap
.name
)
10923 vty_out(vty
, " route-map %s",
10924 bgp_static
->rmap
.name
);
10926 if (bgp_static
->backdoor
)
10930 vty_out(vty
, "\n");
10935 static int bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
10936 afi_t afi
, safi_t safi
, int *write
)
10938 struct bgp_node
*prn
;
10939 struct bgp_node
*rn
;
10940 struct bgp_table
*table
;
10942 struct prefix_rd
*prd
;
10943 struct bgp_static
*bgp_static
;
10944 char buf
[PREFIX_STRLEN
];
10945 char buf2
[SU_ADDRSTRLEN
];
10946 char rdbuf
[RD_ADDRSTRLEN
];
10948 /* Network configuration. */
10949 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10950 prn
= bgp_route_next(prn
))
10951 if ((table
= prn
->info
) != NULL
)
10952 for (rn
= bgp_table_top(table
); rn
;
10953 rn
= bgp_route_next(rn
))
10954 if ((bgp_static
= rn
->info
) != NULL
) {
10955 char *macrouter
= NULL
;
10958 if (bgp_static
->router_mac
)
10959 macrouter
= prefix_mac2str(
10960 bgp_static
->router_mac
,
10962 if (bgp_static
->eth_s_id
)
10964 bgp_static
->eth_s_id
);
10966 prd
= (struct prefix_rd
*)&prn
->p
;
10968 /* "address-family" display. */
10969 bgp_config_write_family_header(
10970 vty
, afi
, safi
, write
);
10972 /* "network" configuration display. */
10973 prefix_rd2str(prd
, rdbuf
,
10977 &bgp_static
->igpnexthop
, buf2
,
10980 prefix2str(p
, buf
, sizeof(buf
)),
10982 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
10989 esi
, buf2
, macrouter
);
10990 vty_out(vty
, "\n");
10992 XFREE(MTYPE_TMP
, macrouter
);
10994 XFREE(MTYPE_TMP
, esi
);
10999 /* Configuration of static route announcement and aggregate
11001 int bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11002 safi_t safi
, int *write
)
11004 struct bgp_node
*rn
;
11006 struct bgp_static
*bgp_static
;
11007 struct bgp_aggregate
*bgp_aggregate
;
11008 char buf
[SU_ADDRSTRLEN
];
11010 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
11011 return bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
, write
);
11013 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
11014 return bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
,
11017 /* Network configuration. */
11018 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11019 rn
= bgp_route_next(rn
))
11020 if ((bgp_static
= rn
->info
) != NULL
) {
11023 /* "address-family" display. */
11024 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11026 /* "network" configuration display. */
11027 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11028 && afi
== AFI_IP
) {
11029 u_int32_t destination
;
11030 struct in_addr netmask
;
11032 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11033 masklen2ip(p
->prefixlen
, &netmask
);
11034 vty_out(vty
, " network %s",
11035 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11038 if ((IN_CLASSC(destination
)
11039 && p
->prefixlen
== 24)
11040 || (IN_CLASSB(destination
)
11041 && p
->prefixlen
== 16)
11042 || (IN_CLASSA(destination
)
11043 && p
->prefixlen
== 8)
11044 || p
->u
.prefix4
.s_addr
== 0) {
11045 /* Natural mask is not display. */
11047 vty_out(vty
, " mask %s",
11048 inet_ntoa(netmask
));
11050 vty_out(vty
, " network %s/%d",
11051 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11056 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11057 vty_out(vty
, " label-index %u",
11058 bgp_static
->label_index
);
11060 if (bgp_static
->rmap
.name
)
11061 vty_out(vty
, " route-map %s",
11062 bgp_static
->rmap
.name
);
11064 if (bgp_static
->backdoor
)
11065 vty_out(vty
, " backdoor");
11068 vty_out(vty
, "\n");
11071 /* Aggregate-address configuration. */
11072 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11073 rn
= bgp_route_next(rn
))
11074 if ((bgp_aggregate
= rn
->info
) != NULL
) {
11077 /* "address-family" display. */
11078 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11080 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11081 && afi
== AFI_IP
) {
11082 struct in_addr netmask
;
11084 masklen2ip(p
->prefixlen
, &netmask
);
11085 vty_out(vty
, " aggregate-address %s %s",
11086 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11088 inet_ntoa(netmask
));
11090 vty_out(vty
, " aggregate-address %s/%d",
11091 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11096 if (bgp_aggregate
->as_set
)
11097 vty_out(vty
, " as-set");
11099 if (bgp_aggregate
->summary_only
)
11100 vty_out(vty
, " summary-only");
11102 vty_out(vty
, "\n");
11108 int bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11109 safi_t safi
, int *write
)
11111 struct bgp_node
*rn
;
11112 struct bgp_distance
*bdistance
;
11114 /* Distance configuration. */
11115 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11116 && bgp
->distance_local
[afi
][safi
]
11117 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11118 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11119 || bgp
->distance_local
[afi
][safi
]
11120 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11121 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11122 vty_out(vty
, " distance bgp %d %d %d\n",
11123 bgp
->distance_ebgp
[afi
][safi
],
11124 bgp
->distance_ibgp
[afi
][safi
],
11125 bgp
->distance_local
[afi
][safi
]);
11128 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11129 rn
= bgp_route_next(rn
))
11130 if ((bdistance
= rn
->info
) != NULL
) {
11131 char buf
[PREFIX_STRLEN
];
11133 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11134 vty_out(vty
, " distance %d %s %s\n",
11135 bdistance
->distance
,
11136 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11137 bdistance
->access_list
? bdistance
->access_list
11144 /* Allocate routing table structure and install commands. */
11145 void bgp_route_init(void)
11150 /* Init BGP distance table. */
11151 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11152 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
11153 bgp_distance_table
[afi
][safi
] =
11154 bgp_table_init(afi
, safi
);
11156 /* IPv4 BGP commands. */
11157 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11158 install_element(BGP_NODE
, &bgp_network_cmd
);
11159 install_element(BGP_NODE
, &bgp_network_mask_cmd
);
11160 install_element(BGP_NODE
, &bgp_network_mask_natural_cmd
);
11161 install_element(BGP_NODE
, &bgp_network_route_map_cmd
);
11162 install_element(BGP_NODE
, &bgp_network_mask_route_map_cmd
);
11163 install_element(BGP_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11164 install_element(BGP_NODE
, &bgp_network_backdoor_cmd
);
11165 install_element(BGP_NODE
, &bgp_network_mask_backdoor_cmd
);
11166 install_element(BGP_NODE
, &bgp_network_mask_natural_backdoor_cmd
);
11167 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11168 install_element(BGP_NODE
, &no_bgp_network_cmd
);
11169 install_element(BGP_NODE
, &no_bgp_network_mask_cmd
);
11170 install_element(BGP_NODE
, &no_bgp_network_mask_natural_cmd
);
11172 install_element(BGP_NODE
, &aggregate_address_cmd
);
11173 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11174 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11175 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11177 /* IPv4 unicast configuration. */
11178 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11179 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11180 install_element(BGP_IPV4_NODE
, &bgp_network_mask_cmd
);
11181 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_cmd
);
11182 install_element(BGP_IPV4_NODE
, &bgp_network_route_map_cmd
);
11183 install_element(BGP_IPV4_NODE
, &bgp_network_mask_route_map_cmd
);
11184 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11185 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_cmd
);
11186 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_route_map_cmd
);
11187 install_element(BGP_IPV4_NODE
, &no_bgp_network_label_index_cmd
);
11188 install_element(BGP_IPV4_NODE
,
11189 &no_bgp_network_label_index_route_map_cmd
);
11190 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11191 install_element(BGP_IPV4_NODE
, &no_bgp_network_cmd
);
11192 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_cmd
);
11193 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_natural_cmd
);
11195 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11196 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11197 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11198 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11200 /* IPv4 multicast configuration. */
11201 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11202 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11203 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_cmd
);
11204 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_natural_cmd
);
11205 install_element(BGP_IPV4M_NODE
, &bgp_network_route_map_cmd
);
11206 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_route_map_cmd
);
11207 install_element(BGP_IPV4M_NODE
,
11208 &bgp_network_mask_natural_route_map_cmd
);
11209 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11210 install_element(BGP_IPV4M_NODE
, &no_bgp_network_cmd
);
11211 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_cmd
);
11212 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_natural_cmd
);
11213 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11214 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11215 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11216 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11218 /* IPv4 labeled-unicast configuration. */
11219 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11220 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11221 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11222 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11224 install_element(VIEW_NODE
,
11225 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11226 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11227 install_element(VIEW_NODE
,
11228 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11229 #ifdef KEEP_OLD_VPN_COMMANDS
11230 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11231 #endif /* KEEP_OLD_VPN_COMMANDS */
11232 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11233 install_element(VIEW_NODE
,
11234 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11236 /* BGP dampening clear commands */
11237 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11238 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11240 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11241 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11244 install_element(ENABLE_NODE
,
11245 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11246 #ifdef KEEP_OLD_VPN_COMMANDS
11247 install_element(ENABLE_NODE
,
11248 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11249 #endif /* KEEP_OLD_VPN_COMMANDS */
11251 /* New config IPv6 BGP commands. */
11252 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11253 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11254 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_route_map_cmd
);
11255 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11256 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_cmd
);
11257 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_label_index_cmd
);
11258 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_label_index_cmd
);
11259 install_element(BGP_IPV6_NODE
,
11260 &ipv6_bgp_network_label_index_route_map_cmd
);
11261 install_element(BGP_IPV6_NODE
,
11262 &no_ipv6_bgp_network_label_index_route_map_cmd
);
11264 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11265 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11267 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11268 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_network_cmd
);
11270 install_element(BGP_IPV6L_NODE
, &bgp_table_map_cmd
);
11271 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
11272 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_route_map_cmd
);
11273 install_element(BGP_IPV6L_NODE
, &no_bgp_table_map_cmd
);
11274 install_element(BGP_IPV6L_NODE
, &no_ipv6_bgp_network_cmd
);
11276 install_element(BGP_NODE
, &bgp_distance_cmd
);
11277 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11278 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11279 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11280 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11281 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11282 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11283 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11284 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11285 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11286 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11287 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11288 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11289 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11290 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11291 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11292 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11293 install_element(BGP_IPV4M_NODE
,
11294 &no_bgp_distance_source_access_list_cmd
);
11295 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11296 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11297 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11298 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11299 install_element(BGP_IPV6_NODE
,
11300 &ipv6_bgp_distance_source_access_list_cmd
);
11301 install_element(BGP_IPV6_NODE
,
11302 &no_ipv6_bgp_distance_source_access_list_cmd
);
11303 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11304 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11305 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11306 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11307 install_element(BGP_IPV6M_NODE
,
11308 &ipv6_bgp_distance_source_access_list_cmd
);
11309 install_element(BGP_IPV6M_NODE
,
11310 &no_ipv6_bgp_distance_source_access_list_cmd
);
11312 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11313 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11314 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11315 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11317 /* IPv4 Multicast Mode */
11318 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11319 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11321 /* Large Communities */
11322 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11323 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11326 void bgp_route_finish(void)
11331 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11332 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
11333 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11334 bgp_distance_table
[afi
][safi
] = NULL
;