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 */
1920 && CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1921 PEER_STATUS_ORF_WAIT_REFRESH
))
1924 memset(&attr
, 0, sizeof(struct attr
));
1925 /* It's initialized in bgp_announce_check() */
1927 /* Announcement to the subgroup. If the route is filtered withdraw it.
1930 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1931 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1933 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1934 selected
->addpath_tx_id
);
1937 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1939 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1946 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1947 * This is called at the end of route processing.
1949 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1951 struct bgp_info
*ri
;
1953 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1954 if (BGP_INFO_HOLDDOWN(ri
))
1956 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1957 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
1962 * Has the route changed from the RIB's perspective? This is invoked only
1963 * if the route selection returns the same best route as earlier - to
1964 * determine if we need to update zebra or not.
1966 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
1968 struct bgp_info
*mpinfo
;
1970 /* If this is multipath, check all selected paths for any nexthop change
1972 * attribute change. Some attribute changes (e.g., community) aren't of
1973 * relevance to the RIB, but we'll update zebra to ensure we handle the
1974 * case of BGP nexthop change. This is the behavior when the best path
1976 * an attribute change anyway.
1978 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
1979 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
1982 /* If this is multipath, check all selected paths for any nexthop change
1984 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
1985 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
1986 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
1987 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
1991 /* Nothing has changed from the RIB's perspective. */
1995 struct bgp_process_queue
{
1997 struct bgp_node
*rn
;
2002 static wq_item_status
bgp_process_main(struct work_queue
*wq
, void *data
)
2004 struct bgp_process_queue
*pq
= data
;
2005 struct bgp
*bgp
= pq
->bgp
;
2006 struct bgp_node
*rn
= pq
->rn
;
2007 afi_t afi
= pq
->afi
;
2008 safi_t safi
= pq
->safi
;
2009 struct prefix
*p
= &rn
->p
;
2010 struct bgp_info
*new_select
;
2011 struct bgp_info
*old_select
;
2012 struct bgp_info_pair old_and_new
;
2014 /* Is it end of initial update? (after startup) */
2016 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2017 sizeof(bgp
->update_delay_zebra_resume_time
));
2019 bgp
->main_zebra_update_hold
= 0;
2020 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
2021 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
2022 if (bgp_fibupd_safi(safi
))
2023 bgp_zebra_announce_table(bgp
, afi
,
2026 bgp
->main_peers_update_hold
= 0;
2028 bgp_start_routeadv(bgp
);
2032 /* Best path selection. */
2033 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2035 old_select
= old_and_new
.old
;
2036 new_select
= old_and_new
.new;
2038 /* Do we need to allocate or free labels?
2039 * Right now, since we only deal with per-prefix labels, it is not
2041 * to do this upon changes to best path except of the label index
2044 if (safi
== SAFI_UNICAST
) {
2047 || bgp_label_index_differs(new_select
, old_select
)
2048 || new_select
->sub_type
!= old_select
->sub_type
) {
2049 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2050 && new_select
->attr
->flag
2052 BGP_ATTR_PREFIX_SID
)
2053 && new_select
->attr
->label_index
2054 != BGP_INVALID_LABEL_INDEX
) {
2057 BGP_NODE_REGISTERED_FOR_LABEL
))
2058 bgp_unregister_for_label(rn
);
2059 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2061 bgp_set_valid_label(&rn
->local_label
);
2063 bgp_register_for_label(rn
, new_select
);
2065 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
2066 bgp_unregister_for_label(rn
);
2069 /* If best route remains the same and this is not due to user-initiated
2070 * clear, see exactly what needs to be done.
2073 if (old_select
&& old_select
== new_select
2074 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2075 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2076 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2077 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2079 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2080 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2082 if (bgp_fibupd_safi(safi
) && !bgp
->name
2083 && !bgp_option_check(BGP_OPT_NO_FIB
)
2084 && new_select
->type
== ZEBRA_ROUTE_BGP
2085 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2086 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2089 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2090 bgp_zebra_clear_route_change_flags(rn
);
2092 /* If there is a change of interest to peers, reannounce the
2094 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2095 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2096 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2098 /* unicast routes must also be annouced to
2099 * labeled-unicast update-groups */
2100 if (safi
== SAFI_UNICAST
)
2101 group_announce_route(bgp
, afi
,
2102 SAFI_LABELED_UNICAST
, rn
,
2105 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2106 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2109 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2113 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2115 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2117 /* bestpath has changed; bump version */
2118 if (old_select
|| new_select
) {
2119 bgp_bump_version(rn
);
2121 if (!bgp
->t_rmap_def_originate_eval
) {
2125 update_group_refresh_default_originate_route_map
,
2126 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2127 &bgp
->t_rmap_def_originate_eval
);
2132 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2134 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2135 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2136 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2140 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2141 if (old_select
!= new_select
) {
2143 vnc_import_bgp_exterior_del_route(bgp
, p
,
2145 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2148 vnc_import_bgp_exterior_add_route(bgp
, p
,
2150 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2156 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2158 /* unicast routes must also be annouced to labeled-unicast update-groups
2160 if (safi
== SAFI_UNICAST
)
2161 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2165 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2166 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2167 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2168 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2169 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2170 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2172 /* Withdraw the route from the kernel. */
2173 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2174 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2175 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2176 bgp_zebra_withdraw(p
, old_select
, safi
);
2180 /* Clear any route change flags. */
2181 bgp_zebra_clear_route_change_flags(rn
);
2183 /* Reap old select bgp_info, if it has been removed */
2184 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2185 bgp_info_reap(rn
, old_select
);
2187 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2191 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2193 struct bgp_process_queue
*pq
= data
;
2194 struct bgp_table
*table
;
2196 bgp_unlock(pq
->bgp
);
2198 table
= bgp_node_table(pq
->rn
);
2199 bgp_unlock_node(pq
->rn
);
2200 bgp_table_unlock(table
);
2202 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pq
);
2205 void bgp_process_queue_init(void)
2207 if (!bm
->process_main_queue
) {
2208 bm
->process_main_queue
=
2209 work_queue_new(bm
->master
, "process_main_queue");
2211 if (!bm
->process_main_queue
) {
2212 zlog_err("%s: Failed to allocate work queue", __func__
);
2217 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_main
;
2218 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2219 bm
->process_main_queue
->spec
.max_retries
= 0;
2220 bm
->process_main_queue
->spec
.hold
= 50;
2221 /* Use a higher yield value of 50ms for main queue processing */
2222 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2225 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2227 struct bgp_process_queue
*pqnode
;
2229 /* already scheduled for processing? */
2230 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2233 if (bm
->process_main_queue
== NULL
)
2236 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2237 sizeof(struct bgp_process_queue
));
2241 /* all unlocked in bgp_processq_del */
2242 bgp_table_lock(bgp_node_table(rn
));
2243 pqnode
->rn
= bgp_lock_node(rn
);
2247 pqnode
->safi
= safi
;
2248 work_queue_add(bm
->process_main_queue
, pqnode
);
2249 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2253 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2255 struct bgp_process_queue
*pqnode
;
2257 if (bm
->process_main_queue
== NULL
)
2260 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2261 sizeof(struct bgp_process_queue
));
2268 work_queue_add(bm
->process_main_queue
, pqnode
);
2271 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2275 peer
= THREAD_ARG(thread
);
2276 peer
->t_pmax_restart
= NULL
;
2278 if (bgp_debug_neighbor_events(peer
))
2280 "%s Maximum-prefix restart timer expired, restore peering",
2283 peer_clear(peer
, NULL
);
2288 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2294 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2297 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2298 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2299 PEER_STATUS_PREFIX_LIMIT
)
2304 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2306 afi_safi_print(afi
, safi
), peer
->host
,
2307 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2308 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2310 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2311 PEER_FLAG_MAX_PREFIX_WARNING
))
2314 /* Convert AFI, SAFI to values for packet. */
2315 pkt_afi
= afi_int2iana(afi
);
2316 pkt_safi
= safi_int2iana(safi
);
2320 ndata
[0] = (pkt_afi
>> 8);
2322 ndata
[2] = pkt_safi
;
2323 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2324 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2325 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2326 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2328 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2329 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2330 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2334 /* Dynamic peers will just close their connection. */
2335 if (peer_dynamic_neighbor(peer
))
2338 /* restart timer start */
2339 if (peer
->pmax_restart
[afi
][safi
]) {
2340 peer
->v_pmax_restart
=
2341 peer
->pmax_restart
[afi
][safi
] * 60;
2343 if (bgp_debug_neighbor_events(peer
))
2345 "%s Maximum-prefix restart timer started for %d secs",
2346 peer
->host
, peer
->v_pmax_restart
);
2348 BGP_TIMER_ON(peer
->t_pmax_restart
,
2349 bgp_maximum_prefix_restart_timer
,
2350 peer
->v_pmax_restart
);
2355 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2356 PEER_STATUS_PREFIX_LIMIT
);
2358 if (peer
->pcount
[afi
][safi
]
2359 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2360 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2361 PEER_STATUS_PREFIX_THRESHOLD
)
2366 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2367 afi_safi_print(afi
, safi
), peer
->host
,
2368 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2369 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2370 PEER_STATUS_PREFIX_THRESHOLD
);
2372 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2373 PEER_STATUS_PREFIX_THRESHOLD
);
2377 /* Unconditionally remove the route from the RIB, without taking
2378 * damping into consideration (eg, because the session went down)
2380 static void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
,
2381 struct peer
*peer
, afi_t afi
, safi_t safi
)
2383 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2385 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2386 bgp_info_delete(rn
, ri
); /* keep historical info */
2388 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2391 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2392 struct peer
*peer
, afi_t afi
, safi_t safi
,
2393 struct prefix_rd
*prd
)
2395 int status
= BGP_DAMP_NONE
;
2397 /* apply dampening, if result is suppressed, we'll be retaining
2398 * the bgp_info in the RIB for historical reference.
2400 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2401 && peer
->sort
== BGP_PEER_EBGP
)
2402 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2403 == BGP_DAMP_SUPPRESSED
) {
2404 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2410 if (safi
== SAFI_MPLS_VPN
) {
2411 struct bgp_node
*prn
= NULL
;
2412 struct bgp_table
*table
= NULL
;
2414 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2415 (struct prefix
*)prd
);
2417 table
= (struct bgp_table
*)(prn
->info
);
2419 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2420 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2422 bgp_unlock_node(prn
);
2424 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2425 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2427 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2428 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2434 /* If this is an EVPN route, process for un-import. */
2435 if (safi
== SAFI_EVPN
)
2436 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2438 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2441 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2442 struct peer
*peer
, struct attr
*attr
,
2443 struct bgp_node
*rn
)
2445 struct bgp_info
*new;
2447 /* Make new BGP info. */
2448 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2450 new->instance
= instance
;
2451 new->sub_type
= sub_type
;
2454 new->uptime
= bgp_clock();
2456 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2460 static void overlay_index_update(struct attr
*attr
,
2461 struct eth_segment_id
*eth_s_id
,
2462 union gw_addr
*gw_ip
)
2467 if (eth_s_id
== NULL
) {
2468 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2469 sizeof(struct eth_segment_id
));
2471 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2472 sizeof(struct eth_segment_id
));
2474 if (gw_ip
== NULL
) {
2475 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2477 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2478 sizeof(union gw_addr
));
2482 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2483 struct eth_segment_id
*eth_s_id
,
2484 union gw_addr
*gw_ip
)
2486 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2487 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2490 if (afi
!= AFI_L2VPN
)
2493 memset(&temp
, 0, 16);
2494 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2495 info_gw_ip
= (union gw_addr
*)&temp
;
2496 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2499 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2500 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2503 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2505 info_gw_ip_remote
= gw_ip
;
2506 if (eth_s_id
== NULL
)
2507 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2509 info_eth_s_id_remote
= eth_s_id
;
2510 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2512 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2513 sizeof(struct eth_segment_id
));
2516 /* Check if received nexthop is valid or not. */
2517 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2522 /* Only validated for unicast and multicast currently. */
2523 /* Also valid for EVPN where the nexthop is an IP address. */
2524 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2527 /* If NEXT_HOP is present, validate it. */
2528 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2529 if (attr
->nexthop
.s_addr
== 0
2530 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2531 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2535 /* If MP_NEXTHOP is present, validate it. */
2536 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2537 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2538 * it is not an IPv6 link-local address.
2540 if (attr
->mp_nexthop_len
) {
2541 switch (attr
->mp_nexthop_len
) {
2542 case BGP_ATTR_NHLEN_IPV4
:
2543 case BGP_ATTR_NHLEN_VPNV4
:
2544 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2545 || IPV4_CLASS_DE(ntohl(
2546 attr
->mp_nexthop_global_in
.s_addr
))
2547 || bgp_nexthop_self(bgp
,
2548 attr
->mp_nexthop_global_in
));
2551 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2552 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2553 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2554 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2555 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2556 || IN6_IS_ADDR_MULTICAST(
2557 &attr
->mp_nexthop_global
));
2569 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2570 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2571 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2572 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2575 int aspath_loop_count
= 0;
2576 struct bgp_node
*rn
;
2578 struct attr new_attr
;
2579 struct attr
*attr_new
;
2580 struct bgp_info
*ri
;
2581 struct bgp_info
*new;
2583 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2586 int do_loop_check
= 1;
2587 int has_valid_label
= 0;
2589 int vnc_implicit_withdraw
= 0;
2593 memset(&new_attr
, 0, sizeof(struct attr
));
2594 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2595 new_attr
.label
= MPLS_INVALID_LABEL
;
2598 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2599 has_valid_label
= bgp_is_valid_label(label
);
2601 if (has_valid_label
)
2602 sprintf(label_buf
, "label %u", label_pton(label
));
2604 /* When peer's soft reconfiguration enabled. Record input packet in
2607 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2608 && peer
!= bgp
->peer_self
)
2609 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2611 /* Check previously received route. */
2612 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2613 if (ri
->peer
== peer
&& ri
->type
== type
2614 && ri
->sub_type
== sub_type
2615 && ri
->addpath_rx_id
== addpath_id
)
2618 /* AS path local-as loop check. */
2619 if (peer
->change_local_as
) {
2620 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2621 aspath_loop_count
= 1;
2623 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2624 > aspath_loop_count
) {
2625 reason
= "as-path contains our own AS;";
2630 /* If the peer is configured for "allowas-in origin" and the last ASN in
2632 * as-path is our ASN then we do not need to call aspath_loop_check
2634 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2635 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2638 /* AS path loop check. */
2639 if (do_loop_check
) {
2640 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2641 > peer
->allowas_in
[afi
][safi
]
2642 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2643 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2644 > peer
->allowas_in
[afi
][safi
])) {
2645 reason
= "as-path contains our own AS;";
2650 /* Route reflector originator ID check. */
2651 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2652 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2653 reason
= "originator is us;";
2657 /* Route reflector cluster ID check. */
2658 if (bgp_cluster_filter(peer
, attr
)) {
2659 reason
= "reflected from the same cluster;";
2663 /* Apply incoming filter. */
2664 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2669 bgp_attr_dup(&new_attr
, attr
);
2671 /* Apply incoming route-map.
2672 * NB: new_attr may now contain newly allocated values from route-map
2674 * commands, so we need bgp_attr_flush in the error paths, until we
2676 * the attr (which takes over the memory references) */
2677 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2679 reason
= "route-map;";
2680 bgp_attr_flush(&new_attr
);
2684 /* next hop check. */
2685 if (bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2686 reason
= "martian or self next-hop;";
2687 bgp_attr_flush(&new_attr
);
2691 attr_new
= bgp_attr_intern(&new_attr
);
2693 /* If the update is implicit withdraw. */
2695 ri
->uptime
= bgp_clock();
2696 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2698 /* Same attribute comes in. */
2699 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2700 && attrhash_cmp(ri
->attr
, attr_new
)
2701 && (!has_valid_label
2702 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2705 && (overlay_index_equal(
2706 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2707 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2708 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2709 BGP_CONFIG_DAMPENING
)
2710 && peer
->sort
== BGP_PEER_EBGP
2711 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2712 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2713 bgp_debug_rdpfxpath2str(
2714 afi
, safi
, prd
, p
, label
,
2715 addpath_id
? 1 : 0, addpath_id
,
2716 pfx_buf
, sizeof(pfx_buf
));
2717 zlog_debug("%s rcvd %s", peer
->host
,
2721 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2722 != BGP_DAMP_SUPPRESSED
) {
2723 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2725 bgp_process(bgp
, rn
, afi
, safi
);
2727 } else /* Duplicate - odd */
2729 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2730 if (!peer
->rcvd_attr_printed
) {
2732 "%s rcvd UPDATE w/ attr: %s",
2734 peer
->rcvd_attr_str
);
2735 peer
->rcvd_attr_printed
= 1;
2738 bgp_debug_rdpfxpath2str(
2739 afi
, safi
, prd
, p
, label
,
2740 addpath_id
? 1 : 0, addpath_id
,
2741 pfx_buf
, sizeof(pfx_buf
));
2743 "%s rcvd %s...duplicate ignored",
2744 peer
->host
, pfx_buf
);
2747 /* graceful restart STALE flag unset. */
2748 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2749 bgp_info_unset_flag(rn
, ri
,
2751 bgp_process(bgp
, rn
, afi
, safi
);
2755 bgp_unlock_node(rn
);
2756 bgp_attr_unintern(&attr_new
);
2761 /* Withdraw/Announce before we fully processed the withdraw */
2762 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2763 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2764 bgp_debug_rdpfxpath2str(
2765 afi
, safi
, prd
, p
, label
,
2766 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2769 "%s rcvd %s, flapped quicker than processing",
2770 peer
->host
, pfx_buf
);
2773 bgp_info_restore(rn
, ri
);
2776 /* Received Logging. */
2777 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2778 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2779 addpath_id
? 1 : 0, addpath_id
,
2780 pfx_buf
, sizeof(pfx_buf
));
2781 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2784 /* graceful restart STALE flag unset. */
2785 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2786 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2788 /* The attribute is changed. */
2789 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2791 /* implicit withdraw, decrement aggregate and pcount here.
2792 * only if update is accepted, they'll increment below.
2794 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2796 /* Update bgp route dampening information. */
2797 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2798 && peer
->sort
== BGP_PEER_EBGP
) {
2799 /* This is implicit withdraw so we should update
2802 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2803 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2806 if (safi
== SAFI_MPLS_VPN
) {
2807 struct bgp_node
*prn
= NULL
;
2808 struct bgp_table
*table
= NULL
;
2810 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2811 (struct prefix
*)prd
);
2813 table
= (struct bgp_table
*)(prn
->info
);
2815 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2816 bgp
, prd
, table
, p
, ri
);
2818 bgp_unlock_node(prn
);
2820 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2821 && (safi
== SAFI_UNICAST
)) {
2822 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2824 * Implicit withdraw case.
2826 ++vnc_implicit_withdraw
;
2827 vnc_import_bgp_del_route(bgp
, p
, ri
);
2828 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2833 /* Special handling for EVPN update of an existing route. If the
2834 * extended community attribute has changed, we need to
2836 * the route using its existing extended community. It will be
2837 * subsequently processed for import with the new extended
2840 if (safi
== SAFI_EVPN
&& !same_attr
) {
2842 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2844 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2847 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2848 attr_new
->ecommunity
);
2850 if (bgp_debug_update(peer
, p
, NULL
, 1))
2852 "Change in EXT-COMM, existing %s new %s",
2854 ri
->attr
->ecommunity
),
2856 attr_new
->ecommunity
));
2857 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2863 /* Update to new attribute. */
2864 bgp_attr_unintern(&ri
->attr
);
2865 ri
->attr
= attr_new
;
2867 /* Update MPLS label */
2868 if (has_valid_label
) {
2869 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2871 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2875 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2876 && (safi
== SAFI_UNICAST
)) {
2877 if (vnc_implicit_withdraw
) {
2879 * Add back the route with its new attributes
2881 * The route is still selected, until the route
2883 * queued by bgp_process actually runs. We have
2885 * update to the VNC side immediately to avoid
2887 * configuration changes (e.g., route-map
2889 * trigger re-importation of the entire RIB.
2891 vnc_import_bgp_add_route(bgp
, p
, ri
);
2892 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
2896 /* Update Overlay Index */
2897 if (afi
== AFI_L2VPN
) {
2898 overlay_index_update(
2899 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2900 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
2903 /* Update bgp route dampening information. */
2904 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2905 && peer
->sort
== BGP_PEER_EBGP
) {
2906 /* Now we do normal update dampening. */
2907 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
2908 if (ret
== BGP_DAMP_SUPPRESSED
) {
2909 bgp_unlock_node(rn
);
2914 /* Nexthop reachability check - for unicast and
2915 * labeled-unicast.. */
2916 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2917 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
2918 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
2919 && !CHECK_FLAG(peer
->flags
,
2920 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
2922 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
2927 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
2929 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2931 if (BGP_DEBUG(nht
, NHT
)) {
2932 char buf1
[INET6_ADDRSTRLEN
];
2934 (const void *)&attr_new
2936 buf1
, INET6_ADDRSTRLEN
);
2937 zlog_debug("%s(%s): NH unresolved",
2938 __FUNCTION__
, buf1
);
2940 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
2943 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
2946 if (safi
== SAFI_MPLS_VPN
) {
2947 struct bgp_node
*prn
= NULL
;
2948 struct bgp_table
*table
= NULL
;
2950 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2951 (struct prefix
*)prd
);
2953 table
= (struct bgp_table
*)(prn
->info
);
2955 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
2956 bgp
, prd
, table
, p
, ri
);
2958 bgp_unlock_node(prn
);
2962 /* If this is an EVPN route and some attribute has changed,
2964 * route for import. If the extended community has changed, we
2966 * have done the un-import earlier and the import would result
2968 * route getting injected into appropriate L2 VNIs. If it is
2970 * some other attribute change, the import will result in
2972 * the attributes for the route in the VNI(s).
2974 if (safi
== SAFI_EVPN
&& !same_attr
)
2975 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
2977 /* Process change. */
2978 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
2980 bgp_process(bgp
, rn
, afi
, safi
);
2981 bgp_unlock_node(rn
);
2984 if (SAFI_MPLS_VPN
== safi
) {
2985 mpls_label_t label_decoded
= decode_label(label
);
2987 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2988 type
, sub_type
, &label_decoded
);
2990 if (SAFI_ENCAP
== safi
) {
2991 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
2992 type
, sub_type
, NULL
);
2997 } // End of implicit withdraw
2999 /* Received Logging. */
3000 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3001 if (!peer
->rcvd_attr_printed
) {
3002 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3003 peer
->rcvd_attr_str
);
3004 peer
->rcvd_attr_printed
= 1;
3007 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3008 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3010 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3013 /* Make new BGP info. */
3014 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3016 /* Update MPLS label */
3017 if (has_valid_label
) {
3018 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3020 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3023 /* Update Overlay Index */
3024 if (afi
== AFI_L2VPN
) {
3025 overlay_index_update(new->attr
,
3026 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3027 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3029 /* Nexthop reachability check. */
3030 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3031 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3032 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3033 && !CHECK_FLAG(peer
->flags
,
3034 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3035 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3040 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
))
3041 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3043 if (BGP_DEBUG(nht
, NHT
)) {
3044 char buf1
[INET6_ADDRSTRLEN
];
3046 (const void *)&attr_new
->nexthop
,
3047 buf1
, INET6_ADDRSTRLEN
);
3048 zlog_debug("%s(%s): NH unresolved",
3049 __FUNCTION__
, buf1
);
3051 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3054 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3057 new->addpath_rx_id
= addpath_id
;
3059 /* Increment prefix */
3060 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3062 /* Register new BGP information. */
3063 bgp_info_add(rn
, new);
3065 /* route_node_get lock */
3066 bgp_unlock_node(rn
);
3069 if (safi
== SAFI_MPLS_VPN
) {
3070 struct bgp_node
*prn
= NULL
;
3071 struct bgp_table
*table
= NULL
;
3073 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3075 table
= (struct bgp_table
*)(prn
->info
);
3077 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3078 bgp
, prd
, table
, p
, new);
3080 bgp_unlock_node(prn
);
3084 /* If maximum prefix count is configured and current prefix
3086 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3089 /* If this is an EVPN route, process for import. */
3090 if (safi
== SAFI_EVPN
)
3091 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3093 /* Process change. */
3094 bgp_process(bgp
, rn
, afi
, safi
);
3097 if (SAFI_MPLS_VPN
== safi
) {
3098 mpls_label_t label_decoded
= decode_label(label
);
3100 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3101 sub_type
, &label_decoded
);
3103 if (SAFI_ENCAP
== safi
) {
3104 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3111 /* This BGP update is filtered. Log the reason then update BGP
3114 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3115 if (!peer
->rcvd_attr_printed
) {
3116 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3117 peer
->rcvd_attr_str
);
3118 peer
->rcvd_attr_printed
= 1;
3121 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3122 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3124 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3125 peer
->host
, pfx_buf
, reason
);
3129 /* If this is an EVPN route, un-import it as it is now filtered.
3131 if (safi
== SAFI_EVPN
)
3132 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3134 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3137 bgp_unlock_node(rn
);
3141 * Filtered update is treated as an implicit withdrawal (see
3143 * a few lines above)
3145 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3146 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3154 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3155 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3156 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3157 struct bgp_route_evpn
*evpn
)
3160 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3161 struct bgp_node
*rn
;
3162 struct bgp_info
*ri
;
3165 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3166 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3174 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3176 /* If peer is soft reconfiguration enabled. Record input packet for
3177 * further calculation.
3179 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3180 * routes that are filtered. This tanks out Quagga RS pretty badly due
3182 * the iteration over all RS clients.
3183 * Since we need to remove the entry from adj_in anyway, do that first
3185 * if there was no entry, we don't need to do anything more.
3187 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3188 && peer
!= bgp
->peer_self
)
3189 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3190 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3191 bgp_debug_rdpfxpath2str(
3192 afi
, safi
, prd
, p
, label
,
3193 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3196 "%s withdrawing route %s not in adj-in",
3197 peer
->host
, pfx_buf
);
3199 bgp_unlock_node(rn
);
3203 /* Lookup withdrawn route. */
3204 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3205 if (ri
->peer
== peer
&& ri
->type
== type
3206 && ri
->sub_type
== sub_type
3207 && ri
->addpath_rx_id
== addpath_id
)
3211 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3212 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3213 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3215 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3219 /* Withdraw specified route from routing table. */
3220 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3221 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3222 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3223 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3224 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3226 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3229 /* Unlock bgp_node_get() lock. */
3230 bgp_unlock_node(rn
);
3235 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3238 struct update_subgroup
*subgrp
;
3239 subgrp
= peer_subgroup(peer
, afi
, safi
);
3240 subgroup_default_originate(subgrp
, withdraw
);
3245 * bgp_stop_announce_route_timer
3247 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3249 if (!paf
->t_announce_route
)
3252 THREAD_TIMER_OFF(paf
->t_announce_route
);
3256 * bgp_announce_route_timer_expired
3258 * Callback that is invoked when the route announcement timer for a
3261 static int bgp_announce_route_timer_expired(struct thread
*t
)
3263 struct peer_af
*paf
;
3266 paf
= THREAD_ARG(t
);
3269 if (peer
->status
!= Established
)
3272 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3275 peer_af_announce_route(paf
, 1);
3280 * bgp_announce_route
3282 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3284 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3286 struct peer_af
*paf
;
3287 struct update_subgroup
*subgrp
;
3289 paf
= peer_af_find(peer
, afi
, safi
);
3292 subgrp
= PAF_SUBGRP(paf
);
3295 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3296 * or a refresh has already been triggered.
3298 if (!subgrp
|| paf
->t_announce_route
)
3302 * Start a timer to stagger/delay the announce. This serves
3303 * two purposes - announcement can potentially be combined for
3304 * multiple peers and the announcement doesn't happen in the
3307 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3308 (subgrp
->peer_count
== 1)
3309 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3310 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3311 &paf
->t_announce_route
);
3315 * Announce routes from all AF tables to a peer.
3317 * This should ONLY be called when there is a need to refresh the
3318 * routes to the peer based on a policy change for this peer alone
3319 * or a route refresh request received from the peer.
3320 * The operation will result in splitting the peer from its existing
3321 * subgroups and putting it in new subgroups.
3323 void bgp_announce_route_all(struct peer
*peer
)
3328 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3329 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3330 bgp_announce_route(peer
, afi
, safi
);
3333 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3334 struct bgp_table
*table
,
3335 struct prefix_rd
*prd
)
3338 struct bgp_node
*rn
;
3339 struct bgp_adj_in
*ain
;
3342 table
= peer
->bgp
->rib
[afi
][safi
];
3344 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3345 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3346 if (ain
->peer
== peer
) {
3347 struct bgp_info
*ri
= rn
->info
;
3348 mpls_label_t label
=
3349 (ri
&& ri
->extra
) ? ri
->extra
->label
3350 : MPLS_INVALID_LABEL
;
3353 peer
, &rn
->p
, ain
->addpath_rx_id
,
3354 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3355 BGP_ROUTE_NORMAL
, prd
, &label
, 1, NULL
);
3358 bgp_unlock_node(rn
);
3365 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3367 struct bgp_node
*rn
;
3368 struct bgp_table
*table
;
3370 if (peer
->status
!= Established
)
3373 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3374 && (safi
!= SAFI_EVPN
))
3375 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3377 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3378 rn
= bgp_route_next(rn
))
3379 if ((table
= rn
->info
) != NULL
) {
3380 struct prefix_rd prd
;
3381 prd
.family
= AF_UNSPEC
;
3383 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3385 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3391 struct bgp_clear_node_queue
{
3392 struct bgp_node
*rn
;
3395 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3397 struct bgp_clear_node_queue
*cnq
= data
;
3398 struct bgp_node
*rn
= cnq
->rn
;
3399 struct peer
*peer
= wq
->spec
.data
;
3400 struct bgp_info
*ri
;
3401 afi_t afi
= bgp_node_table(rn
)->afi
;
3402 safi_t safi
= bgp_node_table(rn
)->safi
;
3406 /* It is possible that we have multiple paths for a prefix from a peer
3407 * if that peer is using AddPath.
3409 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3410 if (ri
->peer
== peer
) {
3411 /* graceful restart STALE flag set. */
3412 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3413 && peer
->nsf
[afi
][safi
]
3414 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3415 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3416 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3418 /* If this is an EVPN route, process for
3420 if (safi
== SAFI_EVPN
)
3421 bgp_evpn_unimport_route(peer
->bgp
, afi
,
3424 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3430 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3432 struct bgp_clear_node_queue
*cnq
= data
;
3433 struct bgp_node
*rn
= cnq
->rn
;
3434 struct bgp_table
*table
= bgp_node_table(rn
);
3436 bgp_unlock_node(rn
);
3437 bgp_table_unlock(table
);
3438 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3441 static void bgp_clear_node_complete(struct work_queue
*wq
)
3443 struct peer
*peer
= wq
->spec
.data
;
3445 /* Tickle FSM to start moving again */
3446 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3448 peer_unlock(peer
); /* bgp_clear_route */
3451 static void bgp_clear_node_queue_init(struct peer
*peer
)
3453 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3455 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3456 #undef CLEAR_QUEUE_NAME_LEN
3458 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3460 zlog_err("%s: Failed to allocate work queue", __func__
);
3463 peer
->clear_node_queue
->spec
.hold
= 10;
3464 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3465 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3466 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3467 peer
->clear_node_queue
->spec
.max_retries
= 0;
3469 /* we only 'lock' this peer reference when the queue is actually active
3471 peer
->clear_node_queue
->spec
.data
= peer
;
3474 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3475 struct bgp_table
*table
)
3477 struct bgp_node
*rn
;
3478 int force
= bm
->process_main_queue
? 0 : 1;
3481 table
= peer
->bgp
->rib
[afi
][safi
];
3483 /* If still no table => afi/safi isn't configured at all or smth. */
3487 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3488 struct bgp_info
*ri
, *next
;
3489 struct bgp_adj_in
*ain
;
3490 struct bgp_adj_in
*ain_next
;
3492 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3493 * queued for every clearing peer, regardless of whether it is
3494 * relevant to the peer at hand.
3496 * Overview: There are 3 different indices which need to be
3497 * scrubbed, potentially, when a peer is removed:
3499 * 1 peer's routes visible via the RIB (ie accepted routes)
3500 * 2 peer's routes visible by the (optional) peer's adj-in index
3501 * 3 other routes visible by the peer's adj-out index
3503 * 3 there is no hurry in scrubbing, once the struct peer is
3504 * removed from bgp->peer, we could just GC such deleted peer's
3505 * adj-outs at our leisure.
3507 * 1 and 2 must be 'scrubbed' in some way, at least made
3508 * invisible via RIB index before peer session is allowed to be
3509 * brought back up. So one needs to know when such a 'search' is
3514 * - there'd be a single global queue or a single RIB walker
3515 * - rather than tracking which route_nodes still need to be
3516 * examined on a peer basis, we'd track which peers still
3519 * Given that our per-peer prefix-counts now should be reliable,
3520 * this may actually be achievable. It doesn't seem to be a huge
3521 * problem at this time,
3523 * It is possible that we have multiple paths for a prefix from
3525 * if that peer is using AddPath.
3529 ain_next
= ain
->next
;
3531 if (ain
->peer
== peer
) {
3532 bgp_adj_in_remove(rn
, ain
);
3533 bgp_unlock_node(rn
);
3539 for (ri
= rn
->info
; ri
; ri
= next
) {
3541 if (ri
->peer
!= peer
)
3545 bgp_info_reap(rn
, ri
);
3547 struct bgp_clear_node_queue
*cnq
;
3549 /* both unlocked in bgp_clear_node_queue_del */
3550 bgp_table_lock(bgp_node_table(rn
));
3553 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3554 sizeof(struct bgp_clear_node_queue
));
3556 work_queue_add(peer
->clear_node_queue
, cnq
);
3564 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3566 struct bgp_node
*rn
;
3567 struct bgp_table
*table
;
3569 if (peer
->clear_node_queue
== NULL
)
3570 bgp_clear_node_queue_init(peer
);
3572 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3573 * Idle until it receives a Clearing_Completed event. This protects
3574 * against peers which flap faster than we can we clear, which could
3577 * a) race with routes from the new session being installed before
3578 * clear_route_node visits the node (to delete the route of that
3580 * b) resource exhaustion, clear_route_node likely leads to an entry
3581 * on the process_main queue. Fast-flapping could cause that queue
3585 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3586 * the unlock will happen upon work-queue completion; other wise, the
3587 * unlock happens at the end of this function.
3589 if (!peer
->clear_node_queue
->thread
)
3592 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3593 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3595 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3596 rn
= bgp_route_next(rn
))
3597 if ((table
= rn
->info
) != NULL
)
3598 bgp_clear_route_table(peer
, afi
, safi
, table
);
3600 /* unlock if no nodes got added to the clear-node-queue. */
3601 if (!peer
->clear_node_queue
->thread
)
3605 void bgp_clear_route_all(struct peer
*peer
)
3610 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3611 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3612 bgp_clear_route(peer
, afi
, safi
);
3615 rfapiProcessPeerDown(peer
);
3619 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3621 struct bgp_table
*table
;
3622 struct bgp_node
*rn
;
3623 struct bgp_adj_in
*ain
;
3624 struct bgp_adj_in
*ain_next
;
3626 table
= peer
->bgp
->rib
[afi
][safi
];
3628 /* It is possible that we have multiple paths for a prefix from a peer
3629 * if that peer is using AddPath.
3631 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3635 ain_next
= ain
->next
;
3637 if (ain
->peer
== peer
) {
3638 bgp_adj_in_remove(rn
, ain
);
3639 bgp_unlock_node(rn
);
3647 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3649 struct bgp_node
*rn
;
3650 struct bgp_info
*ri
;
3651 struct bgp_table
*table
;
3653 if (safi
== SAFI_MPLS_VPN
) {
3654 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3655 rn
= bgp_route_next(rn
)) {
3656 struct bgp_node
*rm
;
3657 struct bgp_info
*ri
;
3659 /* look for neighbor in tables */
3660 if ((table
= rn
->info
) != NULL
) {
3661 for (rm
= bgp_table_top(table
); rm
;
3662 rm
= bgp_route_next(rm
))
3663 for (ri
= rm
->info
; ri
; ri
= ri
->next
)
3664 if (ri
->peer
== peer
) {
3678 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3679 rn
= bgp_route_next(rn
))
3680 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3681 if (ri
->peer
== peer
) {
3682 if (CHECK_FLAG(ri
->flags
,
3684 bgp_rib_remove(rn
, ri
, peer
,
3691 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3693 struct bgp_node
*rn
;
3694 struct bgp_info
*ri
;
3695 struct bgp_info
*next
;
3697 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3698 for (ri
= rn
->info
; ri
; ri
= next
) {
3700 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3701 && ri
->type
== ZEBRA_ROUTE_BGP
3702 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3703 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3704 if (bgp_fibupd_safi(safi
))
3705 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3706 bgp_info_reap(rn
, ri
);
3711 /* Delete all kernel routes. */
3712 void bgp_cleanup_routes(struct bgp
*bgp
)
3715 struct bgp_node
*rn
;
3717 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3718 if (afi
== AFI_L2VPN
)
3720 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3722 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3724 if (afi
!= AFI_L2VPN
) {
3726 safi
= SAFI_MPLS_VPN
;
3727 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3728 rn
= bgp_route_next(rn
)) {
3731 (struct bgp_table
*)(rn
->info
),
3733 bgp_table_finish((struct bgp_table
**)&(
3736 bgp_unlock_node(rn
);
3740 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3741 rn
= bgp_route_next(rn
)) {
3744 (struct bgp_table
*)(rn
->info
),
3746 bgp_table_finish((struct bgp_table
**)&(
3749 bgp_unlock_node(rn
);
3754 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3755 rn
= bgp_route_next(rn
)) {
3757 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3759 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3761 bgp_unlock_node(rn
);
3766 void bgp_reset(void)
3769 bgp_zclient_reset();
3770 access_list_reset();
3771 prefix_list_reset();
3774 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3776 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3777 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3778 PEER_CAP_ADDPATH_AF_TX_RCV
));
3781 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3783 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3784 struct bgp_nlri
*packet
)
3793 int addpath_encoded
;
3794 u_int32_t addpath_id
;
3796 /* Check peer status. */
3797 if (peer
->status
!= Established
)
3801 lim
= pnt
+ packet
->length
;
3803 safi
= packet
->safi
;
3805 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3807 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3808 syntactic validity. If the field is syntactically incorrect,
3809 then the Error Subcode is set to Invalid Network Field. */
3810 for (; pnt
< lim
; pnt
+= psize
) {
3811 /* Clear prefix structure. */
3812 memset(&p
, 0, sizeof(struct prefix
));
3814 if (addpath_encoded
) {
3816 /* When packet overflow occurs return immediately. */
3817 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3820 addpath_id
= ntohl(*((uint32_t *)pnt
));
3821 pnt
+= BGP_ADDPATH_ID_LEN
;
3824 /* Fetch prefix length. */
3825 p
.prefixlen
= *pnt
++;
3826 /* afi/safi validity already verified by caller,
3827 * bgp_update_receive */
3828 p
.family
= afi2family(afi
);
3830 /* Prefix length check. */
3831 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3833 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3834 peer
->host
, p
.prefixlen
, packet
->afi
);
3838 /* Packet size overflow check. */
3839 psize
= PSIZE(p
.prefixlen
);
3841 /* When packet overflow occur return immediately. */
3842 if (pnt
+ psize
> lim
) {
3844 "%s [Error] Update packet error (prefix length %d overflows packet)",
3845 peer
->host
, p
.prefixlen
);
3849 /* Defensive coding, double-check the psize fits in a struct
3851 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3853 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3854 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3858 /* Fetch prefix from NLRI packet. */
3859 memcpy(&p
.u
.prefix
, pnt
, psize
);
3861 /* Check address. */
3862 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3863 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3864 /* From RFC4271 Section 6.3:
3866 * If a prefix in the NLRI field is semantically
3868 * (e.g., an unexpected multicast IP address),
3870 * be logged locally, and the prefix SHOULD be
3874 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3875 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3880 /* Check address. */
3881 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3882 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3886 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3888 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3893 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
3897 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
3899 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
3906 /* Normal process. */
3908 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
3909 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
3910 NULL
, NULL
, 0, NULL
);
3912 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
3913 safi
, ZEBRA_ROUTE_BGP
,
3914 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
3916 /* Address family configuration mismatch or maximum-prefix count
3922 /* Packet length consistency check. */
3925 "%s [Error] Update packet error (prefix length mismatch with total length)",
3933 static struct bgp_static
*bgp_static_new(void)
3935 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
3938 static void bgp_static_free(struct bgp_static
*bgp_static
)
3940 if (bgp_static
->rmap
.name
)
3941 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
3942 if (bgp_static
->eth_s_id
)
3943 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
3944 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
3947 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
3948 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
3950 struct bgp_node
*rn
;
3951 struct bgp_info
*ri
;
3952 struct bgp_info
*new;
3953 struct bgp_info info
;
3955 struct attr
*attr_new
;
3958 int vnc_implicit_withdraw
= 0;
3965 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
3967 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
3969 attr
.nexthop
= bgp_static
->igpnexthop
;
3970 attr
.med
= bgp_static
->igpmetric
;
3971 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
3973 if (bgp_static
->atomic
)
3974 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
3976 /* Store label index, if required. */
3977 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
3978 attr
.label_index
= bgp_static
->label_index
;
3979 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
3982 /* Apply route-map. */
3983 if (bgp_static
->rmap
.name
) {
3984 struct attr attr_tmp
= attr
;
3985 info
.peer
= bgp
->peer_self
;
3986 info
.attr
= &attr_tmp
;
3988 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
3990 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
3992 bgp
->peer_self
->rmap_type
= 0;
3994 if (ret
== RMAP_DENYMATCH
) {
3995 /* Free uninterned attribute. */
3996 bgp_attr_flush(&attr_tmp
);
3998 /* Unintern original. */
3999 aspath_unintern(&attr
.aspath
);
4000 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4003 attr_new
= bgp_attr_intern(&attr_tmp
);
4005 attr_new
= bgp_attr_intern(&attr
);
4007 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4008 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4009 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4013 if (attrhash_cmp(ri
->attr
, attr_new
)
4014 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4015 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4016 bgp_unlock_node(rn
);
4017 bgp_attr_unintern(&attr_new
);
4018 aspath_unintern(&attr
.aspath
);
4021 /* The attribute is changed. */
4022 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4024 /* Rewrite BGP route information. */
4025 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4026 bgp_info_restore(rn
, ri
);
4028 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4030 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4031 && (safi
== SAFI_UNICAST
)) {
4032 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4034 * Implicit withdraw case.
4035 * We have to do this before ri is
4038 ++vnc_implicit_withdraw
;
4039 vnc_import_bgp_del_route(bgp
, p
, ri
);
4040 vnc_import_bgp_exterior_del_route(
4045 bgp_attr_unintern(&ri
->attr
);
4046 ri
->attr
= attr_new
;
4047 ri
->uptime
= bgp_clock();
4049 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4050 && (safi
== SAFI_UNICAST
)) {
4051 if (vnc_implicit_withdraw
) {
4052 vnc_import_bgp_add_route(bgp
, p
, ri
);
4053 vnc_import_bgp_exterior_add_route(
4059 /* Nexthop reachability check. */
4060 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4061 && (safi
== SAFI_UNICAST
4062 || safi
== SAFI_LABELED_UNICAST
)) {
4063 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4065 bgp_info_set_flag(rn
, ri
,
4068 if (BGP_DEBUG(nht
, NHT
)) {
4069 char buf1
[INET6_ADDRSTRLEN
];
4070 inet_ntop(p
->family
,
4074 "%s(%s): Route not in table, not advertising",
4075 __FUNCTION__
, buf1
);
4077 bgp_info_unset_flag(rn
, ri
,
4081 /* Delete the NHT structure if any, if we're
4083 * enabling/disabling import check. We
4084 * deregister the route
4085 * from NHT to avoid overloading NHT and the
4086 * process interaction
4088 bgp_unlink_nexthop(ri
);
4089 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4091 /* Process change. */
4092 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4093 bgp_process(bgp
, rn
, afi
, safi
);
4094 bgp_unlock_node(rn
);
4095 aspath_unintern(&attr
.aspath
);
4100 /* Make new BGP info. */
4101 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4103 /* Nexthop reachability check. */
4104 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4105 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4106 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4107 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4109 if (BGP_DEBUG(nht
, NHT
)) {
4110 char buf1
[INET6_ADDRSTRLEN
];
4111 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4114 "%s(%s): Route not in table, not advertising",
4115 __FUNCTION__
, buf1
);
4117 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4120 /* Delete the NHT structure if any, if we're toggling between
4121 * enabling/disabling import check. We deregister the route
4122 * from NHT to avoid overloading NHT and the process interaction
4124 bgp_unlink_nexthop(new);
4126 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4129 /* Aggregate address increment. */
4130 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4132 /* Register new BGP information. */
4133 bgp_info_add(rn
, new);
4135 /* route_node_get lock */
4136 bgp_unlock_node(rn
);
4138 /* Process change. */
4139 bgp_process(bgp
, rn
, afi
, safi
);
4141 /* Unintern original. */
4142 aspath_unintern(&attr
.aspath
);
4145 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4148 struct bgp_node
*rn
;
4149 struct bgp_info
*ri
;
4151 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4153 /* Check selected route and self inserted route. */
4154 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4155 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4156 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4159 /* Withdraw static BGP route from routing table. */
4161 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4162 bgp_unlink_nexthop(ri
);
4163 bgp_info_delete(rn
, ri
);
4164 bgp_process(bgp
, rn
, afi
, safi
);
4167 /* Unlock bgp_node_lookup. */
4168 bgp_unlock_node(rn
);
4172 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4174 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4175 afi_t afi
, safi_t safi
,
4176 struct prefix_rd
*prd
)
4178 struct bgp_node
*rn
;
4179 struct bgp_info
*ri
;
4181 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4183 /* Check selected route and self inserted route. */
4184 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4185 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4186 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4189 /* Withdraw static BGP route from routing table. */
4192 rfapiProcessWithdraw(
4193 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4194 1); /* Kill, since it is an administrative change */
4196 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4197 bgp_info_delete(rn
, ri
);
4198 bgp_process(bgp
, rn
, afi
, safi
);
4201 /* Unlock bgp_node_lookup. */
4202 bgp_unlock_node(rn
);
4205 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4206 struct bgp_static
*bgp_static
, afi_t afi
,
4209 struct bgp_node
*rn
;
4210 struct bgp_info
*new;
4211 struct attr
*attr_new
;
4212 struct attr attr
= {0};
4213 struct bgp_info
*ri
;
4215 mpls_label_t label
= 0;
4221 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4224 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4226 attr
.nexthop
= bgp_static
->igpnexthop
;
4227 attr
.med
= bgp_static
->igpmetric
;
4228 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4230 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4231 || (safi
== SAFI_ENCAP
)) {
4232 if (afi
== AFI_IP
) {
4233 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4234 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4237 if (afi
== AFI_L2VPN
) {
4238 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4240 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4241 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4242 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4243 sizeof(struct in6_addr
));
4244 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4245 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4246 struct bgp_encap_type_vxlan bet
;
4247 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4248 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4249 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4251 if (bgp_static
->router_mac
) {
4252 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4255 /* Apply route-map. */
4256 if (bgp_static
->rmap
.name
) {
4257 struct attr attr_tmp
= attr
;
4258 struct bgp_info info
;
4261 info
.peer
= bgp
->peer_self
;
4262 info
.attr
= &attr_tmp
;
4264 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4266 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4268 bgp
->peer_self
->rmap_type
= 0;
4270 if (ret
== RMAP_DENYMATCH
) {
4271 /* Free uninterned attribute. */
4272 bgp_attr_flush(&attr_tmp
);
4274 /* Unintern original. */
4275 aspath_unintern(&attr
.aspath
);
4276 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4281 attr_new
= bgp_attr_intern(&attr_tmp
);
4283 attr_new
= bgp_attr_intern(&attr
);
4286 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4287 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4288 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4293 memset(&add
, 0, sizeof(union gw_addr
));
4294 if (attrhash_cmp(ri
->attr
, attr_new
)
4295 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4296 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4297 bgp_unlock_node(rn
);
4298 bgp_attr_unintern(&attr_new
);
4299 aspath_unintern(&attr
.aspath
);
4302 /* The attribute is changed. */
4303 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4305 /* Rewrite BGP route information. */
4306 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4307 bgp_info_restore(rn
, ri
);
4309 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4310 bgp_attr_unintern(&ri
->attr
);
4311 ri
->attr
= attr_new
;
4312 ri
->uptime
= bgp_clock();
4315 label
= decode_label(&ri
->extra
->label
);
4318 /* Process change. */
4319 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4320 bgp_process(bgp
, rn
, afi
, safi
);
4322 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4323 ri
->attr
, afi
, safi
, ri
->type
,
4324 ri
->sub_type
, &label
);
4326 bgp_unlock_node(rn
);
4327 aspath_unintern(&attr
.aspath
);
4333 /* Make new BGP info. */
4334 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4336 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4337 new->extra
= bgp_info_extra_new();
4338 new->extra
->label
= bgp_static
->label
;
4340 label
= decode_label(&bgp_static
->label
);
4343 /* Aggregate address increment. */
4344 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4346 /* Register new BGP information. */
4347 bgp_info_add(rn
, new);
4348 /* route_node_get lock */
4349 bgp_unlock_node(rn
);
4351 /* Process change. */
4352 bgp_process(bgp
, rn
, afi
, safi
);
4355 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4356 safi
, new->type
, new->sub_type
, &label
);
4359 /* Unintern original. */
4360 aspath_unintern(&attr
.aspath
);
4363 /* Configure static BGP network. When user don't run zebra, static
4364 route should be installed as valid. */
4365 static int bgp_static_set(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4366 safi_t safi
, const char *rmap
, int backdoor
,
4367 u_int32_t label_index
)
4369 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4372 struct bgp_static
*bgp_static
;
4373 struct bgp_node
*rn
;
4374 u_char need_update
= 0;
4376 /* Convert IP prefix string to struct prefix. */
4377 ret
= str2prefix(ip_str
, &p
);
4379 vty_out(vty
, "%% Malformed prefix\n");
4380 return CMD_WARNING_CONFIG_FAILED
;
4382 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4383 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4384 return CMD_WARNING_CONFIG_FAILED
;
4389 /* Set BGP static route configuration. */
4390 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4393 /* Configuration change. */
4394 bgp_static
= rn
->info
;
4396 /* Label index cannot be changed. */
4397 if (bgp_static
->label_index
!= label_index
) {
4398 vty_out(vty
, "%% Label index cannot be changed\n");
4399 return CMD_WARNING_CONFIG_FAILED
;
4402 /* Check previous routes are installed into BGP. */
4403 if (bgp_static
->valid
&& bgp_static
->backdoor
!= backdoor
)
4406 bgp_static
->backdoor
= backdoor
;
4409 if (bgp_static
->rmap
.name
)
4410 XFREE(MTYPE_ROUTE_MAP_NAME
,
4411 bgp_static
->rmap
.name
);
4412 bgp_static
->rmap
.name
=
4413 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4414 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4416 if (bgp_static
->rmap
.name
)
4417 XFREE(MTYPE_ROUTE_MAP_NAME
,
4418 bgp_static
->rmap
.name
);
4419 bgp_static
->rmap
.name
= NULL
;
4420 bgp_static
->rmap
.map
= NULL
;
4421 bgp_static
->valid
= 0;
4423 bgp_unlock_node(rn
);
4425 /* New configuration. */
4426 bgp_static
= bgp_static_new();
4427 bgp_static
->backdoor
= backdoor
;
4428 bgp_static
->valid
= 0;
4429 bgp_static
->igpmetric
= 0;
4430 bgp_static
->igpnexthop
.s_addr
= 0;
4431 bgp_static
->label_index
= label_index
;
4434 if (bgp_static
->rmap
.name
)
4435 XFREE(MTYPE_ROUTE_MAP_NAME
,
4436 bgp_static
->rmap
.name
);
4437 bgp_static
->rmap
.name
=
4438 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4439 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4441 rn
->info
= bgp_static
;
4444 bgp_static
->valid
= 1;
4446 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4448 if (!bgp_static
->backdoor
)
4449 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4454 /* Configure static BGP network. */
4455 static int bgp_static_unset(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4458 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4461 struct bgp_static
*bgp_static
;
4462 struct bgp_node
*rn
;
4464 /* Convert IP prefix string to struct prefix. */
4465 ret
= str2prefix(ip_str
, &p
);
4467 vty_out(vty
, "%% Malformed prefix\n");
4468 return CMD_WARNING_CONFIG_FAILED
;
4470 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4471 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4472 return CMD_WARNING_CONFIG_FAILED
;
4477 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4480 "%% Can't find specified static route configuration.\n");
4481 return CMD_WARNING_CONFIG_FAILED
;
4484 bgp_static
= rn
->info
;
4486 /* Update BGP RIB. */
4487 if (!bgp_static
->backdoor
)
4488 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4490 /* Clear configuration. */
4491 bgp_static_free(bgp_static
);
4493 bgp_unlock_node(rn
);
4494 bgp_unlock_node(rn
);
4499 void bgp_static_add(struct bgp
*bgp
)
4503 struct bgp_node
*rn
;
4504 struct bgp_node
*rm
;
4505 struct bgp_table
*table
;
4506 struct bgp_static
*bgp_static
;
4508 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4509 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4510 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4511 rn
= bgp_route_next(rn
))
4512 if (rn
->info
!= NULL
) {
4513 if ((safi
== SAFI_MPLS_VPN
)
4514 || (safi
== SAFI_ENCAP
)
4515 || (safi
== SAFI_EVPN
)) {
4518 for (rm
= bgp_table_top(table
);
4520 rm
= bgp_route_next(rm
)) {
4521 bgp_static
= rm
->info
;
4522 bgp_static_update_safi(
4528 bgp_static_update(bgp
, &rn
->p
,
4535 /* Called from bgp_delete(). Delete all static routes from the BGP
4537 void bgp_static_delete(struct bgp
*bgp
)
4541 struct bgp_node
*rn
;
4542 struct bgp_node
*rm
;
4543 struct bgp_table
*table
;
4544 struct bgp_static
*bgp_static
;
4546 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4547 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4548 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4549 rn
= bgp_route_next(rn
))
4550 if (rn
->info
!= NULL
) {
4551 if ((safi
== SAFI_MPLS_VPN
)
4552 || (safi
== SAFI_ENCAP
)
4553 || (safi
== SAFI_EVPN
)) {
4556 for (rm
= bgp_table_top(table
);
4558 rm
= bgp_route_next(rm
)) {
4559 bgp_static
= rm
->info
;
4560 bgp_static_withdraw_safi(
4569 bgp_unlock_node(rn
);
4572 bgp_static
= rn
->info
;
4573 bgp_static_withdraw(bgp
, &rn
->p
,
4575 bgp_static_free(bgp_static
);
4577 bgp_unlock_node(rn
);
4582 void bgp_static_redo_import_check(struct bgp
*bgp
)
4586 struct bgp_node
*rn
;
4587 struct bgp_node
*rm
;
4588 struct bgp_table
*table
;
4589 struct bgp_static
*bgp_static
;
4591 /* Use this flag to force reprocessing of the route */
4592 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4593 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4594 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4595 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4596 rn
= bgp_route_next(rn
))
4597 if (rn
->info
!= NULL
) {
4598 if ((safi
== SAFI_MPLS_VPN
)
4599 || (safi
== SAFI_ENCAP
)
4600 || (safi
== SAFI_EVPN
)) {
4603 for (rm
= bgp_table_top(table
);
4605 rm
= bgp_route_next(rm
)) {
4606 bgp_static
= rm
->info
;
4607 bgp_static_update_safi(
4613 bgp_static
= rn
->info
;
4614 bgp_static_update(bgp
, &rn
->p
,
4619 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4622 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4625 struct bgp_table
*table
;
4626 struct bgp_node
*rn
;
4627 struct bgp_info
*ri
;
4629 table
= bgp
->rib
[afi
][safi
];
4630 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4631 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4632 if (ri
->peer
== bgp
->peer_self
4633 && ((ri
->type
== ZEBRA_ROUTE_BGP
4634 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4635 || (ri
->type
!= ZEBRA_ROUTE_BGP
4637 == BGP_ROUTE_REDISTRIBUTE
))) {
4638 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4640 bgp_unlink_nexthop(ri
);
4641 bgp_info_delete(rn
, ri
);
4642 bgp_process(bgp
, rn
, afi
, safi
);
4649 * Purge all networks and redistributed routes from routing table.
4650 * Invoked upon the instance going down.
4652 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4657 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4658 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4659 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4664 * Currently this is used to set static routes for VPN and ENCAP.
4665 * I think it can probably be factored with bgp_static_set.
4667 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4668 const char *ip_str
, const char *rd_str
,
4669 const char *label_str
, const char *rmap_str
,
4670 int evpn_type
, const char *esi
, const char *gwip
,
4671 const char *ethtag
, const char *routermac
)
4673 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4676 struct prefix_rd prd
;
4677 struct bgp_node
*prn
;
4678 struct bgp_node
*rn
;
4679 struct bgp_table
*table
;
4680 struct bgp_static
*bgp_static
;
4681 mpls_label_t label
= MPLS_INVALID_LABEL
;
4682 struct prefix gw_ip
;
4684 /* validate ip prefix */
4685 ret
= str2prefix(ip_str
, &p
);
4687 vty_out(vty
, "%% Malformed prefix\n");
4688 return CMD_WARNING_CONFIG_FAILED
;
4691 if ((afi
== AFI_L2VPN
)
4692 && (bgp_build_evpn_prefix(evpn_type
,
4693 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4694 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4695 return CMD_WARNING_CONFIG_FAILED
;
4698 ret
= str2prefix_rd(rd_str
, &prd
);
4700 vty_out(vty
, "%% Malformed rd\n");
4701 return CMD_WARNING_CONFIG_FAILED
;
4705 unsigned long label_val
;
4706 label_val
= strtoul(label_str
, NULL
, 10);
4707 encode_label(label_val
, &label
);
4710 if (safi
== SAFI_EVPN
) {
4711 if (esi
&& str2esi(esi
, NULL
) == 0) {
4712 vty_out(vty
, "%% Malformed ESI\n");
4713 return CMD_WARNING_CONFIG_FAILED
;
4715 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4716 vty_out(vty
, "%% Malformed Router MAC\n");
4717 return CMD_WARNING_CONFIG_FAILED
;
4720 memset(&gw_ip
, 0, sizeof(struct prefix
));
4721 ret
= str2prefix(gwip
, &gw_ip
);
4723 vty_out(vty
, "%% Malformed GatewayIp\n");
4724 return CMD_WARNING_CONFIG_FAILED
;
4726 if ((gw_ip
.family
== AF_INET
4727 && IS_EVPN_PREFIX_IPADDR_V6(
4728 (struct prefix_evpn
*)&p
))
4729 || (gw_ip
.family
== AF_INET6
4730 && IS_EVPN_PREFIX_IPADDR_V4(
4731 (struct prefix_evpn
*)&p
))) {
4733 "%% GatewayIp family differs with IP prefix\n");
4734 return CMD_WARNING_CONFIG_FAILED
;
4738 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4739 if (prn
->info
== NULL
)
4740 prn
->info
= bgp_table_init(afi
, safi
);
4742 bgp_unlock_node(prn
);
4745 rn
= bgp_node_get(table
, &p
);
4748 vty_out(vty
, "%% Same network configuration exists\n");
4749 bgp_unlock_node(rn
);
4751 /* New configuration. */
4752 bgp_static
= bgp_static_new();
4753 bgp_static
->backdoor
= 0;
4754 bgp_static
->valid
= 0;
4755 bgp_static
->igpmetric
= 0;
4756 bgp_static
->igpnexthop
.s_addr
= 0;
4757 bgp_static
->label
= label
;
4758 bgp_static
->prd
= prd
;
4761 if (bgp_static
->rmap
.name
)
4762 XFREE(MTYPE_ROUTE_MAP_NAME
,
4763 bgp_static
->rmap
.name
);
4764 bgp_static
->rmap
.name
=
4765 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4766 bgp_static
->rmap
.map
=
4767 route_map_lookup_by_name(rmap_str
);
4770 if (safi
== SAFI_EVPN
) {
4772 bgp_static
->eth_s_id
=
4774 sizeof(struct eth_segment_id
));
4775 str2esi(esi
, bgp_static
->eth_s_id
);
4778 bgp_static
->router_mac
=
4779 XCALLOC(MTYPE_ATTR
, ETHER_ADDR_LEN
+ 1);
4780 prefix_str2mac(routermac
,
4781 bgp_static
->router_mac
);
4784 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4786 rn
->info
= bgp_static
;
4788 bgp_static
->valid
= 1;
4789 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4795 /* Configure static BGP network. */
4796 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4797 const char *ip_str
, const char *rd_str
,
4798 const char *label_str
, int evpn_type
, const char *esi
,
4799 const char *gwip
, const char *ethtag
)
4801 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4804 struct prefix_rd prd
;
4805 struct bgp_node
*prn
;
4806 struct bgp_node
*rn
;
4807 struct bgp_table
*table
;
4808 struct bgp_static
*bgp_static
;
4809 mpls_label_t label
= MPLS_INVALID_LABEL
;
4811 /* Convert IP prefix string to struct prefix. */
4812 ret
= str2prefix(ip_str
, &p
);
4814 vty_out(vty
, "%% Malformed prefix\n");
4815 return CMD_WARNING_CONFIG_FAILED
;
4818 if ((afi
== AFI_L2VPN
)
4819 && (bgp_build_evpn_prefix(evpn_type
,
4820 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4821 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4822 return CMD_WARNING_CONFIG_FAILED
;
4824 ret
= str2prefix_rd(rd_str
, &prd
);
4826 vty_out(vty
, "%% Malformed rd\n");
4827 return CMD_WARNING_CONFIG_FAILED
;
4831 unsigned long label_val
;
4832 label_val
= strtoul(label_str
, NULL
, 10);
4833 encode_label(label_val
, &label
);
4836 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4837 if (prn
->info
== NULL
)
4838 prn
->info
= bgp_table_init(afi
, safi
);
4840 bgp_unlock_node(prn
);
4843 rn
= bgp_node_lookup(table
, &p
);
4846 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4848 bgp_static
= rn
->info
;
4849 bgp_static_free(bgp_static
);
4851 bgp_unlock_node(rn
);
4852 bgp_unlock_node(rn
);
4854 vty_out(vty
, "%% Can't find the route\n");
4859 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4860 const char *rmap_name
)
4862 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4863 struct bgp_rmap
*rmap
;
4865 rmap
= &bgp
->table_map
[afi
][safi
];
4868 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4869 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4870 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4873 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4878 if (bgp_fibupd_safi(safi
))
4879 bgp_zebra_announce_table(bgp
, afi
, safi
);
4884 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
4885 const char *rmap_name
)
4887 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4888 struct bgp_rmap
*rmap
;
4890 rmap
= &bgp
->table_map
[afi
][safi
];
4892 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4896 if (bgp_fibupd_safi(safi
))
4897 bgp_zebra_announce_table(bgp
, afi
, safi
);
4902 int bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4903 safi_t safi
, int *write
)
4905 if (bgp
->table_map
[afi
][safi
].name
) {
4906 bgp_config_write_family_header(vty
, afi
, safi
, write
);
4907 vty_out(vty
, " table-map %s\n",
4908 bgp
->table_map
[afi
][safi
].name
);
4914 DEFUN (bgp_table_map
,
4917 "BGP table to RIB route download filter\n"
4918 "Name of the route map\n")
4921 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4922 argv
[idx_word
]->arg
);
4924 DEFUN (no_bgp_table_map
,
4925 no_bgp_table_map_cmd
,
4926 "no table-map WORD",
4928 "BGP table to RIB route download filter\n"
4929 "Name of the route map\n")
4932 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
4933 argv
[idx_word
]->arg
);
4938 "network A.B.C.D/M",
4939 "Specify a network to announce via BGP\n"
4942 int idx_ipv4_prefixlen
= 1;
4943 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4944 bgp_node_safi(vty
), NULL
, 0,
4945 BGP_INVALID_LABEL_INDEX
);
4948 DEFUN (bgp_network_route_map
,
4949 bgp_network_route_map_cmd
,
4950 "network A.B.C.D/M route-map WORD",
4951 "Specify a network to announce via BGP\n"
4953 "Route-map to modify the attributes\n"
4954 "Name of the route map\n")
4956 int idx_ipv4_prefixlen
= 1;
4958 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4959 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
4960 BGP_INVALID_LABEL_INDEX
);
4963 DEFUN (bgp_network_backdoor
,
4964 bgp_network_backdoor_cmd
,
4965 "network A.B.C.D/M backdoor",
4966 "Specify a network to announce via BGP\n"
4968 "Specify a BGP backdoor route\n")
4970 int idx_ipv4_prefixlen
= 1;
4971 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
4972 SAFI_UNICAST
, NULL
, 1, BGP_INVALID_LABEL_INDEX
);
4975 DEFUN (bgp_network_mask
,
4976 bgp_network_mask_cmd
,
4977 "network A.B.C.D mask A.B.C.D",
4978 "Specify a network to announce via BGP\n"
4986 char prefix_str
[BUFSIZ
];
4988 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
4991 vty_out(vty
, "%% Inconsistent address and mask\n");
4992 return CMD_WARNING_CONFIG_FAILED
;
4995 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
4996 0, BGP_INVALID_LABEL_INDEX
);
4999 DEFUN (bgp_network_mask_route_map
,
5000 bgp_network_mask_route_map_cmd
,
5001 "network A.B.C.D mask A.B.C.D route-map WORD",
5002 "Specify a network to announce via BGP\n"
5006 "Route-map to modify the attributes\n"
5007 "Name of the route map\n")
5013 char prefix_str
[BUFSIZ
];
5015 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5018 vty_out(vty
, "%% Inconsistent address and mask\n");
5019 return CMD_WARNING_CONFIG_FAILED
;
5022 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5023 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5026 DEFUN (bgp_network_mask_backdoor
,
5027 bgp_network_mask_backdoor_cmd
,
5028 "network A.B.C.D mask A.B.C.D backdoor",
5029 "Specify a network to announce via BGP\n"
5033 "Specify a BGP backdoor route\n")
5038 char prefix_str
[BUFSIZ
];
5040 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5043 vty_out(vty
, "%% Inconsistent address and mask\n");
5044 return CMD_WARNING_CONFIG_FAILED
;
5047 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5048 BGP_INVALID_LABEL_INDEX
);
5051 DEFUN (bgp_network_mask_natural
,
5052 bgp_network_mask_natural_cmd
,
5054 "Specify a network to announce via BGP\n"
5059 char prefix_str
[BUFSIZ
];
5061 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5063 vty_out(vty
, "%% Inconsistent address and mask\n");
5064 return CMD_WARNING_CONFIG_FAILED
;
5067 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5068 0, BGP_INVALID_LABEL_INDEX
);
5071 DEFUN (bgp_network_mask_natural_route_map
,
5072 bgp_network_mask_natural_route_map_cmd
,
5073 "network A.B.C.D route-map WORD",
5074 "Specify a network to announce via BGP\n"
5076 "Route-map to modify the attributes\n"
5077 "Name of the route map\n")
5082 char prefix_str
[BUFSIZ
];
5084 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5086 vty_out(vty
, "%% Inconsistent address and mask\n");
5087 return CMD_WARNING_CONFIG_FAILED
;
5090 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5091 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5094 DEFUN (bgp_network_mask_natural_backdoor
,
5095 bgp_network_mask_natural_backdoor_cmd
,
5096 "network A.B.C.D backdoor",
5097 "Specify a network to announce via BGP\n"
5099 "Specify a BGP backdoor route\n")
5103 char prefix_str
[BUFSIZ
];
5105 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5107 vty_out(vty
, "%% Inconsistent address and mask\n");
5108 return CMD_WARNING_CONFIG_FAILED
;
5111 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5112 BGP_INVALID_LABEL_INDEX
);
5115 DEFUN (bgp_network_label_index
,
5116 bgp_network_label_index_cmd
,
5117 "network A.B.C.D/M label-index (0-1048560)",
5118 "Specify a network to announce via BGP\n"
5119 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5120 "Label index to associate with the prefix\n"
5121 "Label index value\n")
5123 u_int32_t label_index
;
5125 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5126 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5127 NULL
, 0, label_index
);
5130 DEFUN (bgp_network_label_index_route_map
,
5131 bgp_network_label_index_route_map_cmd
,
5132 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
5133 "Specify a network to announce via BGP\n"
5135 "Label index to associate with the prefix\n"
5136 "Label index value\n"
5137 "Route-map to modify the attributes\n"
5138 "Name of the route map\n")
5140 u_int32_t label_index
;
5142 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5143 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5144 argv
[5]->arg
, 0, label_index
);
5147 DEFUN (no_bgp_network
,
5149 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
5151 "Specify a network to announce via BGP\n"
5153 "Specify a BGP backdoor route\n"
5154 "Route-map to modify the attributes\n"
5155 "Name of the route map\n")
5157 int idx_ipv4_prefixlen
= 2;
5158 return bgp_static_unset(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5159 bgp_node_safi(vty
));
5162 DEFUN (no_bgp_network_mask
,
5163 no_bgp_network_mask_cmd
,
5164 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
5166 "Specify a network to announce via BGP\n"
5170 "Specify a BGP backdoor route\n"
5171 "Route-map to modify the attributes\n"
5172 "Name of the route map\n")
5177 char prefix_str
[BUFSIZ
];
5179 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5182 vty_out(vty
, "%% Inconsistent address and mask\n");
5183 return CMD_WARNING_CONFIG_FAILED
;
5186 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5189 DEFUN (no_bgp_network_mask_natural
,
5190 no_bgp_network_mask_natural_cmd
,
5191 "no network A.B.C.D [<backdoor|route-map WORD>]",
5193 "Specify a network to announce via BGP\n"
5195 "Specify a BGP backdoor route\n"
5196 "Route-map to modify the attributes\n"
5197 "Name of the route map\n")
5201 char prefix_str
[BUFSIZ
];
5203 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5205 vty_out(vty
, "%% Inconsistent address and mask\n");
5206 return CMD_WARNING_CONFIG_FAILED
;
5209 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5212 ALIAS(no_bgp_network
, no_bgp_network_label_index_cmd
,
5213 "no network A.B.C.D/M label-index (0-1048560)",
5215 "Specify a network to announce via BGP\n"
5216 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5217 "Label index to associate with the prefix\n"
5218 "Label index value\n")
5220 ALIAS(no_bgp_network
, no_bgp_network_label_index_route_map_cmd
,
5221 "no network A.B.C.D/M label-index (0-1048560) route-map WORD",
5223 "Specify a network to announce via BGP\n"
5225 "Label index to associate with the prefix\n"
5226 "Label index value\n"
5227 "Route-map to modify the attributes\n"
5228 "Name of the route map\n")
5230 DEFUN (ipv6_bgp_network
,
5231 ipv6_bgp_network_cmd
,
5232 "network X:X::X:X/M",
5233 "Specify a network to announce via BGP\n"
5236 int idx_ipv6_prefixlen
= 1;
5237 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5238 bgp_node_safi(vty
), NULL
, 0,
5239 BGP_INVALID_LABEL_INDEX
);
5242 DEFUN (ipv6_bgp_network_route_map
,
5243 ipv6_bgp_network_route_map_cmd
,
5244 "network X:X::X:X/M route-map WORD",
5245 "Specify a network to announce via BGP\n"
5247 "Route-map to modify the attributes\n"
5248 "Name of the route map\n")
5250 int idx_ipv6_prefixlen
= 1;
5252 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5253 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5254 BGP_INVALID_LABEL_INDEX
);
5257 DEFUN (ipv6_bgp_network_label_index
,
5258 ipv6_bgp_network_label_index_cmd
,
5259 "network X:X::X:X/M label-index (0-1048560)",
5260 "Specify a network to announce via BGP\n"
5261 "IPv6 prefix <network>/<length>\n"
5262 "Label index to associate with the prefix\n"
5263 "Label index value\n")
5265 u_int32_t label_index
;
5267 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5268 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5269 NULL
, 0, label_index
);
5272 DEFUN (ipv6_bgp_network_label_index_route_map
,
5273 ipv6_bgp_network_label_index_route_map_cmd
,
5274 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
5275 "Specify a network to announce via BGP\n"
5277 "Label index to associate with the prefix\n"
5278 "Label index value\n"
5279 "Route-map to modify the attributes\n"
5280 "Name of the route map\n")
5282 u_int32_t label_index
;
5284 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5285 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5286 argv
[5]->arg
, 0, label_index
);
5289 DEFUN (no_ipv6_bgp_network
,
5290 no_ipv6_bgp_network_cmd
,
5291 "no network X:X::X:X/M [route-map WORD]",
5293 "Specify a network to announce via BGP\n"
5295 "Route-map to modify the attributes\n"
5296 "Name of the route map\n")
5298 int idx_ipv6_prefixlen
= 2;
5299 return bgp_static_unset(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5300 bgp_node_safi(vty
));
5303 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_cmd
,
5304 "no network X:X::X:X/M label-index (0-1048560)",
5306 "Specify a network to announce via BGP\n"
5307 "IPv6 prefix <network>/<length>\n"
5308 "Label index to associate with the prefix\n"
5309 "Label index value\n")
5311 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_route_map_cmd
,
5312 "no network X:X::X:X/M label-index (0-1048560) route-map WORD",
5314 "Specify a network to announce via BGP\n"
5316 "Label index to associate with the prefix\n"
5317 "Label index value\n"
5318 "Route-map to modify the attributes\n"
5319 "Name of the route map\n")
5321 /* Aggreagete address:
5323 advertise-map Set condition to advertise attribute
5324 as-set Generate AS set path information
5325 attribute-map Set attributes of aggregate
5326 route-map Set parameters of aggregate
5327 summary-only Filter more specific routes from updates
5328 suppress-map Conditionally filter more specific routes from updates
5331 struct bgp_aggregate
{
5332 /* Summary-only flag. */
5333 u_char summary_only
;
5335 /* AS set generation. */
5338 /* Route-map for aggregated route. */
5339 struct route_map
*map
;
5341 /* Suppress-count. */
5342 unsigned long count
;
5344 /* SAFI configuration. */
5348 static struct bgp_aggregate
*bgp_aggregate_new(void)
5350 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5353 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5355 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5358 /* Update an aggregate as routes are added/removed from the BGP table */
5359 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5360 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5361 struct bgp_info
*del
,
5362 struct bgp_aggregate
*aggregate
)
5364 struct bgp_table
*table
;
5365 struct bgp_node
*top
;
5366 struct bgp_node
*rn
;
5368 struct aspath
*aspath
= NULL
;
5369 struct aspath
*asmerge
= NULL
;
5370 struct community
*community
= NULL
;
5371 struct community
*commerge
= NULL
;
5372 #if defined(AGGREGATE_NEXTHOP_CHECK)
5373 struct in_addr nexthop
;
5376 struct bgp_info
*ri
;
5377 struct bgp_info
*new;
5379 unsigned long match
= 0;
5380 u_char atomic_aggregate
= 0;
5382 /* Record adding route's nexthop and med. */
5384 #if defined(AGGREGATE_NEXTHOP_CHECK)
5385 nexthop
= rinew
->attr
->nexthop
;
5386 med
= rinew
->attr
->med
;
5390 /* ORIGIN attribute: If at least one route among routes that are
5391 aggregated has ORIGIN with the value INCOMPLETE, then the
5392 aggregated route must have the ORIGIN attribute with the value
5393 INCOMPLETE. Otherwise, if at least one route among routes that
5394 are aggregated has ORIGIN with the value EGP, then the aggregated
5395 route must have the origin attribute with the value EGP. In all
5396 other case the value of the ORIGIN attribute of the aggregated
5397 route is INTERNAL. */
5398 origin
= BGP_ORIGIN_IGP
;
5400 table
= bgp
->rib
[afi
][safi
];
5402 top
= bgp_node_get(table
, p
);
5403 for (rn
= bgp_node_get(table
, p
); rn
;
5404 rn
= bgp_route_next_until(rn
, top
))
5405 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5408 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5409 if (BGP_INFO_HOLDDOWN(ri
))
5412 if (del
&& ri
== del
)
5415 if (!rinew
&& first
) {
5416 #if defined(AGGREGATE_NEXTHOP_CHECK)
5417 nexthop
= ri
->attr
->nexthop
;
5418 med
= ri
->attr
->med
;
5423 #ifdef AGGREGATE_NEXTHOP_CHECK
5424 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5426 || ri
->attr
->med
!= med
) {
5428 aspath_free(aspath
);
5430 community_free(community
);
5431 bgp_unlock_node(rn
);
5432 bgp_unlock_node(top
);
5435 #endif /* AGGREGATE_NEXTHOP_CHECK */
5438 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5439 atomic_aggregate
= 1;
5441 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5442 if (aggregate
->summary_only
) {
5443 (bgp_info_extra_get(ri
))
5447 BGP_INFO_ATTR_CHANGED
);
5453 if (origin
< ri
->attr
->origin
)
5454 origin
= ri
->attr
->origin
;
5456 if (aggregate
->as_set
) {
5458 asmerge
= aspath_aggregate(
5461 aspath_free(aspath
);
5464 aspath
= aspath_dup(
5467 if (ri
->attr
->community
) {
5469 commerge
= community_merge(
5471 ri
->attr
->community
);
5472 community
= community_uniq_sort(
5477 community
= community_dup(
5478 ri
->attr
->community
);
5484 bgp_process(bgp
, rn
, afi
, safi
);
5486 bgp_unlock_node(top
);
5491 if (aggregate
->summary_only
)
5492 (bgp_info_extra_get(rinew
))->suppress
++;
5494 if (origin
< rinew
->attr
->origin
)
5495 origin
= rinew
->attr
->origin
;
5497 if (aggregate
->as_set
) {
5499 asmerge
= aspath_aggregate(aspath
,
5500 rinew
->attr
->aspath
);
5501 aspath_free(aspath
);
5504 aspath
= aspath_dup(rinew
->attr
->aspath
);
5506 if (rinew
->attr
->community
) {
5508 commerge
= community_merge(
5510 rinew
->attr
->community
);
5512 community_uniq_sort(commerge
);
5513 community_free(commerge
);
5515 community
= community_dup(
5516 rinew
->attr
->community
);
5521 if (aggregate
->count
> 0) {
5522 rn
= bgp_node_get(table
, p
);
5524 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5525 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5526 community
, aggregate
->as_set
,
5529 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5531 bgp_info_add(rn
, new);
5532 bgp_unlock_node(rn
);
5533 bgp_process(bgp
, rn
, afi
, safi
);
5536 aspath_free(aspath
);
5538 community_free(community
);
5542 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5543 struct bgp_aggregate
*);
5545 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5546 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5548 struct bgp_node
*child
;
5549 struct bgp_node
*rn
;
5550 struct bgp_aggregate
*aggregate
;
5551 struct bgp_table
*table
;
5553 /* MPLS-VPN aggregation is not yet supported. */
5554 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5555 || (safi
== SAFI_EVPN
))
5558 table
= bgp
->aggregate
[afi
][safi
];
5560 /* No aggregates configured. */
5561 if (bgp_table_top_nolock(table
) == NULL
)
5564 if (p
->prefixlen
== 0)
5567 if (BGP_INFO_HOLDDOWN(ri
))
5570 child
= bgp_node_get(table
, p
);
5572 /* Aggregate address configuration check. */
5573 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5574 if ((aggregate
= rn
->info
) != NULL
5575 && rn
->p
.prefixlen
< p
->prefixlen
) {
5576 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5577 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5580 bgp_unlock_node(child
);
5583 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5584 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5586 struct bgp_node
*child
;
5587 struct bgp_node
*rn
;
5588 struct bgp_aggregate
*aggregate
;
5589 struct bgp_table
*table
;
5591 /* MPLS-VPN aggregation is not yet supported. */
5592 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5593 || (safi
== SAFI_EVPN
))
5596 table
= bgp
->aggregate
[afi
][safi
];
5598 /* No aggregates configured. */
5599 if (bgp_table_top_nolock(table
) == NULL
)
5602 if (p
->prefixlen
== 0)
5605 child
= bgp_node_get(table
, p
);
5607 /* Aggregate address configuration check. */
5608 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5609 if ((aggregate
= rn
->info
) != NULL
5610 && rn
->p
.prefixlen
< p
->prefixlen
) {
5611 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5612 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5615 bgp_unlock_node(child
);
5618 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5619 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5620 safi_t safi
, struct bgp_aggregate
*aggregate
)
5622 struct bgp_table
*table
;
5623 struct bgp_node
*top
;
5624 struct bgp_node
*rn
;
5625 struct bgp_info
*new;
5626 struct bgp_info
*ri
;
5627 unsigned long match
;
5628 u_char origin
= BGP_ORIGIN_IGP
;
5629 struct aspath
*aspath
= NULL
;
5630 struct aspath
*asmerge
= NULL
;
5631 struct community
*community
= NULL
;
5632 struct community
*commerge
= NULL
;
5633 u_char atomic_aggregate
= 0;
5635 table
= bgp
->rib
[afi
][safi
];
5638 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5640 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5643 /* If routes exists below this node, generate aggregate routes. */
5644 top
= bgp_node_get(table
, p
);
5645 for (rn
= bgp_node_get(table
, p
); rn
;
5646 rn
= bgp_route_next_until(rn
, top
))
5647 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5650 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5651 if (BGP_INFO_HOLDDOWN(ri
))
5655 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5656 atomic_aggregate
= 1;
5658 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5659 /* summary-only aggregate route suppress
5661 route announcement. */
5662 if (aggregate
->summary_only
) {
5663 (bgp_info_extra_get(ri
))
5667 BGP_INFO_ATTR_CHANGED
);
5671 /* If at least one route among routes
5672 * that are aggregated has
5673 * ORIGIN with the value INCOMPLETE,
5674 * then the aggregated route
5675 * MUST have the ORIGIN attribute with
5676 * the value INCOMPLETE.
5677 * Otherwise, if at least one route
5678 * among routes that are
5679 * aggregated has ORIGIN with the value
5680 * EGP, then the aggregated
5681 * route MUST have the ORIGIN attribute
5682 * with the value EGP.
5684 if (origin
< ri
->attr
->origin
)
5685 origin
= ri
->attr
->origin
;
5687 /* as-set aggregate route generate
5689 community aggregation. */
5690 if (aggregate
->as_set
) {
5692 asmerge
= aspath_aggregate(
5695 aspath_free(aspath
);
5698 aspath
= aspath_dup(
5701 if (ri
->attr
->community
) {
5703 commerge
= community_merge(
5705 ri
->attr
->community
);
5706 community
= community_uniq_sort(
5711 community
= community_dup(
5712 ri
->attr
->community
);
5719 /* If this node is suppressed, process the change. */
5721 bgp_process(bgp
, rn
, afi
, safi
);
5723 bgp_unlock_node(top
);
5725 /* Add aggregate route to BGP table. */
5726 if (aggregate
->count
) {
5727 rn
= bgp_node_get(table
, p
);
5729 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5730 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5731 community
, aggregate
->as_set
,
5734 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5736 bgp_info_add(rn
, new);
5737 bgp_unlock_node(rn
);
5739 /* Process change. */
5740 bgp_process(bgp
, rn
, afi
, safi
);
5743 aspath_free(aspath
);
5745 community_free(community
);
5749 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5750 safi_t safi
, struct bgp_aggregate
*aggregate
)
5752 struct bgp_table
*table
;
5753 struct bgp_node
*top
;
5754 struct bgp_node
*rn
;
5755 struct bgp_info
*ri
;
5756 unsigned long match
;
5758 table
= bgp
->rib
[afi
][safi
];
5760 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5762 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5765 /* If routes exists below this node, generate aggregate routes. */
5766 top
= bgp_node_get(table
, p
);
5767 for (rn
= bgp_node_get(table
, p
); rn
;
5768 rn
= bgp_route_next_until(rn
, top
))
5769 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5772 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5773 if (BGP_INFO_HOLDDOWN(ri
))
5776 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5777 if (aggregate
->summary_only
5779 ri
->extra
->suppress
--;
5781 if (ri
->extra
->suppress
== 0) {
5784 BGP_INFO_ATTR_CHANGED
);
5792 /* If this node was suppressed, process the change. */
5794 bgp_process(bgp
, rn
, afi
, safi
);
5796 bgp_unlock_node(top
);
5798 /* Delete aggregate route from BGP table. */
5799 rn
= bgp_node_get(table
, p
);
5801 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5802 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5803 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5806 /* Withdraw static BGP route from routing table. */
5808 bgp_info_delete(rn
, ri
);
5809 bgp_process(bgp
, rn
, afi
, safi
);
5812 /* Unlock bgp_node_lookup. */
5813 bgp_unlock_node(rn
);
5816 /* Aggregate route attribute. */
5817 #define AGGREGATE_SUMMARY_ONLY 1
5818 #define AGGREGATE_AS_SET 1
5820 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5821 afi_t afi
, safi_t safi
)
5823 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5826 struct bgp_node
*rn
;
5827 struct bgp_aggregate
*aggregate
;
5829 /* Convert string to prefix structure. */
5830 ret
= str2prefix(prefix_str
, &p
);
5832 vty_out(vty
, "Malformed prefix\n");
5833 return CMD_WARNING_CONFIG_FAILED
;
5837 /* Old configuration check. */
5838 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5841 "%% There is no aggregate-address configuration.\n");
5842 return CMD_WARNING_CONFIG_FAILED
;
5845 aggregate
= rn
->info
;
5846 if (aggregate
->safi
== SAFI_UNICAST
)
5847 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5848 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5849 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5851 if (aggregate
->safi
== SAFI_MULTICAST
)
5852 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5854 /* Unlock aggregate address configuration. */
5856 bgp_aggregate_free(aggregate
);
5857 bgp_unlock_node(rn
);
5858 bgp_unlock_node(rn
);
5863 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5864 safi_t safi
, u_char summary_only
, u_char as_set
)
5866 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5869 struct bgp_node
*rn
;
5870 struct bgp_aggregate
*aggregate
;
5872 /* Convert string to prefix structure. */
5873 ret
= str2prefix(prefix_str
, &p
);
5875 vty_out(vty
, "Malformed prefix\n");
5876 return CMD_WARNING_CONFIG_FAILED
;
5880 /* Old configuration check. */
5881 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5884 vty_out(vty
, "There is already same aggregate network.\n");
5885 /* try to remove the old entry */
5886 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5888 vty_out(vty
, "Error deleting aggregate.\n");
5889 bgp_unlock_node(rn
);
5890 return CMD_WARNING_CONFIG_FAILED
;
5894 /* Make aggregate address structure. */
5895 aggregate
= bgp_aggregate_new();
5896 aggregate
->summary_only
= summary_only
;
5897 aggregate
->as_set
= as_set
;
5898 aggregate
->safi
= safi
;
5899 rn
->info
= aggregate
;
5901 /* Aggregate address insert into BGP routing table. */
5902 if (safi
== SAFI_UNICAST
)
5903 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5904 if (safi
== SAFI_LABELED_UNICAST
)
5905 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5907 if (safi
== SAFI_MULTICAST
)
5908 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5913 DEFUN (aggregate_address
,
5914 aggregate_address_cmd
,
5915 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5916 "Configure BGP aggregate entries\n"
5917 "Aggregate prefix\n"
5918 "Generate AS set path information\n"
5919 "Filter more specific routes from updates\n"
5920 "Filter more specific routes from updates\n"
5921 "Generate AS set path information\n")
5924 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5925 char *prefix
= argv
[idx
]->arg
;
5927 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5929 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5930 ? AGGREGATE_SUMMARY_ONLY
5933 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5934 summary_only
, as_set
);
5937 DEFUN (aggregate_address_mask
,
5938 aggregate_address_mask_cmd
,
5939 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5940 "Configure BGP aggregate entries\n"
5941 "Aggregate address\n"
5943 "Generate AS set path information\n"
5944 "Filter more specific routes from updates\n"
5945 "Filter more specific routes from updates\n"
5946 "Generate AS set path information\n")
5949 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5950 char *prefix
= argv
[idx
]->arg
;
5951 char *mask
= argv
[idx
+ 1]->arg
;
5953 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5955 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5956 ? AGGREGATE_SUMMARY_ONLY
5959 char prefix_str
[BUFSIZ
];
5960 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5963 vty_out(vty
, "%% Inconsistent address and mask\n");
5964 return CMD_WARNING_CONFIG_FAILED
;
5967 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5968 summary_only
, as_set
);
5971 DEFUN (no_aggregate_address
,
5972 no_aggregate_address_cmd
,
5973 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5975 "Configure BGP aggregate entries\n"
5976 "Aggregate prefix\n"
5977 "Generate AS set path information\n"
5978 "Filter more specific routes from updates\n"
5979 "Filter more specific routes from updates\n"
5980 "Generate AS set path information\n")
5983 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5984 char *prefix
= argv
[idx
]->arg
;
5985 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5988 DEFUN (no_aggregate_address_mask
,
5989 no_aggregate_address_mask_cmd
,
5990 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5992 "Configure BGP aggregate entries\n"
5993 "Aggregate address\n"
5995 "Generate AS set path information\n"
5996 "Filter more specific routes from updates\n"
5997 "Filter more specific routes from updates\n"
5998 "Generate AS set path information\n")
6001 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6002 char *prefix
= argv
[idx
]->arg
;
6003 char *mask
= argv
[idx
+ 1]->arg
;
6005 char prefix_str
[BUFSIZ
];
6006 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6009 vty_out(vty
, "%% Inconsistent address and mask\n");
6010 return CMD_WARNING_CONFIG_FAILED
;
6013 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6016 DEFUN (ipv6_aggregate_address
,
6017 ipv6_aggregate_address_cmd
,
6018 "aggregate-address X:X::X:X/M [summary-only]",
6019 "Configure BGP aggregate entries\n"
6020 "Aggregate prefix\n"
6021 "Filter more specific routes from updates\n")
6024 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6025 char *prefix
= argv
[idx
]->arg
;
6026 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6027 ? AGGREGATE_SUMMARY_ONLY
6029 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6033 DEFUN (no_ipv6_aggregate_address
,
6034 no_ipv6_aggregate_address_cmd
,
6035 "no aggregate-address X:X::X:X/M [summary-only]",
6037 "Configure BGP aggregate entries\n"
6038 "Aggregate prefix\n"
6039 "Filter more specific routes from updates\n")
6042 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6043 char *prefix
= argv
[idx
]->arg
;
6044 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6047 /* Redistribute route treatment. */
6048 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6049 const struct in_addr
*nexthop
,
6050 const struct in6_addr
*nexthop6
, unsigned int ifindex
,
6051 u_int32_t metric
, u_char type
, u_short instance
,
6054 struct bgp_info
*new;
6055 struct bgp_info
*bi
;
6056 struct bgp_info info
;
6057 struct bgp_node
*bn
;
6059 struct attr
*new_attr
;
6062 struct bgp_redist
*red
;
6064 /* Make default attribute. */
6065 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6067 attr
.nexthop
= *nexthop
;
6068 attr
.nh_ifindex
= ifindex
;
6071 attr
.mp_nexthop_global
= *nexthop6
;
6072 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6076 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6079 afi
= family2afi(p
->family
);
6081 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6083 struct attr attr_new
;
6085 /* Copy attribute for modification. */
6086 bgp_attr_dup(&attr_new
, &attr
);
6088 if (red
->redist_metric_flag
)
6089 attr_new
.med
= red
->redist_metric
;
6091 /* Apply route-map. */
6092 if (red
->rmap
.name
) {
6093 info
.peer
= bgp
->peer_self
;
6094 info
.attr
= &attr_new
;
6096 SET_FLAG(bgp
->peer_self
->rmap_type
,
6097 PEER_RMAP_TYPE_REDISTRIBUTE
);
6099 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6102 bgp
->peer_self
->rmap_type
= 0;
6104 if (ret
== RMAP_DENYMATCH
) {
6105 /* Free uninterned attribute. */
6106 bgp_attr_flush(&attr_new
);
6108 /* Unintern original. */
6109 aspath_unintern(&attr
.aspath
);
6110 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6115 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6116 SAFI_UNICAST
, p
, NULL
);
6118 new_attr
= bgp_attr_intern(&attr_new
);
6120 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6121 if (bi
->peer
== bgp
->peer_self
6122 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6126 /* Ensure the (source route) type is updated. */
6128 if (attrhash_cmp(bi
->attr
, new_attr
)
6129 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6130 bgp_attr_unintern(&new_attr
);
6131 aspath_unintern(&attr
.aspath
);
6132 bgp_unlock_node(bn
);
6135 /* The attribute is changed. */
6136 bgp_info_set_flag(bn
, bi
,
6137 BGP_INFO_ATTR_CHANGED
);
6139 /* Rewrite BGP route information. */
6140 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6141 bgp_info_restore(bn
, bi
);
6143 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6145 bgp_attr_unintern(&bi
->attr
);
6146 bi
->attr
= new_attr
;
6147 bi
->uptime
= bgp_clock();
6149 /* Process change. */
6150 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6152 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6153 bgp_unlock_node(bn
);
6154 aspath_unintern(&attr
.aspath
);
6159 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6160 bgp
->peer_self
, new_attr
, bn
);
6161 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6163 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6164 bgp_info_add(bn
, new);
6165 bgp_unlock_node(bn
);
6166 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6169 /* Unintern original. */
6170 aspath_unintern(&attr
.aspath
);
6173 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6177 struct bgp_node
*rn
;
6178 struct bgp_info
*ri
;
6179 struct bgp_redist
*red
;
6181 afi
= family2afi(p
->family
);
6183 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6185 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6186 SAFI_UNICAST
, p
, NULL
);
6188 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6189 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6193 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6194 bgp_info_delete(rn
, ri
);
6195 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6197 bgp_unlock_node(rn
);
6201 /* Withdraw specified route type's route. */
6202 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6205 struct bgp_node
*rn
;
6206 struct bgp_info
*ri
;
6207 struct bgp_table
*table
;
6209 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6211 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6212 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6213 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6214 && ri
->instance
== instance
)
6218 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6220 bgp_info_delete(rn
, ri
);
6221 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6226 /* Static function to display route. */
6227 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
)
6230 u_int32_t destination
;
6233 if (p
->family
== AF_INET
) {
6234 len
= vty_out(vty
, "%s",
6235 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
));
6236 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6238 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6239 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6240 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6241 || p
->u
.prefix4
.s_addr
== 0) {
6242 /* When mask is natural, mask is not displayed. */
6244 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6245 } else if (p
->family
== AF_ETHERNET
) {
6246 #if defined(HAVE_CUMULUS)
6247 len
= vty_out(vty
, "%s",
6248 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6251 prefix2str(p
, buf
, PREFIX_STRLEN
);
6252 len
= vty_out(vty
, "%s", buf
);
6255 len
= vty_out(vty
, "%s/%d",
6256 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6261 vty_out(vty
, "\n%*s", 20, " ");
6263 vty_out(vty
, "%*s", len
, " ");
6266 enum bgp_display_type
{
6270 /* Print the short form route status for a bgp_info */
6271 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6272 json_object
*json_path
)
6276 /* Route status display. */
6277 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6278 json_object_boolean_true_add(json_path
, "removed");
6280 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6281 json_object_boolean_true_add(json_path
, "stale");
6283 if (binfo
->extra
&& binfo
->extra
->suppress
)
6284 json_object_boolean_true_add(json_path
, "suppressed");
6286 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6287 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6288 json_object_boolean_true_add(json_path
, "valid");
6291 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6292 json_object_boolean_true_add(json_path
, "history");
6294 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6295 json_object_boolean_true_add(json_path
, "damped");
6297 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6298 json_object_boolean_true_add(json_path
, "bestpath");
6300 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6301 json_object_boolean_true_add(json_path
, "multipath");
6303 /* Internal route. */
6304 if ((binfo
->peer
->as
)
6305 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6306 json_object_string_add(json_path
, "pathFrom",
6309 json_object_string_add(json_path
, "pathFrom",
6315 /* Route status display. */
6316 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6318 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6320 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6322 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6323 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6329 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6331 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6333 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6335 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6340 /* Internal route. */
6341 if (binfo
->peer
&& (binfo
->peer
->as
)
6342 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6348 /* called from terminal list command */
6349 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6350 int display
, safi_t safi
, json_object
*json_paths
)
6353 json_object
*json_path
= NULL
;
6354 json_object
*json_nexthops
= NULL
;
6355 json_object
*json_nexthop_global
= NULL
;
6356 json_object
*json_nexthop_ll
= NULL
;
6359 json_path
= json_object_new_object();
6361 /* short status lead text */
6362 route_vty_short_status_out(vty
, binfo
, json_path
);
6365 /* print prefix and mask */
6367 route_vty_out_route(p
, vty
);
6369 vty_out(vty
, "%*s", 17, " ");
6372 /* Print attribute */
6376 * For ENCAP and EVPN routes, nexthop address family is not
6377 * neccessarily the same as the prefix address family.
6378 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6379 * EVPN routes are also exchanged with a MP nexthop. Currently,
6381 * is only IPv4, the value will be present in either
6383 * attr->mp_nexthop_global_in
6385 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6387 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6393 &attr
->mp_nexthop_global_in
,
6398 inet_ntop(af
, &attr
->mp_nexthop_global
,
6405 } else if (safi
== SAFI_EVPN
) {
6407 json_nexthop_global
= json_object_new_object();
6409 json_object_string_add(
6410 json_nexthop_global
, "ip",
6411 inet_ntoa(attr
->nexthop
));
6412 json_object_string_add(json_nexthop_global
,
6414 json_object_boolean_true_add(
6415 json_nexthop_global
, "used");
6417 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6420 else if (p
->family
== AF_INET
6421 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6423 json_nexthop_global
= json_object_new_object();
6425 if ((safi
== SAFI_MPLS_VPN
)
6426 || (safi
== SAFI_EVPN
))
6427 json_object_string_add(
6428 json_nexthop_global
, "ip",
6430 attr
->mp_nexthop_global_in
));
6432 json_object_string_add(
6433 json_nexthop_global
, "ip",
6434 inet_ntoa(attr
->nexthop
));
6436 json_object_string_add(json_nexthop_global
,
6438 json_object_boolean_true_add(
6439 json_nexthop_global
, "used");
6441 if ((safi
== SAFI_MPLS_VPN
)
6442 || (safi
== SAFI_EVPN
))
6443 vty_out(vty
, "%-16s",
6445 attr
->mp_nexthop_global_in
));
6447 vty_out(vty
, "%-16s",
6448 inet_ntoa(attr
->nexthop
));
6453 else if (p
->family
== AF_INET6
6454 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6459 json_nexthop_global
= json_object_new_object();
6460 json_object_string_add(
6461 json_nexthop_global
, "ip",
6463 &attr
->mp_nexthop_global
, buf
,
6465 json_object_string_add(json_nexthop_global
,
6467 json_object_string_add(json_nexthop_global
,
6470 /* We display both LL & GL if both have been
6472 if ((attr
->mp_nexthop_len
== 32)
6473 || (binfo
->peer
->conf_if
)) {
6475 json_object_new_object();
6476 json_object_string_add(
6477 json_nexthop_ll
, "ip",
6480 &attr
->mp_nexthop_local
,
6482 json_object_string_add(json_nexthop_ll
,
6484 json_object_string_add(json_nexthop_ll
,
6489 &attr
->mp_nexthop_global
,
6490 &attr
->mp_nexthop_local
)
6492 && !attr
->mp_nexthop_prefer_global
)
6493 json_object_boolean_true_add(
6497 json_object_boolean_true_add(
6498 json_nexthop_global
,
6501 json_object_boolean_true_add(
6502 json_nexthop_global
, "used");
6504 /* Display LL if LL/Global both in table unless
6505 * prefer-global is set */
6506 if (((attr
->mp_nexthop_len
== 32)
6507 && !attr
->mp_nexthop_prefer_global
)
6508 || (binfo
->peer
->conf_if
)) {
6509 if (binfo
->peer
->conf_if
) {
6512 binfo
->peer
->conf_if
);
6513 len
= 7 - len
; /* len of IPv6
6519 vty_out(vty
, "\n%*s",
6522 vty_out(vty
, "%*s", len
,
6529 &attr
->mp_nexthop_local
,
6534 vty_out(vty
, "\n%*s",
6537 vty_out(vty
, "%*s", len
,
6545 &attr
->mp_nexthop_global
,
6550 vty_out(vty
, "\n%*s", 36, " ");
6552 vty_out(vty
, "%*s", len
, " ");
6558 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6560 json_object_int_add(json_path
, "med",
6563 vty_out(vty
, "%10u", attr
->med
);
6564 else if (!json_paths
)
6568 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6570 json_object_int_add(json_path
, "localpref",
6573 vty_out(vty
, "%7u", attr
->local_pref
);
6574 else if (!json_paths
)
6578 json_object_int_add(json_path
, "weight", attr
->weight
);
6580 vty_out(vty
, "%7u ", attr
->weight
);
6584 json_object_string_add(json_path
, "peerId",
6585 sockunion2str(&binfo
->peer
->su
,
6593 json_object_string_add(json_path
, "aspath",
6596 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6601 json_object_string_add(
6602 json_path
, "origin",
6603 bgp_origin_long_str
[attr
->origin
]);
6605 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6608 json_object_string_add(json_path
, "alert",
6611 vty_out(vty
, "No attributes to print\n");
6615 if (json_nexthop_global
|| json_nexthop_ll
) {
6616 json_nexthops
= json_object_new_array();
6618 if (json_nexthop_global
)
6619 json_object_array_add(json_nexthops
,
6620 json_nexthop_global
);
6622 if (json_nexthop_ll
)
6623 json_object_array_add(json_nexthops
,
6626 json_object_object_add(json_path
, "nexthops",
6630 json_object_array_add(json_paths
, json_path
);
6634 /* prints an additional line, indented, with VNC info, if
6636 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6637 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6642 /* called from terminal list command */
6643 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6644 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6646 json_object
*json_status
= NULL
;
6647 json_object
*json_net
= NULL
;
6649 /* Route status display. */
6651 json_status
= json_object_new_object();
6652 json_net
= json_object_new_object();
6659 /* print prefix and mask */
6661 json_object_string_add(
6662 json_net
, "addrPrefix",
6663 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6665 route_vty_out_route(p
, vty
);
6667 /* Print attribute */
6670 if (p
->family
== AF_INET
6671 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6672 || safi
== SAFI_EVPN
6673 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6674 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6675 || safi
== SAFI_EVPN
)
6676 json_object_string_add(
6677 json_net
, "nextHop",
6679 attr
->mp_nexthop_global_in
));
6681 json_object_string_add(
6682 json_net
, "nextHop",
6683 inet_ntoa(attr
->nexthop
));
6684 } else if (p
->family
== AF_INET6
6685 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6688 json_object_string_add(
6689 json_net
, "netHopGloabal",
6691 &attr
->mp_nexthop_global
, buf
,
6696 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6697 json_object_int_add(json_net
, "metric",
6700 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6701 json_object_int_add(json_net
, "localPref",
6704 json_object_int_add(json_net
, "weight", attr
->weight
);
6708 json_object_string_add(json_net
, "asPath",
6712 json_object_string_add(json_net
, "bgpOriginCode",
6713 bgp_origin_str
[attr
->origin
]);
6715 if (p
->family
== AF_INET
6716 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6717 || safi
== SAFI_EVPN
6718 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6719 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6720 || safi
== SAFI_EVPN
)
6721 vty_out(vty
, "%-16s",
6723 attr
->mp_nexthop_global_in
));
6725 vty_out(vty
, "%-16s",
6726 inet_ntoa(attr
->nexthop
));
6727 } else if (p
->family
== AF_INET6
6728 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6735 &attr
->mp_nexthop_global
, buf
,
6739 vty_out(vty
, "\n%*s", 36, " ");
6741 vty_out(vty
, "%*s", len
, " ");
6744 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6745 vty_out(vty
, "%10u", attr
->med
);
6749 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6750 vty_out(vty
, "%7u", attr
->local_pref
);
6754 vty_out(vty
, "%7u ", attr
->weight
);
6758 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6761 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6765 json_object_boolean_true_add(json_status
, "*");
6766 json_object_boolean_true_add(json_status
, ">");
6767 json_object_object_add(json_net
, "appliedStatusSymbols",
6769 char buf_cut
[BUFSIZ
];
6770 json_object_object_add(
6772 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6778 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6779 struct bgp_info
*binfo
, int display
, safi_t safi
,
6782 json_object
*json_out
= NULL
;
6784 mpls_label_t label
= MPLS_INVALID_LABEL
;
6790 json_out
= json_object_new_object();
6792 /* short status lead text */
6793 route_vty_short_status_out(vty
, binfo
, json_out
);
6795 /* print prefix and mask */
6798 route_vty_out_route(p
, vty
);
6800 vty_out(vty
, "%*s", 17, " ");
6803 /* Print attribute */
6806 if (((p
->family
== AF_INET
)
6807 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6808 || (safi
== SAFI_EVPN
&& p
->family
== AF_ETHERNET
6809 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6810 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6811 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6812 || safi
== SAFI_EVPN
) {
6814 json_object_string_add(
6815 json_out
, "mpNexthopGlobalIn",
6817 attr
->mp_nexthop_global_in
));
6819 vty_out(vty
, "%-16s",
6821 attr
->mp_nexthop_global_in
));
6824 json_object_string_add(
6825 json_out
, "nexthop",
6826 inet_ntoa(attr
->nexthop
));
6828 vty_out(vty
, "%-16s",
6829 inet_ntoa(attr
->nexthop
));
6831 } else if (((p
->family
== AF_INET6
)
6832 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6833 || (safi
== SAFI_EVPN
&& p
->family
== AF_ETHERNET
6834 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6835 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6839 if (attr
->mp_nexthop_len
6840 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6842 json_object_string_add(
6843 json_out
, "mpNexthopGlobalIn",
6846 &attr
->mp_nexthop_global
,
6852 &attr
->mp_nexthop_global
,
6854 } else if (attr
->mp_nexthop_len
6855 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6858 &attr
->mp_nexthop_global
,
6861 &attr
->mp_nexthop_local
,
6863 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6864 json_object_string_add(
6866 "mpNexthopGlobalLocal", buf_c
);
6868 vty_out(vty
, "%s(%s)",
6871 &attr
->mp_nexthop_global
,
6875 &attr
->mp_nexthop_local
,
6881 label
= decode_label(&binfo
->extra
->label
);
6883 if (bgp_is_valid_label(&label
)) {
6885 json_object_int_add(json_out
, "notag", label
);
6886 json_object_array_add(json
, json_out
);
6888 vty_out(vty
, "notag/%d", label
);
6894 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6895 struct bgp_info
*binfo
, int display
,
6896 json_object
*json_paths
)
6900 json_object
*json_path
= NULL
;
6903 json_path
= json_object_new_object();
6908 /* short status lead text */
6909 route_vty_short_status_out(vty
, binfo
, json_path
);
6911 /* print prefix and mask */
6913 route_vty_out_route(p
, vty
);
6915 vty_out(vty
, "%*s", 17, " ");
6917 /* Print attribute */
6921 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6925 vty_out(vty
, "%-16s",
6926 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6930 vty_out(vty
, "%s(%s)",
6931 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6933 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
6941 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
6942 char *str
= esi2str(id
);
6943 vty_out(vty
, "%s", str
);
6944 XFREE(MTYPE_TMP
, str
);
6945 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
6946 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
6947 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
6949 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
6952 if (attr
->ecommunity
) {
6954 struct ecommunity_val
*routermac
= ecommunity_lookup(
6955 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
6956 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
6958 mac
= ecom_mac2str((char *)routermac
->val
);
6960 vty_out(vty
, "/%s", (char *)mac
);
6961 XFREE(MTYPE_TMP
, mac
);
6967 /* dampening route */
6968 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6969 struct bgp_info
*binfo
, int display
, safi_t safi
,
6970 u_char use_json
, json_object
*json
)
6974 char timebuf
[BGP_UPTIME_LEN
];
6976 /* short status lead text */
6977 route_vty_short_status_out(vty
, binfo
, json
);
6979 /* print prefix and mask */
6982 route_vty_out_route(p
, vty
);
6984 vty_out(vty
, "%*s", 17, " ");
6987 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6991 vty_out(vty
, "\n%*s", 34, " ");
6994 json_object_int_add(json
, "peerHost", len
);
6996 vty_out(vty
, "%*s", len
, " ");
7000 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7004 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7005 BGP_UPTIME_LEN
, use_json
,
7008 /* Print attribute */
7014 json_object_string_add(json
, "asPath",
7017 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7022 json_object_string_add(json
, "origin",
7023 bgp_origin_str
[attr
->origin
]);
7025 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7032 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7033 struct bgp_info
*binfo
, int display
, safi_t safi
,
7034 u_char use_json
, json_object
*json
)
7037 struct bgp_damp_info
*bdi
;
7038 char timebuf
[BGP_UPTIME_LEN
];
7044 bdi
= binfo
->extra
->damp_info
;
7046 /* short status lead text */
7047 route_vty_short_status_out(vty
, binfo
, json
);
7049 /* print prefix and mask */
7052 route_vty_out_route(p
, vty
);
7054 vty_out(vty
, "%*s", 17, " ");
7057 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7061 vty_out(vty
, "\n%*s", 33, " ");
7064 json_object_int_add(json
, "peerHost", len
);
7066 vty_out(vty
, "%*s", len
, " ");
7069 len
= vty_out(vty
, "%d", bdi
->flap
);
7076 json_object_int_add(json
, "bdiFlap", len
);
7078 vty_out(vty
, "%*s", len
, " ");
7082 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7086 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, 0,
7089 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7090 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7092 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7093 BGP_UPTIME_LEN
, use_json
, json
);
7096 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7101 vty_out(vty
, "%*s ", 8, " ");
7104 /* Print attribute */
7110 json_object_string_add(json
, "asPath",
7113 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7118 json_object_string_add(json
, "origin",
7119 bgp_origin_str
[attr
->origin
]);
7121 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7127 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7128 int *first
, const char *header
,
7129 json_object
*json_adv_to
)
7131 char buf1
[INET6_ADDRSTRLEN
];
7132 json_object
*json_peer
= NULL
;
7135 /* 'advertised-to' is a dictionary of peers we have advertised
7137 * prefix too. The key is the peer's IP or swpX, the value is
7139 * hostname if we know it and "" if not.
7141 json_peer
= json_object_new_object();
7144 json_object_string_add(json_peer
, "hostname",
7148 json_object_object_add(json_adv_to
, peer
->conf_if
,
7151 json_object_object_add(
7153 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7157 vty_out(vty
, "%s", header
);
7162 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7164 vty_out(vty
, " %s(%s)", peer
->hostname
,
7167 vty_out(vty
, " %s(%s)", peer
->hostname
,
7168 sockunion2str(&peer
->su
, buf1
,
7172 vty_out(vty
, " %s", peer
->conf_if
);
7175 sockunion2str(&peer
->su
, buf1
,
7181 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7182 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7183 json_object
*json_paths
)
7185 char buf
[INET6_ADDRSTRLEN
];
7187 #if defined(HAVE_CUMULUS)
7188 char buf2
[EVPN_ROUTE_STRLEN
];
7191 int sockunion_vty_out(struct vty
*, union sockunion
*);
7193 json_object
*json_bestpath
= NULL
;
7194 json_object
*json_cluster_list
= NULL
;
7195 json_object
*json_cluster_list_list
= NULL
;
7196 json_object
*json_ext_community
= NULL
;
7197 json_object
*json_last_update
= NULL
;
7198 json_object
*json_nexthop_global
= NULL
;
7199 json_object
*json_nexthop_ll
= NULL
;
7200 json_object
*json_nexthops
= NULL
;
7201 json_object
*json_path
= NULL
;
7202 json_object
*json_peer
= NULL
;
7203 json_object
*json_string
= NULL
;
7204 json_object
*json_adv_to
= NULL
;
7206 struct listnode
*node
, *nnode
;
7208 int addpath_capable
;
7210 unsigned int first_as
;
7213 json_path
= json_object_new_object();
7214 json_peer
= json_object_new_object();
7215 json_nexthop_global
= json_object_new_object();
7218 #if defined(HAVE_CUMULUS)
7219 if (!json_paths
&& safi
== SAFI_EVPN
) {
7222 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7223 vty_out(vty
, " Route %s", buf2
);
7226 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7228 vty_out(vty
, " VNI %s", tag_buf
);
7231 if (binfo
->extra
&& binfo
->extra
->parent
) {
7232 struct bgp_info
*parent_ri
;
7233 struct bgp_node
*rn
, *prn
;
7235 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7236 rn
= parent_ri
->net
;
7237 if (rn
&& rn
->prn
) {
7239 vty_out(vty
, " Imported from %s:%s\n",
7241 (struct prefix_rd
*)&prn
->p
,
7242 buf1
, RD_ADDRSTRLEN
),
7252 /* Line1 display AS-path, Aggregator */
7255 json_object_lock(attr
->aspath
->json
);
7256 json_object_object_add(json_path
, "aspath",
7257 attr
->aspath
->json
);
7259 if (attr
->aspath
->segments
)
7260 aspath_print_vty(vty
, " %s",
7263 vty_out(vty
, " Local");
7267 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7269 json_object_boolean_true_add(json_path
,
7272 vty_out(vty
, ", (removed)");
7275 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7277 json_object_boolean_true_add(json_path
,
7280 vty_out(vty
, ", (stale)");
7283 if (CHECK_FLAG(attr
->flag
,
7284 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7286 json_object_int_add(json_path
, "aggregatorAs",
7287 attr
->aggregator_as
);
7288 json_object_string_add(
7289 json_path
, "aggregatorId",
7290 inet_ntoa(attr
->aggregator_addr
));
7292 vty_out(vty
, ", (aggregated by %u %s)",
7293 attr
->aggregator_as
,
7294 inet_ntoa(attr
->aggregator_addr
));
7298 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7299 PEER_FLAG_REFLECTOR_CLIENT
)) {
7301 json_object_boolean_true_add(
7302 json_path
, "rxedFromRrClient");
7304 vty_out(vty
, ", (Received from a RR-client)");
7307 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7308 PEER_FLAG_RSERVER_CLIENT
)) {
7310 json_object_boolean_true_add(
7311 json_path
, "rxedFromRsClient");
7313 vty_out(vty
, ", (Received from a RS-client)");
7316 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7318 json_object_boolean_true_add(
7319 json_path
, "dampeningHistoryEntry");
7321 vty_out(vty
, ", (history entry)");
7322 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7324 json_object_boolean_true_add(
7325 json_path
, "dampeningSuppressed");
7327 vty_out(vty
, ", (suppressed due to dampening)");
7333 /* Line2 display Next-hop, Neighbor, Router-id */
7334 /* Display the nexthop */
7335 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
)
7336 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7337 || safi
== SAFI_EVPN
7338 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7339 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7340 || safi
== SAFI_EVPN
) {
7342 json_object_string_add(
7343 json_nexthop_global
, "ip",
7345 attr
->mp_nexthop_global_in
));
7349 attr
->mp_nexthop_global_in
));
7352 json_object_string_add(
7353 json_nexthop_global
, "ip",
7354 inet_ntoa(attr
->nexthop
));
7357 inet_ntoa(attr
->nexthop
));
7361 json_object_string_add(json_nexthop_global
,
7365 json_object_string_add(
7366 json_nexthop_global
, "ip",
7368 &attr
->mp_nexthop_global
, buf
,
7370 json_object_string_add(json_nexthop_global
,
7372 json_object_string_add(json_nexthop_global
,
7377 &attr
->mp_nexthop_global
, buf
,
7382 /* Display the IGP cost or 'inaccessible' */
7383 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7385 json_object_boolean_false_add(
7386 json_nexthop_global
, "accessible");
7388 vty_out(vty
, " (inaccessible)");
7390 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7392 json_object_int_add(
7393 json_nexthop_global
, "metric",
7394 binfo
->extra
->igpmetric
);
7396 vty_out(vty
, " (metric %u)",
7397 binfo
->extra
->igpmetric
);
7400 /* IGP cost is 0, display this only for json */
7403 json_object_int_add(json_nexthop_global
,
7408 json_object_boolean_true_add(
7409 json_nexthop_global
, "accessible");
7412 /* Display peer "from" output */
7413 /* This path was originated locally */
7414 if (binfo
->peer
== bgp
->peer_self
) {
7416 if (safi
== SAFI_EVPN
7417 || (p
->family
== AF_INET
7418 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7420 json_object_string_add(
7421 json_peer
, "peerId", "0.0.0.0");
7423 vty_out(vty
, " from 0.0.0.0 ");
7426 json_object_string_add(json_peer
,
7429 vty_out(vty
, " from :: ");
7433 json_object_string_add(
7434 json_peer
, "routerId",
7435 inet_ntoa(bgp
->router_id
));
7437 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7440 /* We RXed this path from one of our peers */
7444 json_object_string_add(
7445 json_peer
, "peerId",
7446 sockunion2str(&binfo
->peer
->su
, buf
,
7448 json_object_string_add(
7449 json_peer
, "routerId",
7451 &binfo
->peer
->remote_id
, buf1
,
7454 if (binfo
->peer
->hostname
)
7455 json_object_string_add(
7456 json_peer
, "hostname",
7457 binfo
->peer
->hostname
);
7459 if (binfo
->peer
->domainname
)
7460 json_object_string_add(
7461 json_peer
, "domainname",
7462 binfo
->peer
->domainname
);
7464 if (binfo
->peer
->conf_if
)
7465 json_object_string_add(
7466 json_peer
, "interface",
7467 binfo
->peer
->conf_if
);
7469 if (binfo
->peer
->conf_if
) {
7470 if (binfo
->peer
->hostname
7473 BGP_FLAG_SHOW_HOSTNAME
))
7474 vty_out(vty
, " from %s(%s)",
7475 binfo
->peer
->hostname
,
7476 binfo
->peer
->conf_if
);
7478 vty_out(vty
, " from %s",
7479 binfo
->peer
->conf_if
);
7481 if (binfo
->peer
->hostname
7484 BGP_FLAG_SHOW_HOSTNAME
))
7485 vty_out(vty
, " from %s(%s)",
7486 binfo
->peer
->hostname
,
7489 vty_out(vty
, " from %s",
7498 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7499 vty_out(vty
, " (%s)",
7500 inet_ntoa(attr
->originator_id
));
7502 vty_out(vty
, " (%s)",
7505 &binfo
->peer
->remote_id
,
7513 /* display the link-local nexthop */
7514 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7516 json_nexthop_ll
= json_object_new_object();
7517 json_object_string_add(
7518 json_nexthop_ll
, "ip",
7520 &attr
->mp_nexthop_local
, buf
,
7522 json_object_string_add(json_nexthop_ll
, "afi",
7524 json_object_string_add(json_nexthop_ll
, "scope",
7527 json_object_boolean_true_add(json_nexthop_ll
,
7530 if (!attr
->mp_nexthop_prefer_global
)
7531 json_object_boolean_true_add(
7532 json_nexthop_ll
, "used");
7534 json_object_boolean_true_add(
7535 json_nexthop_global
, "used");
7537 vty_out(vty
, " (%s) %s\n",
7539 &attr
->mp_nexthop_local
, buf
,
7541 attr
->mp_nexthop_prefer_global
7546 /* If we do not have a link-local nexthop then we must flag the
7550 json_object_boolean_true_add(
7551 json_nexthop_global
, "used");
7554 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7555 * Int/Ext/Local, Atomic, best */
7557 json_object_string_add(
7558 json_path
, "origin",
7559 bgp_origin_long_str
[attr
->origin
]);
7561 vty_out(vty
, " Origin %s",
7562 bgp_origin_long_str
[attr
->origin
]);
7564 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7566 json_object_int_add(json_path
, "med",
7569 vty_out(vty
, ", metric %u", attr
->med
);
7572 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7574 json_object_int_add(json_path
, "localpref",
7577 vty_out(vty
, ", localpref %u",
7581 json_object_int_add(json_path
, "localpref",
7582 bgp
->default_local_pref
);
7584 vty_out(vty
, ", localpref %u",
7585 bgp
->default_local_pref
);
7588 if (attr
->weight
!= 0) {
7590 json_object_int_add(json_path
, "weight",
7593 vty_out(vty
, ", weight %u", attr
->weight
);
7596 if (attr
->tag
!= 0) {
7598 json_object_int_add(json_path
, "tag",
7601 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7605 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7607 json_object_boolean_false_add(json_path
,
7610 vty_out(vty
, ", invalid");
7611 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7613 json_object_boolean_true_add(json_path
,
7616 vty_out(vty
, ", valid");
7619 if (binfo
->peer
!= bgp
->peer_self
) {
7620 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7621 if (CHECK_FLAG(bgp
->config
,
7622 BGP_CONFIG_CONFEDERATION
)) {
7624 json_object_string_add(
7629 ", confed-internal");
7632 json_object_string_add(
7636 vty_out(vty
, ", internal");
7639 if (bgp_confederation_peers_check(
7640 bgp
, binfo
->peer
->as
)) {
7642 json_object_string_add(
7647 ", confed-external");
7650 json_object_string_add(
7654 vty_out(vty
, ", external");
7657 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7659 json_object_boolean_true_add(json_path
,
7661 json_object_boolean_true_add(json_path
,
7664 vty_out(vty
, ", aggregated, local");
7666 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7668 json_object_boolean_true_add(json_path
,
7671 vty_out(vty
, ", sourced");
7674 json_object_boolean_true_add(json_path
,
7676 json_object_boolean_true_add(json_path
,
7679 vty_out(vty
, ", sourced, local");
7683 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7685 json_object_boolean_true_add(json_path
,
7688 vty_out(vty
, ", atomic-aggregate");
7691 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7692 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7693 && bgp_info_mpath_count(binfo
))) {
7695 json_object_boolean_true_add(json_path
,
7698 vty_out(vty
, ", multipath");
7701 // Mark the bestpath(s)
7702 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7703 first_as
= aspath_get_first_as(attr
->aspath
);
7708 json_object_new_object();
7709 json_object_int_add(json_bestpath
,
7710 "bestpathFromAs", first_as
);
7713 vty_out(vty
, ", bestpath-from-AS %d",
7717 ", bestpath-from-AS Local");
7721 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7725 json_object_new_object();
7726 json_object_boolean_true_add(json_bestpath
,
7729 vty_out(vty
, ", best");
7733 json_object_object_add(json_path
, "bestpath",
7739 /* Line 4 display Community */
7740 if (attr
->community
) {
7742 json_object_lock(attr
->community
->json
);
7743 json_object_object_add(json_path
, "community",
7744 attr
->community
->json
);
7746 vty_out(vty
, " Community: %s\n",
7747 attr
->community
->str
);
7751 /* Line 5 display Extended-community */
7752 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7754 json_ext_community
= json_object_new_object();
7755 json_object_string_add(json_ext_community
,
7757 attr
->ecommunity
->str
);
7758 json_object_object_add(json_path
,
7759 "extendedCommunity",
7760 json_ext_community
);
7762 vty_out(vty
, " Extended Community: %s\n",
7763 attr
->ecommunity
->str
);
7767 /* Line 6 display Large community */
7768 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
))
7769 vty_out(vty
, " Large Community: %s\n",
7770 attr
->lcommunity
->str
);
7772 /* Line 7 display Originator, Cluster-id */
7773 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7774 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7776 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7778 json_object_string_add(
7779 json_path
, "originatorId",
7780 inet_ntoa(attr
->originator_id
));
7782 vty_out(vty
, " Originator: %s",
7783 inet_ntoa(attr
->originator_id
));
7786 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7791 json_object_new_object();
7792 json_cluster_list_list
=
7793 json_object_new_array();
7796 i
< attr
->cluster
->length
/ 4;
7798 json_string
= json_object_new_string(
7802 json_object_array_add(
7803 json_cluster_list_list
,
7807 /* struct cluster_list does not have
7809 * aspath and community do. Add this
7812 json_object_string_add(json_cluster_list,
7813 "string", attr->cluster->str);
7815 json_object_object_add(
7816 json_cluster_list
, "list",
7817 json_cluster_list_list
);
7818 json_object_object_add(
7819 json_path
, "clusterList",
7822 vty_out(vty
, ", Cluster list: ");
7825 i
< attr
->cluster
->length
/ 4;
7839 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7840 bgp_damp_info_vty(vty
, binfo
, json_path
);
7843 #if defined(HAVE_CUMULUS)
7844 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7845 && safi
!= SAFI_EVPN
)
7847 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
7850 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
7852 json_object_int_add(json_path
, "remoteLabel",
7855 vty_out(vty
, " Remote label: %d\n", label
);
7859 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7861 json_object_int_add(json_path
, "labelIndex",
7864 vty_out(vty
, " Label Index: %d\n",
7868 /* Line 8 display Addpath IDs */
7869 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7871 json_object_int_add(json_path
, "addpathRxId",
7872 binfo
->addpath_rx_id
);
7873 json_object_int_add(json_path
, "addpathTxId",
7874 binfo
->addpath_tx_id
);
7876 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7877 binfo
->addpath_rx_id
,
7878 binfo
->addpath_tx_id
);
7882 /* If we used addpath to TX a non-bestpath we need to display
7883 * "Advertised to" on a path-by-path basis */
7884 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7887 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7889 bgp_addpath_encode_tx(peer
, afi
, safi
);
7890 has_adj
= bgp_adj_out_lookup(
7891 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7893 if ((addpath_capable
&& has_adj
)
7894 || (!addpath_capable
&& has_adj
7895 && CHECK_FLAG(binfo
->flags
,
7896 BGP_INFO_SELECTED
))) {
7897 if (json_path
&& !json_adv_to
)
7899 json_object_new_object();
7901 route_vty_out_advertised_to(
7910 json_object_object_add(json_path
,
7921 /* Line 9 display Uptime */
7922 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
7924 json_last_update
= json_object_new_object();
7925 json_object_int_add(json_last_update
, "epoch", tbuf
);
7926 json_object_string_add(json_last_update
, "string",
7928 json_object_object_add(json_path
, "lastUpdate",
7931 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
7934 /* We've constructed the json object for this path, add it to the json
7938 if (json_nexthop_global
|| json_nexthop_ll
) {
7939 json_nexthops
= json_object_new_array();
7941 if (json_nexthop_global
)
7942 json_object_array_add(json_nexthops
,
7943 json_nexthop_global
);
7945 if (json_nexthop_ll
)
7946 json_object_array_add(json_nexthops
,
7949 json_object_object_add(json_path
, "nexthops",
7953 json_object_object_add(json_path
, "peer", json_peer
);
7954 json_object_array_add(json_paths
, json_path
);
7959 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7960 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7961 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
7963 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
7964 const char *prefix_list_str
, afi_t afi
,
7965 safi_t safi
, enum bgp_show_type type
);
7966 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
7967 const char *filter
, afi_t afi
, safi_t safi
,
7968 enum bgp_show_type type
);
7969 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
7970 const char *rmap_str
, afi_t afi
, safi_t safi
,
7971 enum bgp_show_type type
);
7972 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
7973 const char *com
, int exact
, afi_t afi
,
7975 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
7976 const char *prefix
, afi_t afi
, safi_t safi
,
7977 enum bgp_show_type type
);
7978 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
7979 safi_t safi
, enum bgp_show_type type
);
7980 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
7981 struct cmd_token
**argv
, int exact
, afi_t afi
,
7984 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
,
7985 struct bgp_table
*table
, enum bgp_show_type type
,
7986 void *output_arg
, u_char use_json
)
7988 struct bgp_info
*ri
;
7989 struct bgp_node
*rn
;
7992 unsigned long output_count
;
7993 unsigned long total_count
;
7997 json_object
*json_paths
= NULL
;
8002 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
8003 ", \"routerId\": \"%s\", \"routes\": { ",
8004 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
8005 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8007 table
->version
, inet_ntoa(bgp
->router_id
));
8008 json_paths
= json_object_new_object();
8011 /* This is first entry point, so reset total line. */
8015 /* Start processing of routes. */
8016 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
8017 if (rn
->info
!= NULL
) {
8019 if (!first
&& use_json
) {
8023 json_paths
= json_object_new_array();
8027 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8029 if (type
== bgp_show_type_flap_statistics
8030 || type
== bgp_show_type_flap_neighbor
8031 || type
== bgp_show_type_dampend_paths
8032 || type
== bgp_show_type_damp_neighbor
) {
8034 && ri
->extra
->damp_info
))
8037 if (type
== bgp_show_type_regexp
) {
8038 regex_t
*regex
= output_arg
;
8040 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8044 if (type
== bgp_show_type_prefix_list
) {
8045 struct prefix_list
*plist
= output_arg
;
8047 if (prefix_list_apply(plist
, &rn
->p
)
8051 if (type
== bgp_show_type_filter_list
) {
8052 struct as_list
*as_list
= output_arg
;
8054 if (as_list_apply(as_list
,
8056 != AS_FILTER_PERMIT
)
8059 if (type
== bgp_show_type_route_map
) {
8060 struct route_map
*rmap
= output_arg
;
8061 struct bgp_info binfo
;
8062 struct attr dummy_attr
;
8065 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8067 binfo
.peer
= ri
->peer
;
8068 binfo
.attr
= &dummy_attr
;
8070 ret
= route_map_apply(rmap
, &rn
->p
,
8072 if (ret
== RMAP_DENYMATCH
)
8075 if (type
== bgp_show_type_neighbor
8076 || type
== bgp_show_type_flap_neighbor
8077 || type
== bgp_show_type_damp_neighbor
) {
8078 union sockunion
*su
= output_arg
;
8080 if (ri
->peer
== NULL
8081 || ri
->peer
->su_remote
== NULL
8083 ri
->peer
->su_remote
, su
))
8086 if (type
== bgp_show_type_cidr_only
) {
8087 u_int32_t destination
;
8090 ntohl(rn
->p
.u
.prefix4
.s_addr
);
8091 if (IN_CLASSC(destination
)
8092 && rn
->p
.prefixlen
== 24)
8094 if (IN_CLASSB(destination
)
8095 && rn
->p
.prefixlen
== 16)
8097 if (IN_CLASSA(destination
)
8098 && rn
->p
.prefixlen
== 8)
8101 if (type
== bgp_show_type_prefix_longer
) {
8102 struct prefix
*p
= output_arg
;
8104 if (!prefix_match(p
, &rn
->p
))
8107 if (type
== bgp_show_type_community_all
) {
8108 if (!ri
->attr
->community
)
8111 if (type
== bgp_show_type_community
) {
8112 struct community
*com
= output_arg
;
8114 if (!ri
->attr
->community
8115 || !community_match(
8116 ri
->attr
->community
,
8120 if (type
== bgp_show_type_community_exact
) {
8121 struct community
*com
= output_arg
;
8123 if (!ri
->attr
->community
8125 ri
->attr
->community
,
8129 if (type
== bgp_show_type_community_list
) {
8130 struct community_list
*list
=
8133 if (!community_list_match(
8134 ri
->attr
->community
, list
))
8138 == bgp_show_type_community_list_exact
) {
8139 struct community_list
*list
=
8142 if (!community_list_exact_match(
8143 ri
->attr
->community
, list
))
8146 if (type
== bgp_show_type_lcommunity
) {
8147 struct lcommunity
*lcom
= output_arg
;
8149 if (!ri
->attr
->lcommunity
8150 || !lcommunity_match(
8151 ri
->attr
->lcommunity
,
8155 if (type
== bgp_show_type_lcommunity_list
) {
8156 struct community_list
*list
=
8159 if (!lcommunity_list_match(
8160 ri
->attr
->lcommunity
, list
))
8163 if (type
== bgp_show_type_lcommunity_all
) {
8164 if (!ri
->attr
->lcommunity
)
8167 if (type
== bgp_show_type_dampend_paths
8168 || type
== bgp_show_type_damp_neighbor
) {
8169 if (!CHECK_FLAG(ri
->flags
,
8171 || CHECK_FLAG(ri
->flags
,
8176 if (!use_json
&& header
) {
8178 "BGP table version is %" PRIu64
8179 ", local router ID is %s\n",
8181 inet_ntoa(bgp
->router_id
));
8182 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8183 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8184 if (type
== bgp_show_type_dampend_paths
8185 || type
== bgp_show_type_damp_neighbor
)
8187 BGP_SHOW_DAMP_HEADER
);
8189 type
== bgp_show_type_flap_statistics
8190 || type
== bgp_show_type_flap_neighbor
)
8192 BGP_SHOW_FLAP_HEADER
);
8194 vty_out(vty
, BGP_SHOW_HEADER
);
8198 if (type
== bgp_show_type_dampend_paths
8199 || type
== bgp_show_type_damp_neighbor
)
8201 vty
, &rn
->p
, ri
, display
,
8202 SAFI_UNICAST
, use_json
,
8204 else if (type
== bgp_show_type_flap_statistics
8205 || type
== bgp_show_type_flap_neighbor
)
8207 vty
, &rn
->p
, ri
, display
,
8208 SAFI_UNICAST
, use_json
,
8211 route_vty_out(vty
, &rn
->p
, ri
, display
,
8212 SAFI_UNICAST
, json_paths
);
8220 sprintf(buf2
, "%s/%d",
8221 inet_ntop(p
->family
,
8225 vty_out(vty
, "\"%s\": ", buf2
);
8227 json_object_to_json_string(
8229 json_object_free(json_paths
);
8236 json_object_free(json_paths
);
8237 vty_out(vty
, " } }\n");
8239 /* No route is displayed */
8240 if (output_count
== 0) {
8241 if (type
== bgp_show_type_normal
)
8243 "No BGP prefixes displayed, %ld exist\n",
8247 "\nDisplayed %ld routes and %ld total paths\n",
8248 output_count
, total_count
);
8254 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8255 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8257 struct bgp_table
*table
;
8260 bgp
= bgp_get_default();
8265 vty_out(vty
, "No BGP process is configured\n");
8269 /* use MPLS and ENCAP specific shows until they are merged */
8270 if (safi
== SAFI_MPLS_VPN
) {
8271 return bgp_show_mpls_vpn(vty
, afi
, NULL
, type
, output_arg
, 0,
8274 /* labeled-unicast routes live in the unicast table */
8275 else if (safi
== SAFI_LABELED_UNICAST
)
8276 safi
= SAFI_UNICAST
;
8278 table
= bgp
->rib
[afi
][safi
];
8280 return bgp_show_table(vty
, bgp
, table
, type
, output_arg
, use_json
);
8283 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8284 safi_t safi
, u_char use_json
)
8286 struct listnode
*node
, *nnode
;
8291 vty_out(vty
, "{\n");
8293 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8296 vty_out(vty
, ",\n");
8300 vty_out(vty
, "\"%s\":",
8301 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8305 vty_out(vty
, "\nInstance %s:\n",
8306 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8310 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8315 vty_out(vty
, "}\n");
8318 /* Header of detailed BGP route information */
8319 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8320 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8321 afi_t afi
, safi_t safi
, json_object
*json
)
8323 struct bgp_info
*ri
;
8326 struct listnode
*node
, *nnode
;
8327 char buf1
[INET6_ADDRSTRLEN
];
8328 char buf2
[INET6_ADDRSTRLEN
];
8329 #if defined(HAVE_CUMULUS)
8330 char buf3
[EVPN_ROUTE_STRLEN
];
8336 int no_advertise
= 0;
8339 int has_valid_label
= 0;
8340 mpls_label_t label
= 0;
8341 json_object
*json_adv_to
= NULL
;
8344 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8346 if (has_valid_label
)
8347 label
= label_pton(&rn
->local_label
);
8350 if (has_valid_label
)
8351 json_object_int_add(json
, "localLabel", label
);
8353 json_object_string_add(json
, "prefix",
8354 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8356 json_object_int_add(json
, "prefixlen", p
->prefixlen
);
8358 #if defined(HAVE_CUMULUS)
8359 if (safi
== SAFI_EVPN
)
8360 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8361 prd
? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8364 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8365 buf3
, sizeof(buf3
)));
8367 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8368 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8369 ? prefix_rd2str(prd
, buf1
,
8372 safi
== SAFI_MPLS_VPN
? ":" : "",
8373 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8377 if (p
->family
== AF_ETHERNET
)
8378 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8380 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8382 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8383 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8384 || safi
== SAFI_EVPN
)
8385 ? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8387 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8389 buf2
, p
->prefixlen
);
8392 if (has_valid_label
)
8393 vty_out(vty
, "Local label: %d\n", label
);
8394 #if defined(HAVE_CUMULUS)
8395 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8397 if (bgp_labeled_safi(safi
))
8399 vty_out(vty
, "not allocated\n");
8402 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8404 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8406 if (ri
->extra
&& ri
->extra
->suppress
)
8408 if (ri
->attr
->community
!= NULL
) {
8409 if (community_include(ri
->attr
->community
,
8410 COMMUNITY_NO_ADVERTISE
))
8412 if (community_include(ri
->attr
->community
,
8413 COMMUNITY_NO_EXPORT
))
8415 if (community_include(ri
->attr
->community
,
8416 COMMUNITY_LOCAL_AS
))
8423 vty_out(vty
, "Paths: (%d available", count
);
8425 vty_out(vty
, ", best #%d", best
);
8426 if (safi
== SAFI_UNICAST
)
8427 vty_out(vty
, ", table %s",
8429 == BGP_INSTANCE_TYPE_DEFAULT
)
8430 ? "Default-IP-Routing-Table"
8433 vty_out(vty
, ", no best path");
8436 vty_out(vty
, ", not advertised to any peer");
8438 vty_out(vty
, ", not advertised to EBGP peer");
8440 vty_out(vty
, ", not advertised outside local AS");
8444 ", Advertisements suppressed by an aggregate.");
8445 vty_out(vty
, ")\n");
8448 /* If we are not using addpath then we can display Advertised to and
8450 * show what peers we advertised the bestpath to. If we are using
8452 * though then we must display Advertised to on a path-by-path basis. */
8453 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8454 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8455 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8456 if (json
&& !json_adv_to
)
8457 json_adv_to
= json_object_new_object();
8459 route_vty_out_advertised_to(
8461 " Advertised to non peer-group peers:\n ",
8468 json_object_object_add(json
, "advertisedTo",
8473 vty_out(vty
, " Not advertised to any peer");
8479 /* Display specified route of BGP table. */
8480 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8481 struct bgp_table
*rib
, const char *ip_str
,
8482 afi_t afi
, safi_t safi
,
8483 struct prefix_rd
*prd
, int prefix_check
,
8484 enum bgp_path_type pathtype
, u_char use_json
)
8489 struct prefix match
;
8490 struct bgp_node
*rn
;
8491 struct bgp_node
*rm
;
8492 struct bgp_info
*ri
;
8493 struct bgp_table
*table
;
8494 json_object
*json
= NULL
;
8495 json_object
*json_paths
= NULL
;
8497 /* Check IP address argument. */
8498 ret
= str2prefix(ip_str
, &match
);
8500 vty_out(vty
, "address is malformed\n");
8504 match
.family
= afi2family(afi
);
8507 json
= json_object_new_object();
8508 json_paths
= json_object_new_array();
8511 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8512 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8513 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8516 if ((table
= rn
->info
) != NULL
) {
8519 if ((rm
= bgp_node_match(table
, &match
))
8523 != match
.prefixlen
) {
8524 bgp_unlock_node(rm
);
8528 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8530 route_vty_out_detail_header(
8541 if (pathtype
== BGP_PATH_ALL
8543 == BGP_PATH_BESTPATH
8548 == BGP_PATH_MULTIPATH
8554 BGP_INFO_SELECTED
))))
8555 route_vty_out_detail(
8562 bgp_unlock_node(rm
);
8569 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8571 || rn
->p
.prefixlen
== match
.prefixlen
) {
8572 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8574 route_vty_out_detail_header(
8575 vty
, bgp
, rn
, NULL
, afi
,
8581 if (pathtype
== BGP_PATH_ALL
8582 || (pathtype
== BGP_PATH_BESTPATH
8586 || (pathtype
== BGP_PATH_MULTIPATH
8592 BGP_INFO_SELECTED
))))
8593 route_vty_out_detail(
8594 vty
, bgp
, &rn
->p
, ri
,
8595 afi
, safi
, json_paths
);
8599 bgp_unlock_node(rn
);
8605 json_object_object_add(json
, "paths", json_paths
);
8607 vty_out(vty
, "%s\n",
8608 json_object_to_json_string_ext(
8609 json
, JSON_C_TO_STRING_PRETTY
));
8610 json_object_free(json
);
8613 vty_out(vty
, "%% Network not in table\n");
8621 /* Display specified route of Main RIB */
8622 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8623 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8624 int prefix_check
, enum bgp_path_type pathtype
,
8628 bgp
= bgp_get_default();
8630 /* labeled-unicast routes live in the unicast table */
8631 if (safi
== SAFI_LABELED_UNICAST
)
8632 safi
= SAFI_UNICAST
;
8634 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8635 afi
, safi
, prd
, prefix_check
, pathtype
,
8639 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8640 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8643 struct lcommunity
*lcom
;
8649 b
= buffer_new(1024);
8650 for (i
= 0; i
< argc
; i
++) {
8652 buffer_putc(b
, ' ');
8654 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8656 buffer_putstr(b
, argv
[i
]->arg
);
8660 buffer_putc(b
, '\0');
8662 str
= buffer_getstr(b
);
8665 lcom
= lcommunity_str2com(str
);
8666 XFREE(MTYPE_TMP
, str
);
8668 vty_out(vty
, "%% Large-community malformed\n");
8672 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8676 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8677 const char *lcom
, afi_t afi
, safi_t safi
,
8680 struct community_list
*list
;
8682 list
= community_list_lookup(bgp_clist
, lcom
,
8683 LARGE_COMMUNITY_LIST_MASTER
);
8685 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8690 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8694 DEFUN (show_ip_bgp_large_community_list
,
8695 show_ip_bgp_large_community_list_cmd
,
8696 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8700 BGP_INSTANCE_HELP_STR
8702 BGP_SAFI_WITH_LABEL_HELP_STR
8703 "Display routes matching the large-community-list\n"
8704 "large-community-list number\n"
8705 "large-community-list name\n"
8709 afi_t afi
= AFI_IP6
;
8710 safi_t safi
= SAFI_UNICAST
;
8713 if (argv_find(argv
, argc
, "ip", &idx
))
8715 if (argv_find(argv
, argc
, "view", &idx
)
8716 || argv_find(argv
, argc
, "vrf", &idx
))
8717 vrf
= argv
[++idx
]->arg
;
8718 if (argv_find(argv
, argc
, "ipv4", &idx
)
8719 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8720 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8721 if (argv_find(argv
, argc
, "unicast", &idx
)
8722 || argv_find(argv
, argc
, "multicast", &idx
))
8723 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8726 int uj
= use_json(argc
, argv
);
8728 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8730 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8734 argv_find(argv
, argc
, "large-community-list", &idx
);
8735 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8738 DEFUN (show_ip_bgp_large_community
,
8739 show_ip_bgp_large_community_cmd
,
8740 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8744 BGP_INSTANCE_HELP_STR
8746 BGP_SAFI_WITH_LABEL_HELP_STR
8747 "Display routes matching the large-communities\n"
8748 "List of large-community numbers\n"
8752 afi_t afi
= AFI_IP6
;
8753 safi_t safi
= SAFI_UNICAST
;
8756 if (argv_find(argv
, argc
, "ip", &idx
))
8758 if (argv_find(argv
, argc
, "view", &idx
)
8759 || argv_find(argv
, argc
, "vrf", &idx
))
8760 vrf
= argv
[++idx
]->arg
;
8761 if (argv_find(argv
, argc
, "ipv4", &idx
)
8762 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8763 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8764 if (argv_find(argv
, argc
, "unicast", &idx
)
8765 || argv_find(argv
, argc
, "multicast", &idx
))
8766 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8769 int uj
= use_json(argc
, argv
);
8771 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8773 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8777 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8778 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8780 return bgp_show(vty
, bgp
, afi
, safi
,
8781 bgp_show_type_lcommunity_all
, NULL
, uj
);
8784 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8787 /* BGP route print out function. */
8790 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8793 |dampening <flap-statistics|dampened-paths|parameters>\
8798 |community [<AA:NN|local-AS|no-advertise|no-export> [exact-match]]\
8799 |community-list <(1-500)|WORD> [exact-match]\
8800 |A.B.C.D/M longer-prefixes\
8801 |X:X::X:X/M longer-prefixes>\
8806 BGP_INSTANCE_HELP_STR
8808 BGP_SAFI_WITH_LABEL_HELP_STR
8809 "Display only routes with non-natural netmasks\n"
8810 "Display detailed information about dampening\n"
8811 "Display flap statistics of routes\n"
8812 "Display paths suppressed due to dampening\n"
8813 "Display detail of configured dampening parameters\n"
8814 "Display routes matching the route-map\n"
8815 "A route-map to match on\n"
8816 "Display routes conforming to the prefix-list\n"
8817 "Prefix-list name\n"
8818 "Display routes conforming to the filter-list\n"
8819 "Regular expression access list name\n"
8820 "BGP RIB advertisement statistics\n"
8821 "Display routes matching the communities\n"
8823 "Do not send outside local AS (well-known community)\n"
8824 "Do not advertise to any peer (well-known community)\n"
8825 "Do not export to next AS (well-known community)\n"
8826 "Exact match of the communities\n"
8827 "Display routes matching the community-list\n"
8828 "community-list number\n"
8829 "community-list name\n"
8830 "Exact match of the communities\n"
8832 "Display route and more specific routes\n"
8834 "Display route and more specific routes\n"
8837 afi_t afi
= AFI_IP6
;
8838 safi_t safi
= SAFI_UNICAST
;
8839 int exact_match
= 0;
8840 enum bgp_show_type sh_type
= bgp_show_type_normal
;
8841 struct bgp
*bgp
= NULL
;
8844 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8849 int uj
= use_json(argc
, argv
);
8853 if (argv_find(argv
, argc
, "cidr-only", &idx
))
8854 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
8857 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8858 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
8859 return bgp_show(vty
, bgp
, afi
, safi
,
8860 bgp_show_type_dampend_paths
, NULL
, uj
);
8861 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
8862 return bgp_show(vty
, bgp
, afi
, safi
,
8863 bgp_show_type_flap_statistics
, NULL
,
8865 else if (argv_find(argv
, argc
, "parameters", &idx
))
8866 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8869 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8870 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8871 safi
, bgp_show_type_prefix_list
);
8873 if (argv_find(argv
, argc
, "filter-list", &idx
))
8874 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8875 safi
, bgp_show_type_filter_list
);
8877 if (argv_find(argv
, argc
, "statistics", &idx
))
8878 return bgp_table_stats(vty
, bgp
, afi
, safi
);
8880 if (argv_find(argv
, argc
, "route-map", &idx
))
8881 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8882 safi
, bgp_show_type_route_map
);
8884 if (argv_find(argv
, argc
, "community", &idx
)) {
8885 /* show a specific community */
8886 if (argv_find(argv
, argc
, "local-AS", &idx
)
8887 || argv_find(argv
, argc
, "no-advertise", &idx
)
8888 || argv_find(argv
, argc
, "no-export", &idx
)) {
8889 if (argv_find(argv
, argc
, "exact_match", &idx
))
8891 return bgp_show_community(vty
, bgp
, argc
, argv
,
8892 exact_match
, afi
, safi
);
8894 /* show all communities */
8896 return bgp_show(vty
, bgp
, afi
, safi
,
8897 bgp_show_type_community_all
, NULL
, uj
);
8900 if (argv_find(argv
, argc
, "community-list", &idx
)) {
8901 const char *clist_number_or_name
= argv
[++idx
]->arg
;
8902 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
8904 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
8905 exact_match
, afi
, safi
);
8908 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8909 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8910 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
8912 bgp_show_type_prefix_longer
);
8914 if (safi
== SAFI_MPLS_VPN
)
8915 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
8918 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
8921 DEFUN (show_ip_bgp_route
,
8922 show_ip_bgp_route_cmd
,
8923 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
8924 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
8928 BGP_INSTANCE_HELP_STR
8930 BGP_SAFI_WITH_LABEL_HELP_STR
8931 "Network in the BGP routing table to display\n"
8933 "Network in the BGP routing table to display\n"
8935 "Display only the bestpath\n"
8936 "Display only multipaths\n"
8939 int prefix_check
= 0;
8941 afi_t afi
= AFI_IP6
;
8942 safi_t safi
= SAFI_UNICAST
;
8943 char *prefix
= NULL
;
8944 struct bgp
*bgp
= NULL
;
8945 enum bgp_path_type path_type
;
8946 u_char uj
= use_json(argc
, argv
);
8950 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8957 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8961 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8962 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
8963 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
8965 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8966 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8969 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
8970 && afi
!= AFI_IP6
) {
8972 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
8975 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
8978 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
8982 prefix
= argv
[idx
]->arg
;
8984 /* [<bestpath|multipath>] */
8985 if (argv_find(argv
, argc
, "bestpath", &idx
))
8986 path_type
= BGP_PATH_BESTPATH
;
8987 else if (argv_find(argv
, argc
, "multipath", &idx
))
8988 path_type
= BGP_PATH_MULTIPATH
;
8990 path_type
= BGP_PATH_ALL
;
8992 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
8996 DEFUN (show_ip_bgp_regexp
,
8997 show_ip_bgp_regexp_cmd
,
8998 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9002 BGP_INSTANCE_HELP_STR
9004 BGP_SAFI_WITH_LABEL_HELP_STR
9005 "Display routes matching the AS path regular expression\n"
9006 "A regular-expression to match the BGP AS paths\n")
9008 afi_t afi
= AFI_IP6
;
9009 safi_t safi
= SAFI_UNICAST
;
9010 struct bgp
*bgp
= NULL
;
9013 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9018 // get index of regex
9019 argv_find(argv
, argc
, "regexp", &idx
);
9022 char *regstr
= argv_concat(argv
, argc
, idx
);
9023 int rc
= bgp_show_regexp(vty
, (const char *)regstr
, afi
, safi
,
9024 bgp_show_type_regexp
);
9025 XFREE(MTYPE_TMP
, regstr
);
9029 DEFUN (show_ip_bgp_instance_all
,
9030 show_ip_bgp_instance_all_cmd
,
9031 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9035 BGP_INSTANCE_ALL_HELP_STR
9037 BGP_SAFI_WITH_LABEL_HELP_STR
9041 safi_t safi
= SAFI_UNICAST
;
9042 struct bgp
*bgp
= NULL
;
9045 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9050 int uj
= use_json(argc
, argv
);
9054 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9058 static int bgp_show_regexp(struct vty
*vty
, const char *regstr
, afi_t afi
,
9059 safi_t safi
, enum bgp_show_type type
)
9064 regex
= bgp_regcomp(regstr
);
9066 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9070 rc
= bgp_show(vty
, NULL
, afi
, safi
, type
, regex
, 0);
9071 bgp_regex_free(regex
);
9075 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9076 const char *prefix_list_str
, afi_t afi
,
9077 safi_t safi
, enum bgp_show_type type
)
9079 struct prefix_list
*plist
;
9081 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9082 if (plist
== NULL
) {
9083 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9088 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9091 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9092 const char *filter
, afi_t afi
, safi_t safi
,
9093 enum bgp_show_type type
)
9095 struct as_list
*as_list
;
9097 as_list
= as_list_lookup(filter
);
9098 if (as_list
== NULL
) {
9099 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9104 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9107 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9108 const char *rmap_str
, afi_t afi
, safi_t safi
,
9109 enum bgp_show_type type
)
9111 struct route_map
*rmap
;
9113 rmap
= route_map_lookup_by_name(rmap_str
);
9115 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9119 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9122 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9123 struct cmd_token
**argv
, int exact
, afi_t afi
,
9126 struct community
*com
;
9133 b
= buffer_new(1024);
9134 for (i
= 0; i
< argc
; i
++) {
9136 buffer_putc(b
, ' ');
9138 if (strmatch(argv
[i
]->text
, "unicast")
9139 || strmatch(argv
[i
]->text
, "multicast"))
9144 buffer_putstr(b
, argv
[i
]->arg
);
9146 buffer_putc(b
, '\0');
9148 str
= buffer_getstr(b
);
9151 com
= community_str2com(str
);
9152 XFREE(MTYPE_TMP
, str
);
9154 vty_out(vty
, "%% Community malformed: \n");
9158 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9159 (exact
? bgp_show_type_community_exact
9160 : bgp_show_type_community
),
9162 community_free(com
);
9167 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9168 const char *com
, int exact
, afi_t afi
,
9171 struct community_list
*list
;
9173 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9175 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9179 return bgp_show(vty
, bgp
, afi
, safi
,
9180 (exact
? bgp_show_type_community_list_exact
9181 : bgp_show_type_community_list
),
9185 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9186 const char *prefix
, afi_t afi
, safi_t safi
,
9187 enum bgp_show_type type
)
9194 ret
= str2prefix(prefix
, p
);
9196 vty_out(vty
, "%% Malformed Prefix\n");
9200 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9205 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9206 const char *ip_str
, u_char use_json
)
9212 /* Get peer sockunion. */
9213 ret
= str2sockunion(ip_str
, &su
);
9215 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9217 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9221 json_object
*json_no
= NULL
;
9222 json_no
= json_object_new_object();
9223 json_object_string_add(
9225 "malformedAddressOrName",
9227 vty_out(vty
, "%s\n",
9228 json_object_to_json_string(
9230 json_object_free(json_no
);
9233 "%% Malformed address or name: %s\n",
9241 /* Peer structure lookup. */
9242 peer
= peer_lookup(bgp
, &su
);
9245 json_object
*json_no
= NULL
;
9246 json_no
= json_object_new_object();
9247 json_object_string_add(json_no
, "warning",
9248 "No such neighbor");
9249 vty_out(vty
, "%s\n",
9250 json_object_to_json_string(json_no
));
9251 json_object_free(json_no
);
9253 vty_out(vty
, "No such neighbor\n");
9261 BGP_STATS_MAXBITLEN
= 0,
9265 BGP_STATS_UNAGGREGATEABLE
,
9266 BGP_STATS_MAX_AGGREGATEABLE
,
9267 BGP_STATS_AGGREGATES
,
9269 BGP_STATS_ASPATH_COUNT
,
9270 BGP_STATS_ASPATH_MAXHOPS
,
9271 BGP_STATS_ASPATH_TOTHOPS
,
9272 BGP_STATS_ASPATH_MAXSIZE
,
9273 BGP_STATS_ASPATH_TOTSIZE
,
9274 BGP_STATS_ASN_HIGHEST
,
9278 static const char *table_stats_strs
[] = {
9279 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9280 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9281 [BGP_STATS_RIB
] = "Total Advertisements",
9282 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9283 [BGP_STATS_MAX_AGGREGATEABLE
] = "Maximum aggregateable prefixes",
9284 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9285 [BGP_STATS_SPACE
] = "Address space advertised",
9286 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9287 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9288 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9289 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9290 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9291 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9292 [BGP_STATS_MAX
] = NULL
,
9295 struct bgp_table_stats
{
9296 struct bgp_table
*table
;
9297 unsigned long long counts
[BGP_STATS_MAX
];
9301 #define TALLY_SIGFIG 100000
9302 static unsigned long
9303 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9305 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9306 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9307 unsigned long ret
= newtot
/ count
;
9309 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9316 static int bgp_table_stats_walker(struct thread
*t
)
9318 struct bgp_node
*rn
;
9319 struct bgp_node
*top
;
9320 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9321 unsigned int space
= 0;
9323 if (!(top
= bgp_table_top(ts
->table
)))
9326 switch (top
->p
.family
) {
9328 space
= IPV4_MAX_BITLEN
;
9331 space
= IPV6_MAX_BITLEN
;
9335 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9337 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9338 struct bgp_info
*ri
;
9339 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9340 unsigned int rinum
= 0;
9348 ts
->counts
[BGP_STATS_PREFIXES
]++;
9349 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9352 ts
->counts
[BGP_STATS_AVGPLEN
]
9353 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9354 ts
->counts
[BGP_STATS_AVGPLEN
],
9358 /* check if the prefix is included by any other announcements */
9359 while (prn
&& !prn
->info
)
9360 prn
= bgp_node_parent_nolock(prn
);
9362 if (prn
== NULL
|| prn
== top
) {
9363 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9364 /* announced address space */
9366 ts
->counts
[BGP_STATS_SPACE
] +=
9367 1 << (space
- rn
->p
.prefixlen
);
9368 } else if (prn
->info
)
9369 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9371 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9373 ts
->counts
[BGP_STATS_RIB
]++;
9376 && (CHECK_FLAG(ri
->attr
->flag
,
9378 BGP_ATTR_ATOMIC_AGGREGATE
))))
9379 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9382 if (ri
->attr
&& ri
->attr
->aspath
) {
9384 aspath_count_hops(ri
->attr
->aspath
);
9386 aspath_size(ri
->attr
->aspath
);
9387 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9389 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9391 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9392 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9395 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9396 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9399 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9400 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9402 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9403 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9404 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9406 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9407 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9408 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9411 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9412 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9420 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9423 struct bgp_table_stats ts
;
9426 if (!bgp
->rib
[afi
][safi
]) {
9427 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9432 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9434 /* labeled-unicast routes live in the unicast table */
9435 if (safi
== SAFI_LABELED_UNICAST
)
9436 safi
= SAFI_UNICAST
;
9438 memset(&ts
, 0, sizeof(ts
));
9439 ts
.table
= bgp
->rib
[afi
][safi
];
9440 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9442 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9443 if (!table_stats_strs
[i
])
9448 case BGP_STATS_ASPATH_AVGHOPS
:
9449 case BGP_STATS_ASPATH_AVGSIZE
:
9450 case BGP_STATS_AVGPLEN
:
9451 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9452 vty_out (vty
, "%12.2f",
9453 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9456 case BGP_STATS_ASPATH_TOTHOPS
:
9457 case BGP_STATS_ASPATH_TOTSIZE
:
9458 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9459 vty_out(vty
, "%12.2f",
9461 ? (float)ts
.counts
[i
]
9463 [BGP_STATS_ASPATH_COUNT
]
9466 case BGP_STATS_TOTPLEN
:
9467 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9468 vty_out(vty
, "%12.2f",
9470 ? (float)ts
.counts
[i
]
9472 [BGP_STATS_PREFIXES
]
9475 case BGP_STATS_SPACE
:
9476 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9477 vty_out(vty
, "%12llu\n", ts
.counts
[i
]);
9478 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 9)
9480 vty_out(vty
, "%30s: ", "%% announced ");
9481 vty_out(vty
, "%12.2f\n",
9482 100 * (float)ts
.counts
[BGP_STATS_SPACE
]
9483 / (float)((uint64_t)1UL
9485 [BGP_STATS_MAXBITLEN
]));
9486 vty_out(vty
, "%30s: ", "/8 equivalent ");
9487 vty_out(vty
, "%12.2f\n",
9488 (float)ts
.counts
[BGP_STATS_SPACE
]
9491 [BGP_STATS_MAXBITLEN
]
9493 if (ts
.counts
[BGP_STATS_MAXBITLEN
] < 25)
9495 vty_out(vty
, "%30s: ", "/24 equivalent ");
9496 vty_out(vty
, "%12.2f",
9497 (float)ts
.counts
[BGP_STATS_SPACE
]
9500 [BGP_STATS_MAXBITLEN
]
9504 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9505 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9522 PCOUNT_PFCNT
, /* the figure we display to users */
9526 static const char *pcount_strs
[] = {
9527 [PCOUNT_ADJ_IN
] = "Adj-in", [PCOUNT_DAMPED
] = "Damped",
9528 [PCOUNT_REMOVED
] = "Removed", [PCOUNT_HISTORY
] = "History",
9529 [PCOUNT_STALE
] = "Stale", [PCOUNT_VALID
] = "Valid",
9530 [PCOUNT_ALL
] = "All RIB", [PCOUNT_COUNTED
] = "PfxCt counted",
9531 [PCOUNT_PFCNT
] = "Useable", [PCOUNT_MAX
] = NULL
,
9534 struct peer_pcounts
{
9535 unsigned int count
[PCOUNT_MAX
];
9536 const struct peer
*peer
;
9537 const struct bgp_table
*table
;
9540 static int bgp_peer_count_walker(struct thread
*t
)
9542 struct bgp_node
*rn
;
9543 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9544 const struct peer
*peer
= pc
->peer
;
9546 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9547 struct bgp_adj_in
*ain
;
9548 struct bgp_info
*ri
;
9550 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9551 if (ain
->peer
== peer
)
9552 pc
->count
[PCOUNT_ADJ_IN
]++;
9554 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9555 char buf
[SU_ADDRSTRLEN
];
9557 if (ri
->peer
!= peer
)
9560 pc
->count
[PCOUNT_ALL
]++;
9562 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9563 pc
->count
[PCOUNT_DAMPED
]++;
9564 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9565 pc
->count
[PCOUNT_HISTORY
]++;
9566 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9567 pc
->count
[PCOUNT_REMOVED
]++;
9568 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9569 pc
->count
[PCOUNT_STALE
]++;
9570 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9571 pc
->count
[PCOUNT_VALID
]++;
9572 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9573 pc
->count
[PCOUNT_PFCNT
]++;
9575 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9576 pc
->count
[PCOUNT_COUNTED
]++;
9577 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9579 "%s [pcount] %s/%d is counted but flags 0x%x",
9581 inet_ntop(rn
->p
.family
,
9582 &rn
->p
.u
.prefix
, buf
,
9584 rn
->p
.prefixlen
, ri
->flags
);
9586 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9588 "%s [pcount] %s/%d not counted but flags 0x%x",
9590 inet_ntop(rn
->p
.family
,
9591 &rn
->p
.u
.prefix
, buf
,
9593 rn
->p
.prefixlen
, ri
->flags
);
9600 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9601 safi_t safi
, u_char use_json
)
9603 struct peer_pcounts pcounts
= {.peer
= peer
};
9605 json_object
*json
= NULL
;
9606 json_object
*json_loop
= NULL
;
9609 json
= json_object_new_object();
9610 json_loop
= json_object_new_object();
9613 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9614 || !peer
->bgp
->rib
[afi
][safi
]) {
9616 json_object_string_add(
9618 "No such neighbor or address family");
9619 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9620 json_object_free(json
);
9622 vty_out(vty
, "%% No such neighbor or address family\n");
9627 memset(&pcounts
, 0, sizeof(pcounts
));
9628 pcounts
.peer
= peer
;
9629 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9631 /* in-place call via thread subsystem so as to record execution time
9632 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9633 * * on just vty_read()).
9635 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9638 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9639 json_object_string_add(json
, "multiProtocol",
9640 afi_safi_print(afi
, safi
));
9641 json_object_int_add(json
, "pfxCounter",
9642 peer
->pcount
[afi
][safi
]);
9644 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9645 json_object_int_add(json_loop
, pcount_strs
[i
],
9648 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9650 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9651 json_object_string_add(json
, "pfxctDriftFor",
9653 json_object_string_add(
9654 json
, "recommended",
9655 "Please report this bug, with the above command output");
9657 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9658 json_object_free(json
);
9662 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9663 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9664 peer
->hostname
, peer
->host
,
9665 afi_safi_print(afi
, safi
));
9667 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9668 afi_safi_print(afi
, safi
));
9671 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9672 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9674 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9675 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9678 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9679 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9681 "Please report this bug, with the above command output\n");
9688 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9689 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9690 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9691 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9695 BGP_INSTANCE_HELP_STR
9698 "Detailed information on TCP and BGP neighbor connections\n"
9699 "Neighbor to display information about\n"
9700 "Neighbor to display information about\n"
9701 "Neighbor on BGP configured interface\n"
9702 "Display detailed prefix count information\n"
9705 afi_t afi
= AFI_IP6
;
9706 safi_t safi
= SAFI_UNICAST
;
9709 struct bgp
*bgp
= NULL
;
9711 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9716 int uj
= use_json(argc
, argv
);
9720 argv_find(argv
, argc
, "neighbors", &idx
);
9721 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9725 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9728 #ifdef KEEP_OLD_VPN_COMMANDS
9729 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9730 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9731 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9736 "Display information about all VPNv4 NLRIs\n"
9737 "Detailed information on TCP and BGP neighbor connections\n"
9738 "Neighbor to display information about\n"
9739 "Neighbor to display information about\n"
9740 "Neighbor on BGP configured interface\n"
9741 "Display detailed prefix count information\n"
9746 u_char uj
= use_json(argc
, argv
);
9748 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9752 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9755 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9756 show_ip_bgp_vpn_all_route_prefix_cmd
,
9757 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9762 "Display information about all VPNv4 NLRIs\n"
9763 "Network in the BGP routing table to display\n"
9764 "Network in the BGP routing table to display\n"
9768 char *network
= NULL
;
9769 struct bgp
*bgp
= bgp_get_default();
9771 vty_out(vty
, "Can't find default instance\n");
9775 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9776 network
= argv
[idx
]->arg
;
9777 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9778 network
= argv
[idx
]->arg
;
9780 vty_out(vty
, "Unable to figure out Network\n");
9784 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9785 BGP_PATH_ALL
, use_json(argc
, argv
));
9787 #endif /* KEEP_OLD_VPN_COMMANDS */
9789 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9790 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9791 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9797 "Display information about all EVPN NLRIs\n"
9798 "Network in the BGP routing table to display\n"
9799 "Network in the BGP routing table to display\n"
9803 char *network
= NULL
;
9805 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9806 network
= argv
[idx
]->arg
;
9807 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9808 network
= argv
[idx
]->arg
;
9810 vty_out(vty
, "Unable to figure out Network\n");
9813 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9814 BGP_PATH_ALL
, use_json(argc
, argv
));
9817 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9818 safi_t safi
, int in
, const char *rmap_name
,
9819 u_char use_json
, json_object
*json
)
9821 struct bgp_table
*table
;
9822 struct bgp_adj_in
*ain
;
9823 struct bgp_adj_out
*adj
;
9824 unsigned long output_count
;
9825 unsigned long filtered_count
;
9826 struct bgp_node
*rn
;
9832 struct update_subgroup
*subgrp
;
9833 json_object
*json_scode
= NULL
;
9834 json_object
*json_ocode
= NULL
;
9835 json_object
*json_ar
= NULL
;
9836 struct peer_af
*paf
;
9839 json_scode
= json_object_new_object();
9840 json_ocode
= json_object_new_object();
9841 json_ar
= json_object_new_object();
9843 json_object_string_add(json_scode
, "suppressed", "s");
9844 json_object_string_add(json_scode
, "damped", "d");
9845 json_object_string_add(json_scode
, "history", "h");
9846 json_object_string_add(json_scode
, "valid", "*");
9847 json_object_string_add(json_scode
, "best", ">");
9848 json_object_string_add(json_scode
, "multipath", "=");
9849 json_object_string_add(json_scode
, "internal", "i");
9850 json_object_string_add(json_scode
, "ribFailure", "r");
9851 json_object_string_add(json_scode
, "stale", "S");
9852 json_object_string_add(json_scode
, "removed", "R");
9854 json_object_string_add(json_ocode
, "igp", "i");
9855 json_object_string_add(json_ocode
, "egp", "e");
9856 json_object_string_add(json_ocode
, "incomplete", "?");
9863 json_object_string_add(json
, "alert", "no BGP");
9864 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9865 json_object_free(json
);
9867 vty_out(vty
, "%% No bgp\n");
9871 table
= bgp
->rib
[afi
][safi
];
9873 output_count
= filtered_count
= 0;
9874 subgrp
= peer_subgroup(peer
, afi
, safi
);
9877 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
9879 json_object_int_add(json
, "bgpTableVersion",
9881 json_object_string_add(json
, "bgpLocalRouterId",
9882 inet_ntoa(bgp
->router_id
));
9883 json_object_object_add(json
, "bgpStatusCodes",
9885 json_object_object_add(json
, "bgpOriginCodes",
9887 json_object_string_add(json
,
9888 "bgpOriginatingDefaultNetwork",
9892 "BGP table version is %" PRIu64
9893 ", local router ID is %s\n",
9894 table
->version
, inet_ntoa(bgp
->router_id
));
9895 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9896 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9898 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
9903 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9905 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
9906 if (ain
->peer
== peer
) {
9909 json_object_int_add(
9913 json_object_string_add(
9918 json_object_object_add(
9922 json_object_object_add(
9928 "BGP table version is 0, local router ID is %s\n",
9932 BGP_SHOW_SCODE_HEADER
);
9934 BGP_SHOW_OCODE_HEADER
);
9945 bgp_attr_dup(&attr
, ain
->attr
);
9946 if (bgp_input_modifier(
9947 peer
, &rn
->p
, &attr
,
9963 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
9964 SUBGRP_FOREACH_PEER(adj
->subgroup
, paf
)
9965 if (paf
->peer
== peer
) {
9968 json_object_int_add(
9969 json
, "bgpTableVersion",
9971 json_object_string_add(
9976 json_object_object_add(
9977 json
, "bgpStatusCodes",
9979 json_object_object_add(
9980 json
, "bgpOriginCodes",
9984 "BGP table version is %" PRIu64
9985 ", local router ID is %s\n",
9990 BGP_SHOW_SCODE_HEADER
);
9992 BGP_SHOW_OCODE_HEADER
);
9999 vty_out(vty
, BGP_SHOW_HEADER
);
10004 bgp_attr_dup(&attr
, adj
->attr
);
10005 ret
= bgp_output_modifier(
10006 peer
, &rn
->p
, &attr
, afi
, safi
,
10008 if (ret
!= RMAP_DENY
) {
10009 route_vty_out_tmp(vty
, &rn
->p
,
10021 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10023 if (output_count
!= 0) {
10025 json_object_int_add(json
, "totalPrefixCounter",
10028 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10032 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10033 json_object_free(json
);
10037 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10038 safi_t safi
, int in
, const char *rmap_name
,
10041 json_object
*json
= NULL
;
10044 json
= json_object_new_object();
10046 /* labeled-unicast routes live in the unicast table */
10047 if (safi
== SAFI_LABELED_UNICAST
)
10048 safi
= SAFI_UNICAST
;
10050 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10052 json_object_string_add(
10054 "No such neighbor or address family");
10055 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10056 json_object_free(json
);
10058 vty_out(vty
, "%% No such neighbor or address family\n");
10060 return CMD_WARNING
;
10064 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10065 PEER_FLAG_SOFT_RECONFIG
)) {
10067 json_object_string_add(
10069 "Inbound soft reconfiguration not enabled");
10070 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10071 json_object_free(json
);
10074 "%% Inbound soft reconfiguration not enabled\n");
10076 return CMD_WARNING
;
10079 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10081 return CMD_SUCCESS
;
10084 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10085 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10086 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10087 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10091 BGP_INSTANCE_HELP_STR
10093 BGP_SAFI_WITH_LABEL_HELP_STR
10094 "Detailed information on TCP and BGP neighbor connections\n"
10095 "Neighbor to display information about\n"
10096 "Neighbor to display information about\n"
10097 "Neighbor on BGP configured interface\n"
10098 "Display the received routes from neighbor\n"
10099 "Display the routes advertised to a BGP neighbor\n"
10100 "Route-map to modify the attributes\n"
10101 "Name of the route map\n"
10104 afi_t afi
= AFI_IP6
;
10105 safi_t safi
= SAFI_UNICAST
;
10106 char *rmap_name
= NULL
;
10107 char *peerstr
= NULL
;
10109 struct bgp
*bgp
= NULL
;
10114 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10117 return CMD_WARNING
;
10119 int uj
= use_json(argc
, argv
);
10123 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10124 argv_find(argv
, argc
, "neighbors", &idx
);
10125 peerstr
= argv
[++idx
]->arg
;
10127 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10129 return CMD_WARNING
;
10131 if (argv_find(argv
, argc
, "received-routes", &idx
))
10133 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10135 if (argv_find(argv
, argc
, "route-map", &idx
))
10136 rmap_name
= argv
[++idx
]->arg
;
10138 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10141 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10142 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10143 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10149 "Address Family modifier\n"
10150 "Detailed information on TCP and BGP neighbor connections\n"
10151 "Neighbor to display information about\n"
10152 "Neighbor to display information about\n"
10153 "Neighbor on BGP configured interface\n"
10154 "Display information received from a BGP neighbor\n"
10155 "Display the prefixlist filter\n"
10158 afi_t afi
= AFI_IP6
;
10159 safi_t safi
= SAFI_UNICAST
;
10160 char *peerstr
= NULL
;
10163 union sockunion su
;
10169 /* show [ip] bgp */
10170 if (argv_find(argv
, argc
, "ip", &idx
))
10172 /* [<ipv4|ipv6> [unicast]] */
10173 if (argv_find(argv
, argc
, "ipv4", &idx
))
10175 if (argv_find(argv
, argc
, "ipv6", &idx
))
10177 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10178 argv_find(argv
, argc
, "neighbors", &idx
);
10179 peerstr
= argv
[++idx
]->arg
;
10181 u_char uj
= use_json(argc
, argv
);
10183 ret
= str2sockunion(peerstr
, &su
);
10185 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10188 vty_out(vty
, "{}\n");
10191 "%% Malformed address or name: %s\n",
10193 return CMD_WARNING
;
10196 peer
= peer_lookup(NULL
, &su
);
10199 vty_out(vty
, "{}\n");
10201 vty_out(vty
, "No peer\n");
10202 return CMD_WARNING
;
10206 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10207 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10210 vty_out(vty
, "Address Family: %s\n",
10211 afi_safi_print(afi
, safi
));
10212 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10215 vty_out(vty
, "{}\n");
10217 vty_out(vty
, "No functional output\n");
10220 return CMD_SUCCESS
;
10223 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10224 afi_t afi
, safi_t safi
,
10225 enum bgp_show_type type
, u_char use_json
)
10227 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10229 json_object
*json_no
= NULL
;
10230 json_no
= json_object_new_object();
10231 json_object_string_add(
10232 json_no
, "warning",
10233 "No such neighbor or address family");
10234 vty_out(vty
, "%s\n",
10235 json_object_to_json_string(json_no
));
10236 json_object_free(json_no
);
10238 vty_out(vty
, "%% No such neighbor or address family\n");
10239 return CMD_WARNING
;
10242 /* labeled-unicast routes live in the unicast table */
10243 if (safi
== SAFI_LABELED_UNICAST
)
10244 safi
= SAFI_UNICAST
;
10246 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10249 DEFUN (show_ip_bgp_neighbor_routes
,
10250 show_ip_bgp_neighbor_routes_cmd
,
10251 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10252 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10256 BGP_INSTANCE_HELP_STR
10258 BGP_SAFI_WITH_LABEL_HELP_STR
10259 "Detailed information on TCP and BGP neighbor connections\n"
10260 "Neighbor to display information about\n"
10261 "Neighbor to display information about\n"
10262 "Neighbor on BGP configured interface\n"
10263 "Display flap statistics of the routes learned from neighbor\n"
10264 "Display the dampened routes received from neighbor\n"
10265 "Display routes learned from neighbor\n"
10268 char *peerstr
= NULL
;
10269 struct bgp
*bgp
= NULL
;
10270 afi_t afi
= AFI_IP6
;
10271 safi_t safi
= SAFI_UNICAST
;
10273 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10277 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10280 return CMD_WARNING
;
10282 int uj
= use_json(argc
, argv
);
10286 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10287 argv_find(argv
, argc
, "neighbors", &idx
);
10288 peerstr
= argv
[++idx
]->arg
;
10290 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10292 vty_out(vty
, "No such neighbor\n");
10293 return CMD_WARNING
;
10296 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10297 sh_type
= bgp_show_type_flap_neighbor
;
10298 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10299 sh_type
= bgp_show_type_damp_neighbor
;
10300 else if (argv_find(argv
, argc
, "routes", &idx
))
10301 sh_type
= bgp_show_type_neighbor
;
10303 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10306 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10308 struct bgp_distance
{
10309 /* Distance value for the IP source prefix. */
10312 /* Name of the access-list to be matched. */
10316 DEFUN (show_bgp_afi_vpn_rd_route
,
10317 show_bgp_afi_vpn_rd_route_cmd
,
10318 "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]",
10322 "Address Family modifier\n"
10323 "Display information for a route distinguisher\n"
10324 "Route Distinguisher\n"
10325 "Network in the BGP routing table to display\n"
10326 "Network in the BGP routing table to display\n"
10330 struct prefix_rd prd
;
10331 afi_t afi
= AFI_MAX
;
10334 argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
);
10335 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10337 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10338 return CMD_WARNING
;
10340 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10341 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10344 static struct bgp_distance
*bgp_distance_new(void)
10346 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10349 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10351 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10354 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10355 const char *ip_str
, const char *access_list_str
)
10362 struct bgp_node
*rn
;
10363 struct bgp_distance
*bdistance
;
10365 afi
= bgp_node_afi(vty
);
10366 safi
= bgp_node_safi(vty
);
10368 ret
= str2prefix(ip_str
, &p
);
10370 vty_out(vty
, "Malformed prefix\n");
10371 return CMD_WARNING_CONFIG_FAILED
;
10374 distance
= atoi(distance_str
);
10376 /* Get BGP distance node. */
10377 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10379 bdistance
= rn
->info
;
10380 bgp_unlock_node(rn
);
10382 bdistance
= bgp_distance_new();
10383 rn
->info
= bdistance
;
10386 /* Set distance value. */
10387 bdistance
->distance
= distance
;
10389 /* Reset access-list configuration. */
10390 if (bdistance
->access_list
) {
10391 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10392 bdistance
->access_list
= NULL
;
10394 if (access_list_str
)
10395 bdistance
->access_list
=
10396 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10398 return CMD_SUCCESS
;
10401 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10402 const char *ip_str
, const char *access_list_str
)
10409 struct bgp_node
*rn
;
10410 struct bgp_distance
*bdistance
;
10412 afi
= bgp_node_afi(vty
);
10413 safi
= bgp_node_safi(vty
);
10415 ret
= str2prefix(ip_str
, &p
);
10417 vty_out(vty
, "Malformed prefix\n");
10418 return CMD_WARNING_CONFIG_FAILED
;
10421 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10422 (struct prefix
*)&p
);
10424 vty_out(vty
, "Can't find specified prefix\n");
10425 return CMD_WARNING_CONFIG_FAILED
;
10428 bdistance
= rn
->info
;
10429 distance
= atoi(distance_str
);
10431 if (bdistance
->distance
!= distance
) {
10432 vty_out(vty
, "Distance does not match configured\n");
10433 return CMD_WARNING_CONFIG_FAILED
;
10436 if (bdistance
->access_list
)
10437 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10438 bgp_distance_free(bdistance
);
10441 bgp_unlock_node(rn
);
10442 bgp_unlock_node(rn
);
10444 return CMD_SUCCESS
;
10447 /* Apply BGP information to distance method. */
10448 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10449 safi_t safi
, struct bgp
*bgp
)
10451 struct bgp_node
*rn
;
10454 struct bgp_distance
*bdistance
;
10455 struct access_list
*alist
;
10456 struct bgp_static
*bgp_static
;
10461 peer
= rinfo
->peer
;
10463 /* Check source address. */
10464 sockunion2hostprefix(&peer
->su
, &q
);
10465 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10467 bdistance
= rn
->info
;
10468 bgp_unlock_node(rn
);
10470 if (bdistance
->access_list
) {
10471 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10473 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10474 return bdistance
->distance
;
10476 return bdistance
->distance
;
10479 /* Backdoor check. */
10480 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10482 bgp_static
= rn
->info
;
10483 bgp_unlock_node(rn
);
10485 if (bgp_static
->backdoor
) {
10486 if (bgp
->distance_local
[afi
][safi
])
10487 return bgp
->distance_local
[afi
][safi
];
10489 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10493 if (peer
->sort
== BGP_PEER_EBGP
) {
10494 if (bgp
->distance_ebgp
[afi
][safi
])
10495 return bgp
->distance_ebgp
[afi
][safi
];
10496 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10498 if (bgp
->distance_ibgp
[afi
][safi
])
10499 return bgp
->distance_ibgp
[afi
][safi
];
10500 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10504 DEFUN (bgp_distance
,
10506 "distance bgp (1-255) (1-255) (1-255)",
10507 "Define an administrative distance\n"
10509 "Distance for routes external to the AS\n"
10510 "Distance for routes internal to the AS\n"
10511 "Distance for local routes\n")
10513 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10514 int idx_number
= 2;
10515 int idx_number_2
= 3;
10516 int idx_number_3
= 4;
10520 afi
= bgp_node_afi(vty
);
10521 safi
= bgp_node_safi(vty
);
10523 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10524 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10525 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10526 return CMD_SUCCESS
;
10529 DEFUN (no_bgp_distance
,
10530 no_bgp_distance_cmd
,
10531 "no distance bgp [(1-255) (1-255) (1-255)]",
10533 "Define an administrative distance\n"
10535 "Distance for routes external to the AS\n"
10536 "Distance for routes internal to the AS\n"
10537 "Distance for local routes\n")
10539 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10543 afi
= bgp_node_afi(vty
);
10544 safi
= bgp_node_safi(vty
);
10546 bgp
->distance_ebgp
[afi
][safi
] = 0;
10547 bgp
->distance_ibgp
[afi
][safi
] = 0;
10548 bgp
->distance_local
[afi
][safi
] = 0;
10549 return CMD_SUCCESS
;
10553 DEFUN (bgp_distance_source
,
10554 bgp_distance_source_cmd
,
10555 "distance (1-255) A.B.C.D/M",
10556 "Define an administrative distance\n"
10557 "Administrative distance\n"
10558 "IP source prefix\n")
10560 int idx_number
= 1;
10561 int idx_ipv4_prefixlen
= 2;
10562 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10563 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10564 return CMD_SUCCESS
;
10567 DEFUN (no_bgp_distance_source
,
10568 no_bgp_distance_source_cmd
,
10569 "no distance (1-255) A.B.C.D/M",
10571 "Define an administrative distance\n"
10572 "Administrative distance\n"
10573 "IP source prefix\n")
10575 int idx_number
= 2;
10576 int idx_ipv4_prefixlen
= 3;
10577 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10578 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10579 return CMD_SUCCESS
;
10582 DEFUN (bgp_distance_source_access_list
,
10583 bgp_distance_source_access_list_cmd
,
10584 "distance (1-255) A.B.C.D/M WORD",
10585 "Define an administrative distance\n"
10586 "Administrative distance\n"
10587 "IP source prefix\n"
10588 "Access list name\n")
10590 int idx_number
= 1;
10591 int idx_ipv4_prefixlen
= 2;
10593 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10594 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10595 return CMD_SUCCESS
;
10598 DEFUN (no_bgp_distance_source_access_list
,
10599 no_bgp_distance_source_access_list_cmd
,
10600 "no distance (1-255) A.B.C.D/M WORD",
10602 "Define an administrative distance\n"
10603 "Administrative distance\n"
10604 "IP source prefix\n"
10605 "Access list name\n")
10607 int idx_number
= 2;
10608 int idx_ipv4_prefixlen
= 3;
10610 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10611 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10612 return CMD_SUCCESS
;
10615 DEFUN (ipv6_bgp_distance_source
,
10616 ipv6_bgp_distance_source_cmd
,
10617 "distance (1-255) X:X::X:X/M",
10618 "Define an administrative distance\n"
10619 "Administrative distance\n"
10620 "IP source prefix\n")
10622 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10623 return CMD_SUCCESS
;
10626 DEFUN (no_ipv6_bgp_distance_source
,
10627 no_ipv6_bgp_distance_source_cmd
,
10628 "no distance (1-255) X:X::X:X/M",
10630 "Define an administrative distance\n"
10631 "Administrative distance\n"
10632 "IP source prefix\n")
10634 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10635 return CMD_SUCCESS
;
10638 DEFUN (ipv6_bgp_distance_source_access_list
,
10639 ipv6_bgp_distance_source_access_list_cmd
,
10640 "distance (1-255) X:X::X:X/M WORD",
10641 "Define an administrative distance\n"
10642 "Administrative distance\n"
10643 "IP source prefix\n"
10644 "Access list name\n")
10646 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10647 return CMD_SUCCESS
;
10650 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10651 no_ipv6_bgp_distance_source_access_list_cmd
,
10652 "no distance (1-255) X:X::X:X/M WORD",
10654 "Define an administrative distance\n"
10655 "Administrative distance\n"
10656 "IP source prefix\n"
10657 "Access list name\n")
10659 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10660 return CMD_SUCCESS
;
10663 DEFUN (bgp_damp_set
,
10665 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10666 "BGP Specific commands\n"
10667 "Enable route-flap dampening\n"
10668 "Half-life time for the penalty\n"
10669 "Value to start reusing a route\n"
10670 "Value to start suppressing a route\n"
10671 "Maximum duration to suppress a stable route\n")
10673 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10674 int idx_half_life
= 2;
10676 int idx_suppress
= 4;
10677 int idx_max_suppress
= 5;
10678 int half
= DEFAULT_HALF_LIFE
* 60;
10679 int reuse
= DEFAULT_REUSE
;
10680 int suppress
= DEFAULT_SUPPRESS
;
10681 int max
= 4 * half
;
10684 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10685 reuse
= atoi(argv
[idx_reuse
]->arg
);
10686 suppress
= atoi(argv
[idx_suppress
]->arg
);
10687 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10688 } else if (argc
== 3) {
10689 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10693 if (suppress
< reuse
) {
10695 "Suppress value cannot be less than reuse value \n");
10699 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10700 reuse
, suppress
, max
);
10703 DEFUN (bgp_damp_unset
,
10704 bgp_damp_unset_cmd
,
10705 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10707 "BGP Specific commands\n"
10708 "Enable route-flap dampening\n"
10709 "Half-life time for the penalty\n"
10710 "Value to start reusing a route\n"
10711 "Value to start suppressing a route\n"
10712 "Maximum duration to suppress a stable route\n")
10714 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10715 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10718 /* Display specified route of BGP table. */
10719 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10720 const char *ip_str
, afi_t afi
, safi_t safi
,
10721 struct prefix_rd
*prd
, int prefix_check
)
10724 struct prefix match
;
10725 struct bgp_node
*rn
;
10726 struct bgp_node
*rm
;
10727 struct bgp_info
*ri
;
10728 struct bgp_info
*ri_temp
;
10730 struct bgp_table
*table
;
10732 /* BGP structure lookup. */
10734 bgp
= bgp_lookup_by_name(view_name
);
10736 vty_out(vty
, "%% Can't find BGP instance %s\n",
10738 return CMD_WARNING
;
10741 bgp
= bgp_get_default();
10743 vty_out(vty
, "%% No BGP process is configured\n");
10744 return CMD_WARNING
;
10748 /* Check IP address argument. */
10749 ret
= str2prefix(ip_str
, &match
);
10751 vty_out(vty
, "%% address is malformed\n");
10752 return CMD_WARNING
;
10755 match
.family
= afi2family(afi
);
10757 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10758 || (safi
== SAFI_EVPN
)) {
10759 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10760 rn
= bgp_route_next(rn
)) {
10761 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10764 if ((table
= rn
->info
) != NULL
)
10765 if ((rm
= bgp_node_match(table
, &match
))
10769 == match
.prefixlen
) {
10777 bgp_damp_info_free(
10787 bgp_unlock_node(rm
);
10791 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10794 || rn
->p
.prefixlen
== match
.prefixlen
) {
10797 if (ri
->extra
&& ri
->extra
->damp_info
) {
10798 ri_temp
= ri
->next
;
10799 bgp_damp_info_free(
10800 ri
->extra
->damp_info
,
10808 bgp_unlock_node(rn
);
10812 return CMD_SUCCESS
;
10815 DEFUN (clear_ip_bgp_dampening
,
10816 clear_ip_bgp_dampening_cmd
,
10817 "clear ip bgp dampening",
10821 "Clear route flap dampening information\n")
10823 bgp_damp_info_clean();
10824 return CMD_SUCCESS
;
10827 DEFUN (clear_ip_bgp_dampening_prefix
,
10828 clear_ip_bgp_dampening_prefix_cmd
,
10829 "clear ip bgp dampening A.B.C.D/M",
10833 "Clear route flap dampening information\n"
10836 int idx_ipv4_prefixlen
= 4;
10837 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10838 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
10841 DEFUN (clear_ip_bgp_dampening_address
,
10842 clear_ip_bgp_dampening_address_cmd
,
10843 "clear ip bgp dampening A.B.C.D",
10847 "Clear route flap dampening information\n"
10848 "Network to clear damping information\n")
10851 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
10852 SAFI_UNICAST
, NULL
, 0);
10855 DEFUN (clear_ip_bgp_dampening_address_mask
,
10856 clear_ip_bgp_dampening_address_mask_cmd
,
10857 "clear ip bgp dampening A.B.C.D A.B.C.D",
10861 "Clear route flap dampening information\n"
10862 "Network to clear damping information\n"
10866 int idx_ipv4_2
= 5;
10868 char prefix_str
[BUFSIZ
];
10870 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
10873 vty_out(vty
, "%% Inconsistent address and mask\n");
10874 return CMD_WARNING
;
10877 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
10881 /* also used for encap safi */
10882 static int bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
10883 afi_t afi
, safi_t safi
, int *write
)
10885 struct bgp_node
*prn
;
10886 struct bgp_node
*rn
;
10887 struct bgp_table
*table
;
10889 struct prefix_rd
*prd
;
10890 struct bgp_static
*bgp_static
;
10891 mpls_label_t label
;
10892 char buf
[SU_ADDRSTRLEN
];
10893 char rdbuf
[RD_ADDRSTRLEN
];
10895 /* Network configuration. */
10896 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10897 prn
= bgp_route_next(prn
))
10898 if ((table
= prn
->info
) != NULL
)
10899 for (rn
= bgp_table_top(table
); rn
;
10900 rn
= bgp_route_next(rn
))
10901 if ((bgp_static
= rn
->info
) != NULL
) {
10903 prd
= (struct prefix_rd
*)&prn
->p
;
10905 /* "address-family" display. */
10906 bgp_config_write_family_header(
10907 vty
, afi
, safi
, write
);
10909 /* "network" configuration display. */
10910 prefix_rd2str(prd
, rdbuf
,
10912 label
= decode_label(
10913 &bgp_static
->label
);
10915 vty_out(vty
, " network %s/%d rd %s",
10916 inet_ntop(p
->family
,
10919 p
->prefixlen
, rdbuf
);
10920 if (safi
== SAFI_MPLS_VPN
)
10921 vty_out(vty
, " label %u",
10924 if (bgp_static
->rmap
.name
)
10925 vty_out(vty
, " route-map %s",
10926 bgp_static
->rmap
.name
);
10928 if (bgp_static
->backdoor
)
10932 vty_out(vty
, "\n");
10937 static int bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
10938 afi_t afi
, safi_t safi
, int *write
)
10940 struct bgp_node
*prn
;
10941 struct bgp_node
*rn
;
10942 struct bgp_table
*table
;
10944 struct prefix_rd
*prd
;
10945 struct bgp_static
*bgp_static
;
10946 char buf
[PREFIX_STRLEN
];
10947 char buf2
[SU_ADDRSTRLEN
];
10948 char rdbuf
[RD_ADDRSTRLEN
];
10950 /* Network configuration. */
10951 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10952 prn
= bgp_route_next(prn
))
10953 if ((table
= prn
->info
) != NULL
)
10954 for (rn
= bgp_table_top(table
); rn
;
10955 rn
= bgp_route_next(rn
))
10956 if ((bgp_static
= rn
->info
) != NULL
) {
10957 char *macrouter
= NULL
;
10960 if (bgp_static
->router_mac
)
10961 macrouter
= prefix_mac2str(
10962 bgp_static
->router_mac
,
10964 if (bgp_static
->eth_s_id
)
10966 bgp_static
->eth_s_id
);
10968 prd
= (struct prefix_rd
*)&prn
->p
;
10970 /* "address-family" display. */
10971 bgp_config_write_family_header(
10972 vty
, afi
, safi
, write
);
10974 /* "network" configuration display. */
10975 prefix_rd2str(prd
, rdbuf
,
10979 &bgp_static
->igpnexthop
, buf2
,
10982 prefix2str(p
, buf
, sizeof(buf
)),
10984 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
10991 esi
, buf2
, macrouter
);
10992 vty_out(vty
, "\n");
10994 XFREE(MTYPE_TMP
, macrouter
);
10996 XFREE(MTYPE_TMP
, esi
);
11001 /* Configuration of static route announcement and aggregate
11003 int bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11004 safi_t safi
, int *write
)
11006 struct bgp_node
*rn
;
11008 struct bgp_static
*bgp_static
;
11009 struct bgp_aggregate
*bgp_aggregate
;
11010 char buf
[SU_ADDRSTRLEN
];
11012 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
11013 return bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
, write
);
11015 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
11016 return bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
,
11019 /* Network configuration. */
11020 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11021 rn
= bgp_route_next(rn
))
11022 if ((bgp_static
= rn
->info
) != NULL
) {
11025 /* "address-family" display. */
11026 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11028 /* "network" configuration display. */
11029 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11030 && afi
== AFI_IP
) {
11031 u_int32_t destination
;
11032 struct in_addr netmask
;
11034 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11035 masklen2ip(p
->prefixlen
, &netmask
);
11036 vty_out(vty
, " network %s",
11037 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11040 if ((IN_CLASSC(destination
)
11041 && p
->prefixlen
== 24)
11042 || (IN_CLASSB(destination
)
11043 && p
->prefixlen
== 16)
11044 || (IN_CLASSA(destination
)
11045 && p
->prefixlen
== 8)
11046 || p
->u
.prefix4
.s_addr
== 0) {
11047 /* Natural mask is not display. */
11049 vty_out(vty
, " mask %s",
11050 inet_ntoa(netmask
));
11052 vty_out(vty
, " network %s/%d",
11053 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11058 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11059 vty_out(vty
, " label-index %u",
11060 bgp_static
->label_index
);
11062 if (bgp_static
->rmap
.name
)
11063 vty_out(vty
, " route-map %s",
11064 bgp_static
->rmap
.name
);
11066 if (bgp_static
->backdoor
)
11067 vty_out(vty
, " backdoor");
11070 vty_out(vty
, "\n");
11073 /* Aggregate-address configuration. */
11074 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11075 rn
= bgp_route_next(rn
))
11076 if ((bgp_aggregate
= rn
->info
) != NULL
) {
11079 /* "address-family" display. */
11080 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11082 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
)
11083 && afi
== AFI_IP
) {
11084 struct in_addr netmask
;
11086 masklen2ip(p
->prefixlen
, &netmask
);
11087 vty_out(vty
, " aggregate-address %s %s",
11088 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11090 inet_ntoa(netmask
));
11092 vty_out(vty
, " aggregate-address %s/%d",
11093 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11098 if (bgp_aggregate
->as_set
)
11099 vty_out(vty
, " as-set");
11101 if (bgp_aggregate
->summary_only
)
11102 vty_out(vty
, " summary-only");
11104 vty_out(vty
, "\n");
11110 int bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11111 safi_t safi
, int *write
)
11113 struct bgp_node
*rn
;
11114 struct bgp_distance
*bdistance
;
11116 /* Distance configuration. */
11117 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11118 && bgp
->distance_local
[afi
][safi
]
11119 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11120 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11121 || bgp
->distance_local
[afi
][safi
]
11122 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11123 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11124 vty_out(vty
, " distance bgp %d %d %d\n",
11125 bgp
->distance_ebgp
[afi
][safi
],
11126 bgp
->distance_ibgp
[afi
][safi
],
11127 bgp
->distance_local
[afi
][safi
]);
11130 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11131 rn
= bgp_route_next(rn
))
11132 if ((bdistance
= rn
->info
) != NULL
) {
11133 char buf
[PREFIX_STRLEN
];
11135 bgp_config_write_family_header(vty
, afi
, safi
, write
);
11136 vty_out(vty
, " distance %d %s %s\n",
11137 bdistance
->distance
,
11138 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11139 bdistance
->access_list
? bdistance
->access_list
11146 /* Allocate routing table structure and install commands. */
11147 void bgp_route_init(void)
11152 /* Init BGP distance table. */
11153 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11154 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
11155 bgp_distance_table
[afi
][safi
] =
11156 bgp_table_init(afi
, safi
);
11158 /* IPv4 BGP commands. */
11159 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11160 install_element(BGP_NODE
, &bgp_network_cmd
);
11161 install_element(BGP_NODE
, &bgp_network_mask_cmd
);
11162 install_element(BGP_NODE
, &bgp_network_mask_natural_cmd
);
11163 install_element(BGP_NODE
, &bgp_network_route_map_cmd
);
11164 install_element(BGP_NODE
, &bgp_network_mask_route_map_cmd
);
11165 install_element(BGP_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11166 install_element(BGP_NODE
, &bgp_network_backdoor_cmd
);
11167 install_element(BGP_NODE
, &bgp_network_mask_backdoor_cmd
);
11168 install_element(BGP_NODE
, &bgp_network_mask_natural_backdoor_cmd
);
11169 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11170 install_element(BGP_NODE
, &no_bgp_network_cmd
);
11171 install_element(BGP_NODE
, &no_bgp_network_mask_cmd
);
11172 install_element(BGP_NODE
, &no_bgp_network_mask_natural_cmd
);
11174 install_element(BGP_NODE
, &aggregate_address_cmd
);
11175 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11176 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11177 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11179 /* IPv4 unicast configuration. */
11180 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11181 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11182 install_element(BGP_IPV4_NODE
, &bgp_network_mask_cmd
);
11183 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_cmd
);
11184 install_element(BGP_IPV4_NODE
, &bgp_network_route_map_cmd
);
11185 install_element(BGP_IPV4_NODE
, &bgp_network_mask_route_map_cmd
);
11186 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11187 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_cmd
);
11188 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_route_map_cmd
);
11189 install_element(BGP_IPV4_NODE
, &no_bgp_network_label_index_cmd
);
11190 install_element(BGP_IPV4_NODE
,
11191 &no_bgp_network_label_index_route_map_cmd
);
11192 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11193 install_element(BGP_IPV4_NODE
, &no_bgp_network_cmd
);
11194 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_cmd
);
11195 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_natural_cmd
);
11197 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11198 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11199 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11200 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11202 /* IPv4 multicast configuration. */
11203 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11204 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11205 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_cmd
);
11206 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_natural_cmd
);
11207 install_element(BGP_IPV4M_NODE
, &bgp_network_route_map_cmd
);
11208 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_route_map_cmd
);
11209 install_element(BGP_IPV4M_NODE
,
11210 &bgp_network_mask_natural_route_map_cmd
);
11211 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11212 install_element(BGP_IPV4M_NODE
, &no_bgp_network_cmd
);
11213 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_cmd
);
11214 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_natural_cmd
);
11215 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11216 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11217 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11218 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11220 /* IPv4 labeled-unicast configuration. */
11221 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11222 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11223 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11224 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11226 install_element(VIEW_NODE
,
11227 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11228 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11229 install_element(VIEW_NODE
,
11230 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11231 #ifdef KEEP_OLD_VPN_COMMANDS
11232 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11233 #endif /* KEEP_OLD_VPN_COMMANDS */
11234 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11235 install_element(VIEW_NODE
,
11236 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11238 /* BGP dampening clear commands */
11239 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11240 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11242 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11243 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11246 install_element(ENABLE_NODE
,
11247 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11248 #ifdef KEEP_OLD_VPN_COMMANDS
11249 install_element(ENABLE_NODE
,
11250 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11251 #endif /* KEEP_OLD_VPN_COMMANDS */
11253 /* New config IPv6 BGP commands. */
11254 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11255 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11256 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_route_map_cmd
);
11257 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11258 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_cmd
);
11259 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_label_index_cmd
);
11260 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_label_index_cmd
);
11261 install_element(BGP_IPV6_NODE
,
11262 &ipv6_bgp_network_label_index_route_map_cmd
);
11263 install_element(BGP_IPV6_NODE
,
11264 &no_ipv6_bgp_network_label_index_route_map_cmd
);
11266 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11267 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11269 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11270 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_network_cmd
);
11272 install_element(BGP_IPV6L_NODE
, &bgp_table_map_cmd
);
11273 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
11274 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_route_map_cmd
);
11275 install_element(BGP_IPV6L_NODE
, &no_bgp_table_map_cmd
);
11276 install_element(BGP_IPV6L_NODE
, &no_ipv6_bgp_network_cmd
);
11278 install_element(BGP_NODE
, &bgp_distance_cmd
);
11279 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11280 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11281 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11282 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11283 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11284 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11285 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11286 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11287 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11288 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11289 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11290 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11291 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11292 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11293 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11294 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11295 install_element(BGP_IPV4M_NODE
,
11296 &no_bgp_distance_source_access_list_cmd
);
11297 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11298 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11299 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11300 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11301 install_element(BGP_IPV6_NODE
,
11302 &ipv6_bgp_distance_source_access_list_cmd
);
11303 install_element(BGP_IPV6_NODE
,
11304 &no_ipv6_bgp_distance_source_access_list_cmd
);
11305 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11306 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11307 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11308 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11309 install_element(BGP_IPV6M_NODE
,
11310 &ipv6_bgp_distance_source_access_list_cmd
);
11311 install_element(BGP_IPV6M_NODE
,
11312 &no_ipv6_bgp_distance_source_access_list_cmd
);
11314 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11315 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11316 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11317 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11319 /* IPv4 Multicast Mode */
11320 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11321 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11323 /* Large Communities */
11324 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11325 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11328 void bgp_route_finish(void)
11333 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11334 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
11335 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11336 bgp_distance_table
[afi
][safi
] = NULL
;