summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_vty.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_vty.c')
-rw-r--r--bgpd/bgp_vty.c22042
1 files changed, 22042 insertions, 0 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
new file mode 100644
index 0000000..e49baff
--- /dev/null
+++ b/bgpd/bgp_vty.c
@@ -0,0 +1,22042 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* BGP VTY interface.
+ * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "lib/json.h"
+#include "lib/sockopt.h"
+#include "lib_errors.h"
+#include "lib/zclient.h"
+#include "lib/printfrr.h"
+#include "prefix.h"
+#include "plist.h"
+#include "buffer.h"
+#include "linklist.h"
+#include "stream.h"
+#include "frrevent.h"
+#include "log.h"
+#include "memory.h"
+#include "lib_vty.h"
+#include "hash.h"
+#include "queue.h"
+#include "filter.h"
+#include "frrstr.h"
+#include "asn.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr_evpn.h"
+#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_lcommunity.h"
+#include "bgpd/bgp_damp.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_errors.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_mpath.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_updgrp.h"
+#include "bgpd/bgp_bfd.h"
+#include "bgpd/bgp_io.h"
+#include "bgpd/bgp_evpn.h"
+#include "bgpd/bgp_evpn_vty.h"
+#include "bgpd/bgp_evpn_mh.h"
+#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_flowspec.h"
+#include "bgpd/bgp_conditional_adv.h"
+#ifdef ENABLE_BGP_VNC
+#include "bgpd/rfapi/bgp_rfapi_cfg.h"
+#endif
+
+FRR_CFG_DEFAULT_BOOL(BGP_IMPORT_CHECK,
+ {
+ .val_bool = false,
+ .match_profile = "traditional",
+ .match_version = "< 7.4",
+ },
+ { .val_bool = true },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_SHOW_HOSTNAME,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_SHOW_NEXTHOP_HOSTNAME,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_LOG_NEIGHBOR_CHANGES,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_DETERMINISTIC_MED,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
+FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY,
+ { .val_ulong = 10, .match_profile = "datacenter", },
+ { .val_ulong = 120 },
+);
+FRR_CFG_DEFAULT_ULONG(BGP_HOLDTIME,
+ { .val_ulong = 9, .match_profile = "datacenter", },
+ { .val_ulong = 180 },
+);
+FRR_CFG_DEFAULT_ULONG(BGP_KEEPALIVE,
+ { .val_ulong = 3, .match_profile = "datacenter", },
+ { .val_ulong = 60 },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_EBGP_REQUIRES_POLICY,
+ { .val_bool = false, .match_profile = "datacenter", },
+ { .val_bool = false, .match_version = "< 7.4", },
+ { .val_bool = true },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_SUPPRESS_DUPLICATES,
+ { .val_bool = false, .match_version = "< 7.6", },
+ { .val_bool = true },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_GRACEFUL_NOTIFICATION,
+ { .val_bool = false, .match_version = "< 8.3", },
+ { .val_bool = true },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_HARD_ADMIN_RESET,
+ { .val_bool = false, .match_version = "< 8.3", },
+ { .val_bool = true },
+);
+FRR_CFG_DEFAULT_BOOL(BGP_SOFT_VERSION_CAPABILITY,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
+
+DEFINE_HOOK(bgp_inst_config_write,
+ (struct bgp *bgp, struct vty *vty),
+ (bgp, vty));
+DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp));
+DEFINE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp));
+
+static struct peer_group *listen_range_exists(struct bgp *bgp,
+ struct prefix *range, int exact);
+
+/* Show BGP peer's information. */
+enum show_type {
+ show_all,
+ show_peer,
+ show_ipv4_all,
+ show_ipv6_all,
+ show_ipv4_peer,
+ show_ipv6_peer
+};
+
+static struct peer_group *listen_range_exists(struct bgp *bgp,
+ struct prefix *range, int exact);
+
+static void bgp_show_global_graceful_restart_mode_vty(struct vty *vty,
+ struct bgp *bgp);
+
+static int bgp_show_neighbor_graceful_restart_afi_all(struct vty *vty,
+ enum show_type type,
+ const char *ip_str,
+ afi_t afi, bool use_json);
+
+static enum node_type bgp_node_type(afi_t afi, safi_t safi)
+{
+ switch (afi) {
+ case AFI_IP:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return BGP_IPV4_NODE;
+ case SAFI_MULTICAST:
+ return BGP_IPV4M_NODE;
+ case SAFI_LABELED_UNICAST:
+ return BGP_IPV4L_NODE;
+ case SAFI_MPLS_VPN:
+ return BGP_VPNV4_NODE;
+ case SAFI_FLOWSPEC:
+ return BGP_FLOWSPECV4_NODE;
+ case SAFI_UNSPEC:
+ case SAFI_ENCAP:
+ case SAFI_EVPN:
+ case SAFI_MAX:
+ /* not expected */
+ return BGP_IPV4_NODE;
+ }
+ break;
+ case AFI_IP6:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return BGP_IPV6_NODE;
+ case SAFI_MULTICAST:
+ return BGP_IPV6M_NODE;
+ case SAFI_LABELED_UNICAST:
+ return BGP_IPV6L_NODE;
+ case SAFI_MPLS_VPN:
+ return BGP_VPNV6_NODE;
+ case SAFI_FLOWSPEC:
+ return BGP_FLOWSPECV6_NODE;
+ case SAFI_UNSPEC:
+ case SAFI_ENCAP:
+ case SAFI_EVPN:
+ case SAFI_MAX:
+ /* not expected and the return value seems wrong */
+ return BGP_IPV4_NODE;
+ }
+ break;
+ case AFI_L2VPN:
+ return BGP_EVPN_NODE;
+ case AFI_UNSPEC:
+ case AFI_MAX:
+ // We should never be here but to clarify the switch statement..
+ return BGP_IPV4_NODE;
+ }
+
+ // Impossible to happen
+ return BGP_IPV4_NODE;
+}
+
+static const char *get_afi_safi_vty_str(afi_t afi, safi_t safi)
+{
+ if (afi == AFI_IP) {
+ if (safi == SAFI_UNICAST)
+ return "IPv4 Unicast";
+ if (safi == SAFI_MULTICAST)
+ return "IPv4 Multicast";
+ if (safi == SAFI_LABELED_UNICAST)
+ return "IPv4 Labeled Unicast";
+ if (safi == SAFI_MPLS_VPN)
+ return "IPv4 VPN";
+ if (safi == SAFI_ENCAP)
+ return "IPv4 Encap";
+ if (safi == SAFI_FLOWSPEC)
+ return "IPv4 Flowspec";
+ } else if (afi == AFI_IP6) {
+ if (safi == SAFI_UNICAST)
+ return "IPv6 Unicast";
+ if (safi == SAFI_MULTICAST)
+ return "IPv6 Multicast";
+ if (safi == SAFI_LABELED_UNICAST)
+ return "IPv6 Labeled Unicast";
+ if (safi == SAFI_MPLS_VPN)
+ return "IPv6 VPN";
+ if (safi == SAFI_ENCAP)
+ return "IPv6 Encap";
+ if (safi == SAFI_FLOWSPEC)
+ return "IPv6 Flowspec";
+ } else if (afi == AFI_L2VPN) {
+ if (safi == SAFI_EVPN)
+ return "L2VPN EVPN";
+ }
+
+ return "Unknown";
+}
+
+/*
+ * Please note that we have intentionally camelCased
+ * the return strings here. So if you want
+ * to use this function, please ensure you
+ * are doing this within json output
+ */
+static const char *get_afi_safi_json_str(afi_t afi, safi_t safi)
+{
+ if (afi == AFI_IP) {
+ if (safi == SAFI_UNICAST)
+ return "ipv4Unicast";
+ if (safi == SAFI_MULTICAST)
+ return "ipv4Multicast";
+ if (safi == SAFI_LABELED_UNICAST)
+ return "ipv4LabeledUnicast";
+ if (safi == SAFI_MPLS_VPN)
+ return "ipv4Vpn";
+ if (safi == SAFI_ENCAP)
+ return "ipv4Encap";
+ if (safi == SAFI_FLOWSPEC)
+ return "ipv4Flowspec";
+ } else if (afi == AFI_IP6) {
+ if (safi == SAFI_UNICAST)
+ return "ipv6Unicast";
+ if (safi == SAFI_MULTICAST)
+ return "ipv6Multicast";
+ if (safi == SAFI_LABELED_UNICAST)
+ return "ipv6LabeledUnicast";
+ if (safi == SAFI_MPLS_VPN)
+ return "ipv6Vpn";
+ if (safi == SAFI_ENCAP)
+ return "ipv6Encap";
+ if (safi == SAFI_FLOWSPEC)
+ return "ipv6Flowspec";
+ } else if (afi == AFI_L2VPN) {
+ if (safi == SAFI_EVPN)
+ return "l2VpnEvpn";
+ }
+
+ return "Unknown";
+}
+
+/* unset srv6 locator */
+static int bgp_srv6_locator_unset(struct bgp *bgp)
+{
+ int ret;
+ struct listnode *node, *nnode;
+ struct srv6_locator_chunk *chunk;
+ struct bgp_srv6_function *func;
+ struct bgp *bgp_vrf;
+
+ /* release chunk notification via ZAPI */
+ ret = bgp_zebra_srv6_manager_release_locator_chunk(
+ bgp->srv6_locator_name);
+ if (ret < 0)
+ return -1;
+
+ /* refresh chunks */
+ for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) {
+ listnode_delete(bgp->srv6_locator_chunks, chunk);
+ srv6_locator_chunk_free(&chunk);
+ }
+
+ /* refresh functions */
+ for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) {
+ listnode_delete(bgp->srv6_functions, func);
+ XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ }
+
+ /* refresh tovpn_sid */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ /* refresh vpnv4 tovpn_sid */
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+
+ /* refresh vpnv6 tovpn_sid */
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+
+ /* refresh per-vrf tovpn_sid */
+ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+ }
+
+ /* update vpn bgp processes */
+ vpn_leak_postchange_all();
+
+ /* refresh tovpn_sid_locator */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ /* refresh vpnv4 tovpn_sid_locator */
+ srv6_locator_chunk_free(
+ &bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+
+ /* refresh vpnv6 tovpn_sid_locator */
+ srv6_locator_chunk_free(
+ &bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+
+ /* refresh per-vrf tovpn_sid_locator */
+ srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
+ }
+
+ /* clear locator name */
+ memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
+
+ return 0;
+}
+
+/* Utility function to get address family from current node. */
+afi_t bgp_node_afi(struct vty *vty)
+{
+ afi_t afi;
+ switch (vty->node) {
+ case BGP_IPV6_NODE:
+ case BGP_IPV6M_NODE:
+ case BGP_IPV6L_NODE:
+ case BGP_VPNV6_NODE:
+ case BGP_FLOWSPECV6_NODE:
+ afi = AFI_IP6;
+ break;
+ case BGP_EVPN_NODE:
+ afi = AFI_L2VPN;
+ break;
+ default:
+ afi = AFI_IP;
+ break;
+ }
+ return afi;
+}
+
+/* Utility function to get subsequent address family from current
+ node. */
+safi_t bgp_node_safi(struct vty *vty)
+{
+ safi_t safi;
+ switch (vty->node) {
+ case BGP_VPNV4_NODE:
+ case BGP_VPNV6_NODE:
+ safi = SAFI_MPLS_VPN;
+ break;
+ case BGP_IPV4M_NODE:
+ case BGP_IPV6M_NODE:
+ safi = SAFI_MULTICAST;
+ break;
+ case BGP_EVPN_NODE:
+ safi = SAFI_EVPN;
+ break;
+ case BGP_IPV4L_NODE:
+ case BGP_IPV6L_NODE:
+ safi = SAFI_LABELED_UNICAST;
+ break;
+ case BGP_FLOWSPECV4_NODE:
+ case BGP_FLOWSPECV6_NODE:
+ safi = SAFI_FLOWSPEC;
+ break;
+ default:
+ safi = SAFI_UNICAST;
+ break;
+ }
+ return safi;
+}
+
+/**
+ * Converts an AFI in string form to afi_t
+ *
+ * @param afi string, one of
+ * - "ipv4"
+ * - "ipv6"
+ * - "l2vpn"
+ * @return the corresponding afi_t
+ */
+afi_t bgp_vty_afi_from_str(const char *afi_str)
+{
+ afi_t afi = AFI_MAX; /* unknown */
+ if (strmatch(afi_str, "ipv4"))
+ afi = AFI_IP;
+ else if (strmatch(afi_str, "ipv6"))
+ afi = AFI_IP6;
+ else if (strmatch(afi_str, "l2vpn"))
+ afi = AFI_L2VPN;
+ return afi;
+}
+
+int argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index,
+ afi_t *afi)
+{
+ int ret = 0;
+ if (argv_find(argv, argc, "ipv4", index)) {
+ ret = 1;
+ if (afi)
+ *afi = AFI_IP;
+ } else if (argv_find(argv, argc, "ipv6", index)) {
+ ret = 1;
+ if (afi)
+ *afi = AFI_IP6;
+ } else if (argv_find(argv, argc, "l2vpn", index)) {
+ ret = 1;
+ if (afi)
+ *afi = AFI_L2VPN;
+ }
+ return ret;
+}
+
+/* supports <unicast|multicast|vpn|labeled-unicast> */
+safi_t bgp_vty_safi_from_str(const char *safi_str)
+{
+ safi_t safi = SAFI_MAX; /* unknown */
+ if (strmatch(safi_str, "multicast"))
+ safi = SAFI_MULTICAST;
+ else if (strmatch(safi_str, "unicast"))
+ safi = SAFI_UNICAST;
+ else if (strmatch(safi_str, "vpn"))
+ safi = SAFI_MPLS_VPN;
+ else if (strmatch(safi_str, "evpn"))
+ safi = SAFI_EVPN;
+ else if (strmatch(safi_str, "labeled-unicast"))
+ safi = SAFI_LABELED_UNICAST;
+ else if (strmatch(safi_str, "flowspec"))
+ safi = SAFI_FLOWSPEC;
+ return safi;
+}
+
+int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index,
+ safi_t *safi)
+{
+ int ret = 0;
+ if (argv_find(argv, argc, "unicast", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_UNICAST;
+ } else if (argv_find(argv, argc, "multicast", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_MULTICAST;
+ } else if (argv_find(argv, argc, "labeled-unicast", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_LABELED_UNICAST;
+ } else if (argv_find(argv, argc, "vpn", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_MPLS_VPN;
+ } else if (argv_find(argv, argc, "evpn", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_EVPN;
+ } else if (argv_find(argv, argc, "flowspec", index)) {
+ ret = 1;
+ if (safi)
+ *safi = SAFI_FLOWSPEC;
+ }
+ return ret;
+}
+
+/*
+ * Convert an afi_t/safi_t pair to matching BGP_DEFAULT_AF* flag.
+ *
+ * afi
+ * address-family identifier
+ *
+ * safi
+ * subsequent address-family identifier
+ *
+ * Returns:
+ * default_af string corresponding to the supplied afi/safi pair.
+ * If afi/safi is invalid or if flag for afi/safi doesn't exist,
+ * return -1.
+ */
+static const char *get_bgp_default_af_flag(afi_t afi, safi_t safi)
+{
+ switch (afi) {
+ case AFI_IP:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return "ipv4-unicast";
+ case SAFI_MULTICAST:
+ return "ipv4-multicast";
+ case SAFI_MPLS_VPN:
+ return "ipv4-vpn";
+ case SAFI_ENCAP:
+ return "ipv4-encap";
+ case SAFI_LABELED_UNICAST:
+ return "ipv4-labeled-unicast";
+ case SAFI_FLOWSPEC:
+ return "ipv4-flowspec";
+ case SAFI_UNSPEC:
+ case SAFI_EVPN:
+ case SAFI_MAX:
+ return "unknown-afi/safi";
+ }
+ break;
+ case AFI_IP6:
+ switch (safi) {
+ case SAFI_UNICAST:
+ return "ipv6-unicast";
+ case SAFI_MULTICAST:
+ return "ipv6-multicast";
+ case SAFI_MPLS_VPN:
+ return "ipv6-vpn";
+ case SAFI_ENCAP:
+ return "ipv6-encap";
+ case SAFI_LABELED_UNICAST:
+ return "ipv6-labeled-unicast";
+ case SAFI_FLOWSPEC:
+ return "ipv6-flowspec";
+ case SAFI_UNSPEC:
+ case SAFI_EVPN:
+ case SAFI_MAX:
+ return "unknown-afi/safi";
+ }
+ break;
+ case AFI_L2VPN:
+ switch (safi) {
+ case SAFI_EVPN:
+ return "l2vpn-evpn";
+ case SAFI_UNICAST:
+ case SAFI_MULTICAST:
+ case SAFI_MPLS_VPN:
+ case SAFI_ENCAP:
+ case SAFI_LABELED_UNICAST:
+ case SAFI_FLOWSPEC:
+ case SAFI_UNSPEC:
+ case SAFI_MAX:
+ return "unknown-afi/safi";
+ }
+ break;
+ case AFI_UNSPEC:
+ case AFI_MAX:
+ return "unknown-afi/safi";
+ }
+ /* all AFIs are accounted for above, so this shouldn't happen */
+
+ assert(!"Reached end of function where we did not expect to");
+}
+
+int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
+ enum bgp_instance_type inst_type, const char *as_pretty,
+ enum asnotation_mode asnotation)
+{
+ int ret = bgp_get(bgp, as, name, inst_type, as_pretty, asnotation);
+
+ if (ret == BGP_CREATED) {
+ bgp_timers_set(NULL, *bgp, DFLT_BGP_KEEPALIVE, DFLT_BGP_HOLDTIME,
+ DFLT_BGP_CONNECT_RETRY, BGP_DEFAULT_DELAYOPEN);
+
+ if (DFLT_BGP_IMPORT_CHECK)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_IMPORT_CHECK);
+ if (DFLT_BGP_SHOW_HOSTNAME)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_SHOW_HOSTNAME);
+ if (DFLT_BGP_SHOW_NEXTHOP_HOSTNAME)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME);
+ if (DFLT_BGP_LOG_NEIGHBOR_CHANGES)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
+ if (DFLT_BGP_DETERMINISTIC_MED)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_DETERMINISTIC_MED);
+ if (DFLT_BGP_EBGP_REQUIRES_POLICY)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_EBGP_REQUIRES_POLICY);
+ if (DFLT_BGP_SUPPRESS_DUPLICATES)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_SUPPRESS_DUPLICATES);
+ if (DFLT_BGP_GRACEFUL_NOTIFICATION)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_GRACEFUL_NOTIFICATION);
+ if (DFLT_BGP_HARD_ADMIN_RESET)
+ SET_FLAG((*bgp)->flags, BGP_FLAG_HARD_ADMIN_RESET);
+ if (DFLT_BGP_SOFT_VERSION_CAPABILITY)
+ SET_FLAG((*bgp)->flags,
+ BGP_FLAG_SOFT_VERSION_CAPABILITY);
+
+ ret = BGP_SUCCESS;
+ }
+ return ret;
+}
+
+/*
+ * bgp_vty_find_and_parse_afi_safi_bgp
+ *
+ * For a given 'show ...' command, correctly parse the afi/safi/bgp out from it
+ * This function *assumes* that the calling function pre-sets the afi/safi/bgp
+ * to appropriate values for the calling function. This is to allow the
+ * calling function to make decisions appropriate for the show command
+ * that is being parsed.
+ *
+ * The show commands are generally of the form:
+ * "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6>
+ * [<unicast|multicast|vpn|labeled-unicast>]] ..."
+ *
+ * Since we use argv_find if the show command in particular doesn't have:
+ * [ip]
+ * [<view|vrf> VIEWVRFNAME]
+ * [<ipv4|ipv6> [<unicast|multicast|vpn|labeled-unicast>]]
+ * The command parsing should still be ok.
+ *
+ * vty -> The vty for the command so we can output some useful data in
+ * the event of a parse error in the vrf.
+ * argv -> The command tokens
+ * argc -> How many command tokens we have
+ * idx -> The current place in the command, generally should be 0 for this
+ * function
+ * afi -> The parsed afi if it was included in the show command, returned here
+ * safi -> The parsed safi if it was included in the show command, returned here
+ * bgp -> Pointer to the bgp data structure we need to fill in.
+ * use_json -> json is configured or not
+ *
+ * The function returns the correct location in the parse tree for the
+ * last token found.
+ *
+ * Returns 0 for failure to parse correctly, else the idx position of where
+ * it found the last token.
+ */
+int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
+ struct cmd_token **argv, int argc,
+ int *idx, afi_t *afi, safi_t *safi,
+ struct bgp **bgp, bool use_json)
+{
+ char *vrf_name = NULL;
+
+ assert(afi);
+ assert(safi);
+ assert(bgp);
+
+ if (argv_find(argv, argc, "ip", idx))
+ *afi = AFI_IP;
+
+ if (argv_find(argv, argc, "view", idx))
+ vrf_name = argv[*idx + 1]->arg;
+ else if (argv_find(argv, argc, "vrf", idx)) {
+ vrf_name = argv[*idx + 1]->arg;
+ if (strmatch(vrf_name, VRF_DEFAULT_NAME))
+ vrf_name = NULL;
+ }
+ if (vrf_name) {
+ if (strmatch(vrf_name, "all"))
+ *bgp = NULL;
+ else {
+ *bgp = bgp_lookup_by_name(vrf_name);
+ if (!*bgp) {
+ if (use_json) {
+ json_object *json = NULL;
+ json = json_object_new_object();
+ json_object_string_add(
+ json, "warning",
+ "View/Vrf is unknown");
+ vty_json(vty, json);
+ }
+ else
+ vty_out(vty, "View/Vrf %s is unknown\n",
+ vrf_name);
+ *idx = 0;
+ return 0;
+ }
+ }
+ } else {
+ *bgp = bgp_get_default();
+ if (!*bgp) {
+ if (use_json) {
+ json_object *json = NULL;
+ json = json_object_new_object();
+ json_object_string_add(
+ json, "warning",
+ "Default BGP instance not found");
+ vty_json(vty, json);
+ }
+ else
+ vty_out(vty,
+ "Default BGP instance not found\n");
+ *idx = 0;
+ return 0;
+ }
+ }
+
+ if (argv_find_and_parse_afi(argv, argc, idx, afi))
+ argv_find_and_parse_safi(argv, argc, idx, safi);
+
+ *idx += 1;
+ return *idx;
+}
+
+static bool peer_address_self_check(struct bgp *bgp, union sockunion *su)
+{
+ struct interface *ifp = NULL;
+ struct listnode *node;
+ struct bgp_listener *listener;
+ union sockunion all_su;
+
+ if (su->sa.sa_family == AF_INET) {
+ (void)str2sockunion("0.0.0.0", &all_su);
+ ifp = if_lookup_by_ipv4_exact(&su->sin.sin_addr, bgp->vrf_id);
+ } else if (su->sa.sa_family == AF_INET6) {
+ (void)str2sockunion("::", &all_su);
+ ifp = if_lookup_by_ipv6_exact(&su->sin6.sin6_addr,
+ su->sin6.sin6_scope_id,
+ bgp->vrf_id);
+ }
+
+ if (ifp) {
+ for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener)) {
+ if (sockunion_family(su) !=
+ sockunion_family(&listener->su))
+ continue;
+
+ /* If 0.0.0.0/:: is a listener, then treat as self and
+ * reject.
+ */
+ if (!sockunion_cmp(&listener->su, su) ||
+ !sockunion_cmp(&listener->su, &all_su))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Utility function for looking up peer from VTY. */
+/* This is used only for configuration, so disallow if attempted on
+ * a dynamic neighbor.
+ */
+static struct peer *peer_lookup_vty(struct vty *vty, const char *ip_str)
+{
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+ int ret;
+ union sockunion su;
+ struct peer *peer;
+
+ if (!bgp) {
+ return NULL;
+ }
+
+ ret = str2sockunion(ip_str, &su);
+ if (ret < 0) {
+ peer = peer_lookup_by_conf_if(bgp, ip_str);
+ if (!peer) {
+ if ((peer = peer_lookup_by_hostname(bgp, ip_str))
+ == NULL) {
+ vty_out(vty,
+ "%% Malformed address or name: %s\n",
+ ip_str);
+ return NULL;
+ }
+ }
+ } else {
+ peer = peer_lookup(bgp, &su);
+ if (!peer) {
+ vty_out(vty,
+ "%% Specify remote-as or peer-group commands first\n");
+ return NULL;
+ }
+ if (peer_dynamic_neighbor(peer)) {
+ vty_out(vty,
+ "%% Operation not allowed on a dynamic neighbor\n");
+ return NULL;
+ }
+ }
+ return peer;
+}
+
+/* Utility function for looking up peer or peer group. */
+/* This is used only for configuration, so disallow if attempted on
+ * a dynamic neighbor.
+ */
+struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str)
+{
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+ int ret;
+ union sockunion su;
+ struct peer *peer = NULL;
+ struct peer_group *group = NULL;
+
+ if (!bgp) {
+ return NULL;
+ }
+
+ ret = str2sockunion(peer_str, &su);
+ if (ret == 0) {
+ /* IP address, locate peer. */
+ peer = peer_lookup(bgp, &su);
+ } else {
+ /* Not IP, could match either peer configured on interface or a
+ * group. */
+ peer = peer_lookup_by_conf_if(bgp, peer_str);
+ if (!peer)
+ group = peer_group_lookup(bgp, peer_str);
+ }
+
+ if (peer) {
+ if (peer_dynamic_neighbor(peer)) {
+ zlog_warn(
+ "%pBP: Operation not allowed on a dynamic neighbor",
+ peer);
+ vty_out(vty,
+ "%% Operation not allowed on a dynamic neighbor\n");
+ return NULL;
+ }
+
+ return peer;
+ }
+
+ if (group)
+ return group->conf;
+
+ zlog_warn("Specify remote-as or peer-group commands first before: %s",
+ vty->buf);
+ vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
+
+ return NULL;
+}
+
+int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
+{
+ const char *str = NULL;
+
+ switch (ret) {
+ case BGP_SUCCESS:
+ case BGP_CREATED:
+ case BGP_GR_NO_OPERATION:
+ break;
+ case BGP_ERR_INVALID_VALUE:
+ str = "Invalid value";
+ break;
+ case BGP_ERR_INVALID_FLAG:
+ str = "Invalid flag";
+ break;
+ case BGP_ERR_PEER_GROUP_SHUTDOWN:
+ str = "Peer-group has been shutdown. Activate the peer-group first";
+ break;
+ case BGP_ERR_PEER_FLAG_CONFLICT:
+ str = "Can't set override-capability and strict-capability-match at the same time";
+ break;
+ case BGP_ERR_PEER_GROUP_NO_REMOTE_AS:
+ str = "Specify remote-as or peer-group remote AS first";
+ break;
+ case BGP_ERR_PEER_GROUP_CANT_CHANGE:
+ str = "Cannot change the peer-group. Deconfigure first";
+ break;
+ case BGP_ERR_PEER_GROUP_MISMATCH:
+ str = "Peer is not a member of this peer-group";
+ break;
+ case BGP_ERR_PEER_FILTER_CONFLICT:
+ str = "Prefix/distribute list can not co-exist";
+ break;
+ case BGP_ERR_NOT_INTERNAL_PEER:
+ str = "Invalid command. Not an internal neighbor";
+ break;
+ case BGP_ERR_REMOVE_PRIVATE_AS:
+ str = "remove-private-AS cannot be configured for IBGP peers";
+ break;
+ case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS:
+ str = "Cannot have local-as same as BGP AS number";
+ break;
+ case BGP_ERR_TCPSIG_FAILED:
+ str = "Error while applying TCP-Sig to session(s)";
+ break;
+ case BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK:
+ str = "ebgp-multihop and ttl-security cannot be configured together";
+ break;
+ case BGP_ERR_NO_IBGP_WITH_TTLHACK:
+ str = "ttl-security only allowed for EBGP peers";
+ break;
+ case BGP_ERR_AS_OVERRIDE:
+ str = "as-override cannot be configured for IBGP peers";
+ break;
+ case BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT:
+ str = "Invalid limit for number of dynamic neighbors";
+ break;
+ case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS:
+ str = "Dynamic neighbor listen range already exists";
+ break;
+ case BGP_ERR_INVALID_FOR_DYNAMIC_PEER:
+ str = "Operation not allowed on a dynamic neighbor";
+ break;
+ case BGP_ERR_INVALID_FOR_DIRECT_PEER:
+ str = "Operation not allowed on a directly connected neighbor";
+ break;
+ case BGP_ERR_PEER_SAFI_CONFLICT:
+ str = "Cannot activate peer for both 'ipv4 unicast' and 'ipv4 labeled-unicast'";
+ break;
+ case BGP_ERR_GR_INVALID_CMD:
+ str = "The Graceful Restart command used is not valid at this moment.";
+ break;
+ case BGP_ERR_GR_OPERATION_FAILED:
+ str = "The Graceful Restart Operation failed due to an err.";
+ break;
+ case BGP_ERR_PEER_GROUP_MEMBER:
+ str = "Peer-group member cannot override remote-as of peer-group.";
+ break;
+ case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
+ str = "Peer-group members must be all internal or all external.";
+ break;
+ case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND:
+ str = "Range specified cannot be deleted because it is not part of current config.";
+ break;
+ case BGP_ERR_INSTANCE_MISMATCH:
+ str = "Instance specified does not match the current instance.";
+ break;
+ case BGP_ERR_NO_INTERFACE_CONFIG:
+ str = "Interface specified is not being used for interface based peer.";
+ break;
+ case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
+ str = "No configuration already specified for soft reconfiguration.";
+ break;
+ case BGP_ERR_AS_MISMATCH:
+ str = "BGP is already running.";
+ break;
+ case BGP_ERR_AF_UNCONFIGURED:
+ str = "AFI/SAFI specified is not currently configured.";
+ break;
+ case BGP_ERR_INVALID_AS:
+ str = "Confederation AS specified is the same AS as our AS.";
+ break;
+ case BGP_ERR_INVALID_ROLE_NAME:
+ str = "Invalid role name";
+ break;
+ case BGP_ERR_INVALID_INTERNAL_ROLE:
+ str = "External roles can be set only on eBGP session";
+ break;
+ }
+ if (str) {
+ vty_out(vty, "%% %s\n", str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+/* BGP clear sort. */
+enum clear_sort {
+ clear_all,
+ clear_peer,
+ clear_group,
+ clear_external,
+ clear_as
+};
+
+static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
+ safi_t safi, int error)
+{
+ switch (error) {
+ case BGP_ERR_AF_UNCONFIGURED:
+ if (vty)
+ vty_out(vty,
+ "%% BGP: Enable %s address family for the neighbor %s\n",
+ get_afi_safi_str(afi, safi, false), peer->host);
+ else
+ zlog_warn(
+ "%% BGP: Enable %s address family for the neighbor %s",
+ get_afi_safi_str(afi, safi, false), peer->host);
+ break;
+ case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
+ if (vty)
+ vty_out(vty,
+ "%% BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
+ peer->host);
+ else
+ zlog_warn(
+ "%% BGP: Inbound soft reconfig for %s not possible as it has neither refresh capability, nor inbound soft reconfig",
+ peer->host);
+ break;
+ default:
+ break;
+ }
+}
+
+static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi,
+ struct listnode **nnode, enum bgp_clear_type stype)
+{
+ int ret = 0;
+ struct peer_af *paf;
+
+ /* if afi/.safi not specified, spin thru all of them */
+ if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) {
+ afi_t tmp_afi;
+ safi_t tmp_safi;
+ enum bgp_af_index index;
+
+ for (index = BGP_AF_START; index < BGP_AF_MAX; index++) {
+ paf = peer->peer_af_array[index];
+ if (!paf)
+ continue;
+
+ if (paf && paf->subgroup)
+ SET_FLAG(paf->subgroup->sflags,
+ SUBGRP_STATUS_FORCE_UPDATES);
+
+ tmp_afi = paf->afi;
+ tmp_safi = paf->safi;
+ if (!peer->afc[tmp_afi][tmp_safi])
+ continue;
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, nnode);
+ else
+ ret = peer_clear_soft(peer, tmp_afi, tmp_safi,
+ stype);
+ }
+ /* if afi specified and safi not, spin thru safis on this afi */
+ } else if (safi == SAFI_UNSPEC) {
+ safi_t tmp_safi;
+
+ for (tmp_safi = SAFI_UNICAST;
+ tmp_safi < SAFI_MAX; tmp_safi++) {
+ if (!peer->afc[afi][tmp_safi])
+ continue;
+
+ paf = peer_af_find(peer, afi, tmp_safi);
+ if (paf && paf->subgroup)
+ SET_FLAG(paf->subgroup->sflags,
+ SUBGRP_STATUS_FORCE_UPDATES);
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, nnode);
+ else
+ ret = peer_clear_soft(peer, afi,
+ tmp_safi, stype);
+ }
+ /* both afi/safi specified, let the caller know if not defined */
+ } else {
+ if (!peer->afc[afi][safi])
+ return 1;
+
+ paf = peer_af_find(peer, afi, safi);
+ if (paf && paf->subgroup)
+ SET_FLAG(paf->subgroup->sflags,
+ SUBGRP_STATUS_FORCE_UPDATES);
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, nnode);
+ else
+ ret = peer_clear_soft(peer, afi, safi, stype);
+ }
+
+ return ret;
+}
+
+/* `clear ip bgp' functions. */
+static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
+ enum clear_sort sort, enum bgp_clear_type stype,
+ const char *arg)
+{
+ int ret = 0;
+ bool found = false;
+ struct peer *peer;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ /* Clear all neighbors. */
+ /*
+ * Pass along pointer to next node to peer_clear() when walking all
+ * nodes on the BGP instance as that may get freed if it is a
+ * doppelganger
+ */
+ if (sort == clear_all) {
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+
+ bgp_peer_gr_flags_update(peer);
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
+ gr_router_detected = true;
+
+ ret = bgp_peer_clear(peer, afi, safi, &nnode,
+ stype);
+
+ if (ret < 0)
+ bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ }
+
+ if (gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) {
+ bgp_zebra_send_capabilities(bgp, false);
+ } else if (!gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
+ bgp_zebra_send_capabilities(bgp, true);
+ }
+
+ /* This is to apply read-only mode on this clear. */
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ bgp->update_delay_over = 0;
+
+ return CMD_SUCCESS;
+ }
+
+ /* Clear specified neighbor. */
+ if (sort == clear_peer) {
+ union sockunion su;
+
+ /* Make sockunion for lookup. */
+ ret = str2sockunion(arg, &su);
+ if (ret < 0) {
+ peer = peer_lookup_by_conf_if(bgp, arg);
+ if (!peer) {
+ peer = peer_lookup_by_hostname(bgp, arg);
+ if (!peer) {
+ vty_out(vty,
+ "Malformed address or name: %s\n",
+ arg);
+ return CMD_WARNING;
+ }
+ }
+ } else {
+ peer = peer_lookup(bgp, &su);
+ if (!peer) {
+ vty_out(vty,
+ "%% BGP: Unknown neighbor - \"%s\"\n",
+ arg);
+ return CMD_WARNING;
+ }
+ }
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ ret = bgp_peer_clear(peer, afi, safi, NULL, stype);
+
+ /* if afi/safi not defined for this peer, let caller know */
+ if (ret == 1)
+ ret = BGP_ERR_AF_UNCONFIGURED;
+
+ if (ret < 0)
+ bgp_clear_vty_error(vty, peer, afi, safi, ret);
+
+ return CMD_SUCCESS;
+ }
+
+ /* Clear all neighbors belonging to a specific peer-group. */
+ if (sort == clear_group) {
+ struct peer_group *group;
+
+ group = peer_group_lookup(bgp, arg);
+ if (!group) {
+ vty_out(vty, "%% BGP: No such peer-group %s\n", arg);
+ return CMD_WARNING;
+ }
+
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
+ ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);
+
+ if (ret < 0)
+ bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
+ }
+
+ if (!found)
+ vty_out(vty,
+ "%% BGP: No %s peer belonging to peer-group %s is configured\n",
+ get_afi_safi_str(afi, safi, false), arg);
+
+ return CMD_SUCCESS;
+ }
+
+ /* Clear all external (eBGP) neighbors. */
+ if (sort == clear_external) {
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (peer->sort == BGP_PEER_IBGP)
+ continue;
+
+ bgp_peer_gr_flags_update(peer);
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
+ gr_router_detected = true;
+
+ ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);
+
+ if (ret < 0)
+ bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
+ }
+
+ if (gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) {
+ bgp_zebra_send_capabilities(bgp, false);
+ } else if (!gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
+ bgp_zebra_send_capabilities(bgp, true);
+ }
+
+ if (!found)
+ vty_out(vty,
+ "%% BGP: No external %s peer is configured\n",
+ get_afi_safi_str(afi, safi, false));
+
+ return CMD_SUCCESS;
+ }
+
+ /* Clear all neighbors belonging to a specific AS. */
+ if (sort == clear_as) {
+ as_t as;
+
+ if (!asn_str2asn(arg, &as)) {
+ vty_out(vty, "%% BGP: No such AS %s\n", arg);
+ return CMD_WARNING;
+ }
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (peer->as != as)
+ continue;
+
+ bgp_peer_gr_flags_update(peer);
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
+ gr_router_detected = true;
+
+ ret = bgp_peer_clear(peer, afi, safi, &nnode, stype);
+
+ if (ret < 0)
+ bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
+ }
+
+ if (gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) {
+ bgp_zebra_send_capabilities(bgp, false);
+ } else if (!gr_router_detected
+ && bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
+ bgp_zebra_send_capabilities(bgp, true);
+ }
+
+ if (!found)
+ vty_out(vty,
+ "%% BGP: No %s peer is configured with AS %s\n",
+ get_afi_safi_str(afi, safi, false), arg);
+
+ return CMD_SUCCESS;
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_clear_vty(struct vty *vty, const char *name, afi_t afi,
+ safi_t safi, enum clear_sort sort,
+ enum bgp_clear_type stype, const char *arg)
+{
+ struct bgp *bgp;
+
+ /* BGP structure lookup. */
+ if (name) {
+ bgp = bgp_lookup_by_name(name);
+ if (bgp == NULL) {
+ vty_out(vty, "Can't find BGP instance %s\n", name);
+ return CMD_WARNING;
+ }
+ } else {
+ bgp = bgp_get_default();
+ if (bgp == NULL) {
+ vty_out(vty, "No BGP process is configured\n");
+ return CMD_WARNING;
+ }
+ }
+
+ return bgp_clear(vty, bgp, afi, safi, sort, stype, arg);
+}
+
+/* clear soft inbound */
+static void bgp_clear_star_soft_in(struct vty *vty, const char *name)
+{
+ afi_t afi;
+ safi_t safi;
+
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_clear_vty(vty, name, afi, safi, clear_all,
+ BGP_CLEAR_SOFT_IN, NULL);
+}
+
+/* clear soft outbound */
+static void bgp_clear_star_soft_out(struct vty *vty, const char *name)
+{
+ afi_t afi;
+ safi_t safi;
+
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_clear_vty(vty, name, afi, safi, clear_all,
+ BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+
+void bgp_clear_soft_in(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ bgp_clear(NULL, bgp, afi, safi, clear_all, BGP_CLEAR_SOFT_IN, NULL);
+}
+
+static int peer_flag_modify_vty(struct vty *vty, const char *ip_str,
+ uint64_t flag, int set)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /*
+ * If 'neighbor <interface>', then this is for directly connected peers,
+ * we should not accept disable-connected-check.
+ */
+ if (peer->conf_if && (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
+ vty_out(vty,
+ "%s is directly connected peer, cannot accept disable-connected-check\n",
+ ip_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!set && flag == PEER_FLAG_SHUTDOWN)
+ peer_tx_shutdown_message_unset(peer);
+
+ if (set)
+ ret = peer_flag_set(peer, flag);
+ else
+ ret = peer_flag_unset(peer, flag);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_flag_set_vty(struct vty *vty, const char *ip_str, uint64_t flag)
+{
+ return peer_flag_modify_vty(vty, ip_str, flag, 1);
+}
+
+static int peer_flag_unset_vty(struct vty *vty, const char *ip_str,
+ uint64_t flag)
+{
+ return peer_flag_modify_vty(vty, ip_str, flag, 0);
+}
+
+#include "bgpd/bgp_vty_clippy.c"
+
+DEFUN_HIDDEN (bgp_local_mac,
+ bgp_local_mac_cmd,
+ "bgp local-mac vni " CMD_VNI_RANGE " mac WORD seq (0-4294967295)",
+ BGP_STR
+ "Local MAC config\n"
+ "VxLAN Network Identifier\n"
+ "VNI number\n"
+ "local mac\n"
+ "mac address\n"
+ "mac-mobility sequence\n"
+ "seq number\n")
+{
+ int rv;
+ vni_t vni;
+ struct ethaddr mac;
+ struct ipaddr ip;
+ uint32_t seq;
+ struct bgp *bgp;
+
+ vni = strtoul(argv[3]->arg, NULL, 10);
+ if (!prefix_str2mac(argv[5]->arg, &mac)) {
+ vty_out(vty, "%% Malformed MAC address\n");
+ return CMD_WARNING;
+ }
+ memset(&ip, 0, sizeof(ip));
+ seq = strtoul(argv[7]->arg, NULL, 10);
+
+ bgp = bgp_get_default();
+ if (!bgp) {
+ vty_out(vty, "Default BGP instance is not there\n");
+ return CMD_WARNING;
+ }
+
+ rv = bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, 0 /* flags */, seq,
+ zero_esi);
+ if (rv < 0) {
+ vty_out(vty, "Internal error\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (no_bgp_local_mac,
+ no_bgp_local_mac_cmd,
+ "no bgp local-mac vni " CMD_VNI_RANGE " mac WORD",
+ NO_STR
+ BGP_STR
+ "Local MAC config\n"
+ "VxLAN Network Identifier\n"
+ "VNI number\n"
+ "local mac\n"
+ "mac address\n")
+{
+ int rv;
+ vni_t vni;
+ struct ethaddr mac;
+ struct ipaddr ip;
+ struct bgp *bgp;
+
+ vni = strtoul(argv[4]->arg, NULL, 10);
+ if (!prefix_str2mac(argv[6]->arg, &mac)) {
+ vty_out(vty, "%% Malformed MAC address\n");
+ return CMD_WARNING;
+ }
+ memset(&ip, 0, sizeof(ip));
+
+ bgp = bgp_get_default();
+ if (!bgp) {
+ vty_out(vty, "Default BGP instance is not there\n");
+ return CMD_WARNING;
+ }
+
+ rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, ZEBRA_NEIGH_ACTIVE);
+ if (rv < 0) {
+ vty_out(vty, "Internal error\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_synchronization,
+ no_synchronization_cmd,
+ "no synchronization",
+ NO_STR
+ "Perform IGP synchronization\n")
+{
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_auto_summary,
+ no_auto_summary_cmd,
+ "no auto-summary",
+ NO_STR
+ "Enable automatic network number summarization\n")
+{
+ return CMD_SUCCESS;
+}
+
+/* "router bgp" commands. */
+DEFUN_NOSH (router_bgp,
+ router_bgp_cmd,
+ "router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
+ ROUTER_STR
+ BGP_STR
+ AS_STR
+ BGP_INSTANCE_HELP_STR
+ "Force the AS notation output\n"
+ "use 'AA.BB' format for AS 4 byte values\n"
+ "use 'AA.BB' format for all AS values\n"
+ "use plain format for all AS values\n")
+{
+ int idx_asn = 2;
+ int idx_view_vrf = 3;
+ int idx_vrf = 4;
+ int is_new_bgp = 0;
+ int idx_asnotation = 3;
+ int idx_asnotation_kind = 4;
+ enum asnotation_mode asnotation = ASNOTATION_UNDEFINED;
+ int ret;
+ as_t as;
+ struct bgp *bgp;
+ const char *name = NULL;
+ enum bgp_instance_type inst_type;
+
+ // "router bgp" without an ASN
+ if (argc == 2) {
+ // Pending: Make VRF option available for ASN less config
+ bgp = bgp_get_default();
+
+ if (bgp == NULL) {
+ vty_out(vty, "%% No BGP process is configured\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (listcount(bm->bgp) > 1) {
+ vty_out(vty, "%% Please specify ASN and VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ // "router bgp X"
+ else {
+ if (!asn_str2asn(argv[idx_asn]->arg, &as)) {
+ vty_out(vty, "%% BGP: No such AS %s\n",
+ argv[idx_asn]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (as == BGP_PRIVATE_AS_MAX || as == BGP_AS4_MAX)
+ vty_out(vty, "Reserved AS used (%u|%u); AS is %u\n",
+ BGP_PRIVATE_AS_MAX, BGP_AS4_MAX, as);
+
+ inst_type = BGP_INSTANCE_TYPE_DEFAULT;
+
+ if (argv_find(argv, argc, "VIEWVRFNAME", &idx_vrf)) {
+ idx_view_vrf = idx_vrf - 1;
+ if (argv[idx_view_vrf]->text) {
+ name = argv[idx_vrf]->arg;
+
+ if (!strcmp(argv[idx_view_vrf]->text, "vrf")) {
+ if (strmatch(name, VRF_DEFAULT_NAME))
+ name = NULL;
+ else
+ inst_type =
+ BGP_INSTANCE_TYPE_VRF;
+ } else if (!strcmp(argv[idx_view_vrf]->text,
+ "view"))
+ inst_type = BGP_INSTANCE_TYPE_VIEW;
+ }
+ }
+ if (argv_find(argv, argc, "as-notation", &idx_asnotation)) {
+ idx_asnotation_kind = idx_asnotation + 1;
+ if (strmatch(argv[idx_asnotation_kind]->text, "dot+"))
+ asnotation = ASNOTATION_DOTPLUS;
+ else if (strmatch(argv[idx_asnotation_kind]->text,
+ "dot"))
+ asnotation = ASNOTATION_DOT;
+ else if (strmatch(argv[idx_asnotation_kind]->text,
+ "plain"))
+ asnotation = ASNOTATION_PLAIN;
+ }
+
+ if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ is_new_bgp = (bgp_lookup(as, name) == NULL);
+
+ ret = bgp_get_vty(&bgp, &as, name, inst_type,
+ argv[idx_asn]->arg, asnotation);
+ switch (ret) {
+ case BGP_ERR_AS_MISMATCH:
+ vty_out(vty, "BGP is already running; AS is %s\n",
+ bgp->as_pretty);
+ return CMD_WARNING_CONFIG_FAILED;
+ case BGP_ERR_INSTANCE_MISMATCH:
+ vty_out(vty,
+ "BGP instance name and AS number mismatch\n");
+ vty_out(vty,
+ "BGP instance is already running; AS is %s\n",
+ bgp->as_pretty);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /*
+ * If we just instantiated the default instance, complete
+ * any pending VRF-VPN leaking that was configured via
+ * earlier "router bgp X vrf FOO" blocks.
+ */
+ if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ vpn_leak_postchange_all();
+
+ if (inst_type == BGP_INSTANCE_TYPE_VRF)
+ bgp_vpn_leak_export(bgp);
+ /* Pending: handle when user tries to change a view to vrf n vv.
+ */
+ /* for pre-existing bgp instance,
+ * - update as_pretty
+ * - update asnotation if explicitly mentioned
+ */
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) {
+ XFREE(MTYPE_BGP, bgp->as_pretty);
+ bgp->as_pretty = XSTRDUP(MTYPE_BGP, argv[idx_asn]->arg);
+ if (!CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION) &&
+ asnotation != ASNOTATION_UNDEFINED) {
+ SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION);
+ bgp->asnotation = asnotation;
+ }
+ }
+ }
+
+ /* unset the auto created flag as the user config is now present */
+ UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
+ VTY_PUSH_CONTEXT(BGP_NODE, bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "no router bgp" commands. */
+DEFUN (no_router_bgp,
+ no_router_bgp_cmd,
+ "no router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
+ NO_STR
+ ROUTER_STR
+ BGP_STR
+ AS_STR
+ BGP_INSTANCE_HELP_STR
+ "Force the AS notation output\n"
+ "use 'AA.BB' format for AS 4 byte values\n"
+ "use 'AA.BB' format for all AS values\n"
+ "use plain format for all AS values\n")
+{
+ int idx_asn = 3;
+ int idx_vrf = 5;
+ as_t as;
+ struct bgp *bgp;
+ const char *name = NULL;
+
+ // "no router bgp" without an ASN
+ if (argc == 3) {
+ // Pending: Make VRF option available for ASN less config
+ bgp = bgp_get_default();
+
+ if (bgp == NULL) {
+ vty_out(vty, "%% No BGP process is configured\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (listcount(bm->bgp) > 1) {
+ vty_out(vty, "%% Please specify ASN and VRF\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (bgp->l3vni) {
+ vty_out(vty, "%% Please unconfigure l3vni %u\n",
+ bgp->l3vni);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else {
+ if (!asn_str2asn(argv[idx_asn]->arg, &as)) {
+ vty_out(vty, "%% BGP: No such AS %s\n",
+ argv[idx_asn]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (argc > 4) {
+ name = argv[idx_vrf]->arg;
+ if (strmatch(argv[idx_vrf - 1]->text, "vrf")
+ && strmatch(name, VRF_DEFAULT_NAME))
+ name = NULL;
+ }
+
+ /* Lookup bgp structure. */
+ bgp = bgp_lookup(as, name);
+ if (!bgp) {
+ vty_out(vty, "%% Can't find BGP instance\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (bgp->l3vni) {
+ vty_out(vty, "%% Please unconfigure l3vni %u\n",
+ bgp->l3vni);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* Cannot delete default instance if vrf instances exist */
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ struct listnode *node;
+ struct bgp *tmp_bgp;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
+ if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+ if (CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6]
+ [SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ (bgp == bgp_get_evpn() &&
+ (CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV4_UNICAST) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV6_UNICAST) ||
+ CHECK_FLAG(
+ tmp_bgp->af_flags[AFI_L2VPN]
+ [SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) ||
+ (tmp_bgp->l3vni)) {
+ vty_out(vty,
+ "%% Cannot delete default BGP instance. Dependent VRF instances exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ }
+ }
+
+ bgp_delete(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* bgp session-dscp */
+
+DEFPY (bgp_session_dscp,
+ bgp_session_dscp_cmd,
+ "bgp session-dscp (0-63)$dscp",
+ BGP_STR
+ "Override default (C6) bgp TCP session DSCP value\n"
+ "Manually configured dscp parameter\n")
+{
+ bm->tcp_dscp = dscp << 2;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_session_dscp,
+ no_bgp_session_dscp_cmd,
+ "no bgp session-dscp [(0-63)]",
+ NO_STR
+ BGP_STR
+ "Override default (C6) bgp TCP session DSCP value\n"
+ "Manually configured dscp parameter\n")
+{
+ bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
+
+ return CMD_SUCCESS;
+}
+
+/* BGP router-id. */
+
+DEFPY (bgp_router_id,
+ bgp_router_id_cmd,
+ "bgp router-id A.B.C.D",
+ BGP_STR
+ "Override configured router identifier\n"
+ "Manually configured router identifier\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_router_id_static_set(bgp, router_id);
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_router_id,
+ no_bgp_router_id_cmd,
+ "no bgp router-id [A.B.C.D]",
+ NO_STR
+ BGP_STR
+ "Override configured router identifier\n"
+ "Manually configured router identifier\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (router_id_str) {
+ if (!IPV4_ADDR_SAME(&bgp->router_id_static, &router_id)) {
+ vty_out(vty, "%% BGP router-id doesn't match\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ router_id.s_addr = 0;
+ bgp_router_id_static_set(bgp, router_id);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_community_alias, bgp_community_alias_cmd,
+ "[no$no] bgp community alias WORD$community ALIAS_NAME$alias_name",
+ NO_STR BGP_STR
+ "Add community specific parameters\n"
+ "Create an alias for a community\n"
+ "Community (AA:BB or AA:BB:CC)\n"
+ "Alias name\n")
+{
+ struct community_alias ca = {};
+ struct community_alias *lookup_community;
+ struct community_alias *lookup_alias;
+ struct community *comm;
+ struct lcommunity *lcomm;
+ uint8_t invalid = 0;
+
+ comm = community_str2com(community);
+ if (!comm)
+ invalid++;
+ community_free(&comm);
+
+ lcomm = lcommunity_str2com(community);
+ if (!lcomm)
+ invalid++;
+ lcommunity_free(&lcomm);
+
+ if (invalid > 1) {
+ vty_out(vty, "Invalid community format\n");
+ return CMD_WARNING;
+ }
+
+ strlcpy(ca.community, community, sizeof(ca.community));
+ strlcpy(ca.alias, alias_name, sizeof(ca.alias));
+
+ lookup_community = bgp_ca_community_lookup(&ca);
+ lookup_alias = bgp_ca_alias_lookup(&ca);
+
+ if (no) {
+ bgp_ca_alias_delete(&ca);
+ bgp_ca_community_delete(&ca);
+ } else {
+ if (lookup_alias) {
+ /* Lookup if community hash table has an item
+ * with the same alias name.
+ */
+ strlcpy(ca.community, lookup_alias->community,
+ sizeof(ca.community));
+ if (bgp_ca_community_lookup(&ca)) {
+ vty_out(vty,
+ "community (%s) already has this alias (%s)\n",
+ lookup_alias->community,
+ lookup_alias->alias);
+ return CMD_WARNING;
+ }
+ bgp_ca_alias_delete(&ca);
+ }
+
+ if (lookup_community) {
+ /* Lookup if alias hash table has an item
+ * with the same community.
+ */
+ strlcpy(ca.alias, lookup_community->alias,
+ sizeof(ca.alias));
+ if (bgp_ca_alias_lookup(&ca)) {
+ vty_out(vty,
+ "alias (%s) already has this community (%s)\n",
+ lookup_community->alias,
+ lookup_community->community);
+ return CMD_WARNING;
+ }
+ bgp_ca_community_delete(&ca);
+ }
+
+ bgp_ca_alias_insert(&ca);
+ bgp_ca_community_insert(&ca);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_global_suppress_fib_pending,
+ bgp_global_suppress_fib_pending_cmd,
+ "[no] bgp suppress-fib-pending",
+ NO_STR
+ BGP_STR
+ "Advertise only routes that are programmed in kernel to peers globally\n")
+{
+ bm_wait_for_fib_set(!no);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_suppress_fib_pending,
+ bgp_suppress_fib_pending_cmd,
+ "[no] bgp suppress-fib-pending",
+ NO_STR
+ BGP_STR
+ "Advertise only routes that are programmed in kernel to peers\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_suppress_fib_pending_set(bgp, !no);
+ return CMD_SUCCESS;
+}
+
+/* BGP Cluster ID. */
+DEFUN (bgp_cluster_id,
+ bgp_cluster_id_cmd,
+ "bgp cluster-id <A.B.C.D|(1-4294967295)>",
+ BGP_STR
+ "Configure Route-Reflector Cluster-id\n"
+ "Route-Reflector Cluster-id in IP address format\n"
+ "Route-Reflector Cluster-id as 32 bit quantity\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ipv4 = 2;
+ int ret;
+ struct in_addr cluster;
+
+ ret = inet_aton(argv[idx_ipv4]->arg, &cluster);
+ if (!ret) {
+ vty_out(vty, "%% Malformed bgp cluster identifier\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_cluster_id_set(bgp, &cluster);
+ bgp_clear_star_soft_out(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_cluster_id,
+ no_bgp_cluster_id_cmd,
+ "no bgp cluster-id [<A.B.C.D|(1-4294967295)>]",
+ NO_STR
+ BGP_STR
+ "Configure Route-Reflector Cluster-id\n"
+ "Route-Reflector Cluster-id in IP address format\n"
+ "Route-Reflector Cluster-id as 32 bit quantity\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_cluster_id_unset(bgp);
+ bgp_clear_star_soft_out(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_norib,
+ bgp_norib_cmd,
+ "bgp no-rib",
+ BGP_STR
+ "Disable BGP route installation to RIB (Zebra)\n")
+{
+ if (bgp_option_check(BGP_OPT_NO_FIB)) {
+ vty_out(vty,
+ "%% No-RIB option is already set, nothing to do here.\n");
+ return CMD_SUCCESS;
+ }
+
+ bgp_option_norib_set_runtime();
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_norib,
+ no_bgp_norib_cmd,
+ "no bgp no-rib",
+ NO_STR
+ BGP_STR
+ "Disable BGP route installation to RIB (Zebra)\n")
+{
+ if (!bgp_option_check(BGP_OPT_NO_FIB)) {
+ vty_out(vty,
+ "%% No-RIB option is not set, nothing to do here.\n");
+ return CMD_SUCCESS;
+ }
+
+ bgp_option_norib_unset_runtime();
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_send_extra_data,
+ no_bgp_send_extra_data_cmd,
+ "[no] bgp send-extra-data zebra",
+ NO_STR
+ BGP_STR
+ "Extra data to Zebra for display/use\n"
+ "To zebra\n")
+{
+ if (no)
+ UNSET_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA);
+ else
+ SET_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_confederation_identifier,
+ bgp_confederation_identifier_cmd,
+ "bgp confederation identifier ASNUM",
+ BGP_STR
+ "AS confederation parameters\n"
+ "Set routing domain confederation AS\n"
+ AS_STR)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ as_t as;
+
+ if (!asn_str2asn(argv[idx_number]->arg, &as)) {
+ vty_out(vty, "%% BGP: No such AS %s\n", argv[idx_number]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_confederation_id_set(bgp, as, argv[idx_number]->arg);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_confederation_identifier,
+ no_bgp_confederation_identifier_cmd,
+ "no bgp confederation identifier [ASNUM]",
+ NO_STR
+ BGP_STR
+ "AS confederation parameters\n"
+ "Set routing domain confederation AS\n"
+ AS_STR)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_confederation_id_unset(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_confederation_peers,
+ bgp_confederation_peers_cmd,
+ "bgp confederation peers ASNUM...",
+ BGP_STR
+ "AS confederation parameters\n"
+ "Peer ASs in BGP confederation\n"
+ AS_STR)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_asn = 3;
+ as_t as;
+ int i;
+
+ for (i = idx_asn; i < argc; i++) {
+ if (!asn_str2asn(argv[i]->arg, &as)) {
+ vty_out(vty, "%% Invalid confed peer AS value: %s\n",
+ argv[i]->arg);
+ continue;
+ }
+
+ bgp_confederation_peers_add(bgp, as, argv[i]->arg);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_confederation_peers,
+ no_bgp_confederation_peers_cmd,
+ "no bgp confederation peers ASNUM...",
+ NO_STR
+ BGP_STR
+ "AS confederation parameters\n"
+ "Peer ASs in BGP confederation\n"
+ AS_STR)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_asn = 4;
+ as_t as;
+ int i;
+
+ for (i = idx_asn; i < argc; i++) {
+ if (!asn_str2asn(argv[i]->arg, &as)) {
+ vty_out(vty, "%% Invalid confed peer AS value: %s\n",
+ argv[i]->arg);
+ continue;
+ }
+ bgp_confederation_peers_remove(bgp, as);
+ }
+ return CMD_SUCCESS;
+}
+
+/**
+ * Central routine for maximum-paths configuration.
+ * @peer_type: BGP_PEER_EBGP or BGP_PEER_IBGP
+ * @set: 1 for setting values, 0 for removing the max-paths config.
+ */
+static int bgp_maxpaths_config_vty(struct vty *vty, int peer_type,
+ const char *mpaths, uint16_t options,
+ int set)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ uint16_t maxpaths = 0;
+ int ret;
+ afi_t afi;
+ safi_t safi;
+
+ afi = bgp_node_afi(vty);
+ safi = bgp_node_safi(vty);
+
+ if (set) {
+ maxpaths = strtol(mpaths, NULL, 10);
+ if (maxpaths > multipath_num) {
+ vty_out(vty,
+ "%% Maxpaths Specified: %d is > than multipath num specified on bgp command line %d",
+ maxpaths, multipath_num);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ret = bgp_maximum_paths_set(bgp, afi, safi, peer_type, maxpaths,
+ options);
+ } else
+ ret = bgp_maximum_paths_unset(bgp, afi, safi, peer_type);
+
+ if (ret < 0) {
+ vty_out(vty,
+ "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u\n",
+ (set == 1) ? "" : "un",
+ (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp",
+ maxpaths, afi, safi);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_admin,
+ bgp_maxmed_admin_cmd,
+ "bgp max-med administrative ",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->v_maxmed_admin = 1;
+ bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_admin_medv,
+ bgp_maxmed_admin_medv_cmd,
+ "bgp max-med administrative (0-4294967295)",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n"
+ "Max MED value to be used\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+
+ bgp->v_maxmed_admin = 1;
+ bgp->maxmed_admin_value = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_admin,
+ no_bgp_maxmed_admin_cmd,
+ "no bgp max-med administrative [(0-4294967295)]",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Administratively applied, for an indefinite period\n"
+ "Max MED value to be used\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED;
+ bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_onstartup,
+ bgp_maxmed_onstartup_cmd,
+ "bgp max-med on-startup (5-86400) [(0-4294967295)]",
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n"
+ "Max MED value to be used\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(5-86400)", &idx))
+ bgp->v_maxmed_onstartup = strtoul(argv[idx]->arg, NULL, 10);
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ bgp->maxmed_onstartup_value = strtoul(argv[idx]->arg, NULL, 10);
+ else
+ bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_onstartup,
+ no_bgp_maxmed_onstartup_cmd,
+ "no bgp max-med on-startup [(5-86400) [(0-4294967295)]]",
+ NO_STR
+ BGP_STR
+ "Advertise routes with max-med\n"
+ "Effective on a startup\n"
+ "Time (seconds) period for max-med\n"
+ "Max MED value to be used\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* Cancel max-med onstartup if its on */
+ if (bgp->t_maxmed_onstartup) {
+ EVENT_OFF(bgp->t_maxmed_onstartup);
+ bgp->maxmed_onstartup_over = 1;
+ }
+
+ bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED;
+ bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+ bgp_maxmed_update(bgp);
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_global_update_delay_config_vty(struct vty *vty,
+ uint16_t update_delay,
+ uint16_t establish_wait)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ bool vrf_cfg = false;
+
+ /*
+ * See if update-delay is set per-vrf and warn user to delete it
+ * Note that we only need to check this if this is the first time
+ * setting the global config.
+ */
+ if (bm->v_update_delay == BGP_UPDATE_DELAY_DEF) {
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
+ vty_out(vty,
+ "%% update-delay configuration found in vrf %s\n",
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+ vrf_cfg = true;
+ }
+ }
+ }
+
+ if (vrf_cfg) {
+ vty_out(vty,
+ "%%Failed: global update-delay config not permitted\n");
+ return CMD_WARNING;
+ }
+
+ if (!establish_wait) { /* update-delay <delay> */
+ bm->v_update_delay = update_delay;
+ bm->v_establish_wait = bm->v_update_delay;
+ } else {
+ /* update-delay <delay> <establish-wait> */
+ if (update_delay < establish_wait) {
+ vty_out(vty,
+ "%%Failed: update-delay less than the establish-wait!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bm->v_update_delay = update_delay;
+ bm->v_establish_wait = establish_wait;
+ }
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->v_update_delay = bm->v_update_delay;
+ bgp->v_establish_wait = bm->v_establish_wait;
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_global_update_delay_deconfig_vty(struct vty *vty)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
+ bm->v_establish_wait = bm->v_update_delay;
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ bgp->v_update_delay = bm->v_update_delay;
+ bgp->v_establish_wait = bm->v_establish_wait;
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_update_delay_config_vty(struct vty *vty, uint16_t update_delay,
+ uint16_t establish_wait)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* if configured globally, per-instance config is not allowed */
+ if (bm->v_update_delay) {
+ vty_out(vty,
+ "%%Failed: per-vrf update-delay config not permitted with global update-delay\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+
+ if (!establish_wait) /* update-delay <delay> */
+ {
+ bgp->v_update_delay = update_delay;
+ bgp->v_establish_wait = bgp->v_update_delay;
+ return CMD_SUCCESS;
+ }
+
+ /* update-delay <delay> <establish-wait> */
+ if (update_delay < establish_wait) {
+ vty_out(vty,
+ "%%Failed: update-delay less than the establish-wait!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp->v_update_delay = update_delay;
+ bgp->v_establish_wait = establish_wait;
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_update_delay_deconfig_vty(struct vty *vty)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* If configured globally, cannot remove from one bgp instance */
+ if (bm->v_update_delay) {
+ vty_out(vty,
+ "%%Failed: bgp update-delay configured globally. Delete per-vrf not permitted\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
+ bgp->v_establish_wait = bgp->v_update_delay;
+
+ return CMD_SUCCESS;
+}
+
+void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
+{
+ /* If configured globally, no need to display per-instance value */
+ if (bgp->v_update_delay != bm->v_update_delay) {
+ vty_out(vty, " update-delay %d", bgp->v_update_delay);
+ if (bgp->v_update_delay != bgp->v_establish_wait)
+ vty_out(vty, " %d", bgp->v_establish_wait);
+ vty_out(vty, "\n");
+ }
+}
+
+/* Global update-delay configuration */
+DEFPY (bgp_global_update_delay,
+ bgp_global_update_delay_cmd,
+ "bgp update-delay (0-3600)$delay [(1-3600)$wait]",
+ BGP_STR
+ "Force initial delay for best-path and updates for all bgp instances\n"
+ "Max delay in seconds\n"
+ "Establish wait in seconds\n")
+{
+ return bgp_global_update_delay_config_vty(vty, delay, wait);
+}
+
+/* Global update-delay deconfiguration */
+DEFPY (no_bgp_global_update_delay,
+ no_bgp_global_update_delay_cmd,
+ "no bgp update-delay [(0-3600) [(1-3600)]]",
+ NO_STR
+ BGP_STR
+ "Force initial delay for best-path and updates\n"
+ "Max delay in seconds\n"
+ "Establish wait in seconds\n")
+{
+ return bgp_global_update_delay_deconfig_vty(vty);
+}
+
+/* Update-delay configuration */
+
+DEFPY (bgp_update_delay,
+ bgp_update_delay_cmd,
+ "update-delay (0-3600)$delay [(1-3600)$wait]",
+ "Force initial delay for best-path and updates\n"
+ "Max delay in seconds\n"
+ "Establish wait in seconds\n")
+{
+ return bgp_update_delay_config_vty(vty, delay, wait);
+}
+
+/* Update-delay deconfiguration */
+DEFPY (no_bgp_update_delay,
+ no_bgp_update_delay_cmd,
+ "no update-delay [(0-3600) [(1-3600)]]",
+ NO_STR
+ "Force initial delay for best-path and updates\n"
+ "Max delay in seconds\n"
+ "Establish wait in seconds\n")
+{
+ return bgp_update_delay_deconfig_vty(vty);
+}
+
+
+static int bgp_wpkt_quanta_config_vty(struct vty *vty, uint32_t quanta,
+ bool set)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ quanta = set ? quanta : BGP_WRITE_PACKET_MAX;
+ atomic_store_explicit(&bgp->wpkt_quanta, quanta, memory_order_relaxed);
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_rpkt_quanta_config_vty(struct vty *vty, uint32_t quanta,
+ bool set)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ quanta = set ? quanta : BGP_READ_PACKET_MAX;
+ atomic_store_explicit(&bgp->rpkt_quanta, quanta, memory_order_relaxed);
+
+ return CMD_SUCCESS;
+}
+
+void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
+{
+ uint32_t quanta =
+ atomic_load_explicit(&bgp->wpkt_quanta, memory_order_relaxed);
+ if (quanta != BGP_WRITE_PACKET_MAX)
+ vty_out(vty, " write-quanta %d\n", quanta);
+}
+
+void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp)
+{
+ uint32_t quanta =
+ atomic_load_explicit(&bgp->rpkt_quanta, memory_order_relaxed);
+ if (quanta != BGP_READ_PACKET_MAX)
+ vty_out(vty, " read-quanta %d\n", quanta);
+}
+
+/* Packet quanta configuration
+ *
+ * XXX: The value set here controls the size of a stack buffer in the IO
+ * thread. When changing these limits be careful to prevent stack overflow.
+ *
+ * Furthermore, the maximums used here should correspond to
+ * BGP_WRITE_PACKET_MAX and BGP_READ_PACKET_MAX.
+ */
+DEFPY (bgp_wpkt_quanta,
+ bgp_wpkt_quanta_cmd,
+ "[no] write-quanta (1-64)$quanta",
+ NO_STR
+ "How many packets to write to peer socket per run\n"
+ "Number of packets\n")
+{
+ return bgp_wpkt_quanta_config_vty(vty, quanta, !no);
+}
+
+DEFPY (bgp_rpkt_quanta,
+ bgp_rpkt_quanta_cmd,
+ "[no] read-quanta (1-10)$quanta",
+ NO_STR
+ "How many packets to read from peer socket per I/O cycle\n"
+ "Number of packets\n")
+{
+ return bgp_rpkt_quanta_config_vty(vty, quanta, !no);
+}
+
+void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
+{
+ if (!bgp->heuristic_coalesce)
+ vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
+}
+
+/* BGP TCP keepalive */
+static void bgp_config_tcp_keepalive(struct vty *vty, struct bgp *bgp)
+{
+ if (bgp->tcp_keepalive_idle) {
+ vty_out(vty, " bgp tcp-keepalive %u %u %u\n",
+ bgp->tcp_keepalive_idle, bgp->tcp_keepalive_intvl,
+ bgp->tcp_keepalive_probes);
+ }
+}
+
+DEFUN (bgp_coalesce_time,
+ bgp_coalesce_time_cmd,
+ "coalesce-time (0-4294967295)",
+ "Subgroup coalesce timer\n"
+ "Subgroup coalesce timer value (in ms)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ int idx = 0;
+
+ bgp->heuristic_coalesce = false;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_coalesce_time,
+ no_bgp_coalesce_time_cmd,
+ "no coalesce-time (0-4294967295)",
+ NO_STR
+ "Subgroup coalesce timer\n"
+ "Subgroup coalesce timer value (in ms)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->heuristic_coalesce = true;
+ bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
+ return CMD_SUCCESS;
+}
+
+/* Maximum-paths configuration */
+DEFUN (bgp_maxpaths,
+ bgp_maxpaths_cmd,
+ "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ int idx_number = 1;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP,
+ argv[idx_number]->arg, 0, 1);
+}
+
+ALIAS_HIDDEN(bgp_maxpaths, bgp_maxpaths_hidden_cmd,
+ "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+
+DEFUN (bgp_maxpaths_ibgp,
+ bgp_maxpaths_ibgp_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n")
+{
+ int idx_number = 2;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP,
+ argv[idx_number]->arg, 0, 1);
+}
+
+ALIAS_HIDDEN(bgp_maxpaths_ibgp, bgp_maxpaths_ibgp_hidden_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM),
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n")
+
+DEFUN (bgp_maxpaths_ibgp_cluster,
+ bgp_maxpaths_ibgp_cluster_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM) " equal-cluster-length",
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+{
+ int idx_number = 2;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP,
+ argv[idx_number]->arg, true, 1);
+}
+
+ALIAS_HIDDEN(bgp_maxpaths_ibgp_cluster, bgp_maxpaths_ibgp_cluster_hidden_cmd,
+ "maximum-paths ibgp " CMD_RANGE_STR(
+ 1, MULTIPATH_NUM) " equal-cluster-length",
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+
+DEFUN (no_bgp_maxpaths,
+ no_bgp_maxpaths_cmd,
+ "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0);
+}
+
+ALIAS_HIDDEN(no_bgp_maxpaths, no_bgp_maxpaths_hidden_cmd,
+ "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", NO_STR
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+
+DEFUN (no_bgp_maxpaths_ibgp,
+ no_bgp_maxpaths_ibgp_cmd,
+ "no maximum-paths ibgp [" CMD_RANGE_STR(1, MULTIPATH_NUM) " [equal-cluster-length]]",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0);
+}
+
+ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd,
+ "no maximum-paths ibgp [" CMD_RANGE_STR(
+ 1, MULTIPATH_NUM) " [equal-cluster-length]]",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+
+static void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp,
+ afi_t afi, safi_t safi)
+{
+ if (bgp->maxpaths[afi][safi].maxpaths_ebgp != multipath_num) {
+ vty_out(vty, " maximum-paths %d\n",
+ bgp->maxpaths[afi][safi].maxpaths_ebgp);
+ }
+
+ if (bgp->maxpaths[afi][safi].maxpaths_ibgp != multipath_num) {
+ vty_out(vty, " maximum-paths ibgp %d",
+ bgp->maxpaths[afi][safi].maxpaths_ibgp);
+ if (bgp->maxpaths[afi][safi].same_clusterlen)
+ vty_out(vty, " equal-cluster-length");
+ vty_out(vty, "\n");
+ }
+}
+
+/* BGP timers. */
+
+DEFUN (bgp_timers,
+ bgp_timers_cmd,
+ "timers bgp (0-65535) (0-65535)",
+ "Adjust routing timers\n"
+ "BGP timers\n"
+ "Keepalive interval\n"
+ "Holdtime\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 2;
+ int idx_number_2 = 3;
+ unsigned long keepalive = 0;
+ unsigned long holdtime = 0;
+
+ keepalive = strtoul(argv[idx_number]->arg, NULL, 10);
+ holdtime = strtoul(argv[idx_number_2]->arg, NULL, 10);
+
+ /* Holdtime value check. */
+ if (holdtime < 3 && holdtime != 0) {
+ vty_out(vty,
+ "%% hold time value must be either 0 or greater than 3\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_timers_set(vty, bgp, keepalive, holdtime, DFLT_BGP_CONNECT_RETRY,
+ BGP_DEFAULT_DELAYOPEN);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_timers,
+ no_bgp_timers_cmd,
+ "no timers bgp [(0-65535) (0-65535)]",
+ NO_STR
+ "Adjust routing timers\n"
+ "BGP timers\n"
+ "Keepalive interval\n"
+ "Holdtime\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_timers_set(vty, bgp, DFLT_BGP_KEEPALIVE, DFLT_BGP_HOLDTIME,
+ DFLT_BGP_CONNECT_RETRY, BGP_DEFAULT_DELAYOPEN);
+
+ return CMD_SUCCESS;
+}
+
+/* BGP minimum holdtime. */
+
+DEFUN(bgp_minimum_holdtime, bgp_minimum_holdtime_cmd,
+ "bgp minimum-holdtime (1-65535)",
+ "BGP specific commands\n"
+ "BGP minimum holdtime\n"
+ "Seconds\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 2;
+ unsigned long min_holdtime;
+
+ min_holdtime = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ bgp->default_min_holdtime = min_holdtime;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_minimum_holdtime, no_bgp_minimum_holdtime_cmd,
+ "no bgp minimum-holdtime [(1-65535)]",
+ NO_STR
+ "BGP specific commands\n"
+ "BGP minimum holdtime\n"
+ "Seconds\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->default_min_holdtime = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_tcp_keepalive, bgp_tcp_keepalive_cmd,
+ "bgp tcp-keepalive (1-65535)$idle (1-65535)$intvl (1-30)$probes",
+ BGP_STR
+ "TCP keepalive parameters\n"
+ "TCP keepalive idle time (seconds)\n"
+ "TCP keepalive interval (seconds)\n"
+ "TCP keepalive maximum probes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_tcp_keepalive_set(bgp, (uint16_t)idle, (uint16_t)intvl,
+ (uint16_t)probes);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_bgp_tcp_keepalive, no_bgp_tcp_keepalive_cmd,
+ "no bgp tcp-keepalive [(1-65535) (1-65535) (1-30)]",
+ NO_STR
+ BGP_STR
+ "TCP keepalive parameters\n"
+ "TCP keepalive idle time (seconds)\n"
+ "TCP keepalive interval (seconds)\n"
+ "TCP keepalive maximum probes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_tcp_keepalive_unset(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_client_to_client_reflection,
+ bgp_client_to_client_reflection_cmd,
+ "bgp client-to-client reflection",
+ BGP_STR
+ "Configure client to client route reflection\n"
+ "reflection of routes allowed\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT);
+ bgp_clear_star_soft_out(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_client_to_client_reflection,
+ no_bgp_client_to_client_reflection_cmd,
+ "no bgp client-to-client reflection",
+ NO_STR
+ BGP_STR
+ "Configure client to client route reflection\n"
+ "reflection of routes allowed\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT);
+ bgp_clear_star_soft_out(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp always-compare-med" configuration. */
+DEFUN (bgp_always_compare_med,
+ bgp_always_compare_med_cmd,
+ "bgp always-compare-med",
+ BGP_STR
+ "Allow comparing MED from different neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_always_compare_med,
+ no_bgp_always_compare_med_cmd,
+ "no bgp always-compare-med",
+ NO_STR
+ BGP_STR
+ "Allow comparing MED from different neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+
+DEFUN(bgp_ebgp_requires_policy, bgp_ebgp_requires_policy_cmd,
+ "bgp ebgp-requires-policy",
+ BGP_STR
+ "Require in and out policy for eBGP peers (RFC8212)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
+ "no bgp ebgp-requires-policy",
+ NO_STR
+ BGP_STR
+ "Require in and out policy for eBGP peers (RFC8212)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY);
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd,
+ "[no] bgp labeled-unicast <explicit-null|ipv4-explicit-null|ipv6-explicit-null>$value",
+ NO_STR BGP_STR
+ "BGP Labeled-unicast options\n"
+ "Use explicit-null label values for all local prefixes\n"
+ "Use the IPv4 explicit-null label value for IPv4 local prefixes\n"
+ "Use the IPv6 explicit-null label value for IPv6 local prefixes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ uint64_t label_mode;
+
+ if (strmatch(value, "ipv4-explicit-null"))
+ label_mode = BGP_FLAG_LU_IPV4_EXPLICIT_NULL;
+ else if (strmatch(value, "ipv6-explicit-null"))
+ label_mode = BGP_FLAG_LU_IPV6_EXPLICIT_NULL;
+ else
+ label_mode = BGP_FLAG_LU_IPV4_EXPLICIT_NULL |
+ BGP_FLAG_LU_IPV6_EXPLICIT_NULL;
+ if (no)
+ UNSET_FLAG(bgp->flags, label_mode);
+ else
+ SET_FLAG(bgp->flags, label_mode);
+ return CMD_SUCCESS;
+}
+
+DEFUN(bgp_suppress_duplicates, bgp_suppress_duplicates_cmd,
+ "bgp suppress-duplicates",
+ BGP_STR
+ "Suppress duplicate updates if the route actually not changed\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES);
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_suppress_duplicates, no_bgp_suppress_duplicates_cmd,
+ "no bgp suppress-duplicates",
+ NO_STR
+ BGP_STR
+ "Suppress duplicate updates if the route actually not changed\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES);
+ return CMD_SUCCESS;
+}
+
+DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd,
+ "bgp reject-as-sets",
+ BGP_STR
+ "Reject routes with AS_SET or AS_CONFED_SET flag\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ bgp->reject_as_sets = true;
+
+ /* Reset existing BGP sessions to reject routes
+ * with aspath containing AS_SET or AS_CONFED_SET.
+ */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
+ peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd,
+ "no bgp reject-as-sets",
+ NO_STR
+ BGP_STR
+ "Reject routes with AS_SET or AS_CONFED_SET flag\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ bgp->reject_as_sets = false;
+
+ /* Reset existing BGP sessions to reject routes
+ * with aspath containing AS_SET or AS_CONFED_SET.
+ */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
+ peer->last_reset = PEER_DOWN_AS_SETS_REJECT;
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp deterministic-med" configuration. */
+DEFUN (bgp_deterministic_med,
+ bgp_deterministic_med_cmd,
+ "bgp deterministic-med",
+ BGP_STR
+ "Pick the best-MED path among paths advertised from the neighboring AS\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (!CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
+ SET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED);
+ bgp_recalculate_all_bestpaths(bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_deterministic_med,
+ no_bgp_deterministic_med_cmd,
+ "no bgp deterministic-med",
+ NO_STR
+ BGP_STR
+ "Pick the best-MED path among paths advertised from the neighboring AS\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int bestpath_per_as_used;
+ afi_t afi;
+ safi_t safi;
+ struct peer *peer;
+ struct listnode *node, *nnode;
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
+ bestpath_per_as_used = 0;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ FOREACH_AFI_SAFI (afi, safi)
+ if (bgp_addpath_dmed_required(
+ peer->addpath_type[afi][safi])) {
+ bestpath_per_as_used = 1;
+ break;
+ }
+
+ if (bestpath_per_as_used)
+ break;
+ }
+
+ if (bestpath_per_as_used) {
+ vty_out(vty,
+ "bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ } else {
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED);
+ bgp_recalculate_all_bestpaths(bgp);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp graceful-restart mode" configuration. */
+DEFUN (bgp_graceful_restart,
+ bgp_graceful_restart_cmd,
+ "bgp graceful-restart",
+ BGP_STR
+ GR_CMD
+ )
+{
+ int ret = BGP_GR_FAILURE;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : START ");
+
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
+ ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_graceful_restart,
+ no_bgp_graceful_restart_cmd,
+ "no bgp graceful-restart",
+ NO_STR
+ BGP_STR
+ NO_GR_CMD
+ )
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : START ");
+
+ int ret = BGP_GR_FAILURE;
+
+ ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
+ ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (bgp_graceful_restart_stalepath_time,
+ bgp_graceful_restart_stalepath_time_cmd,
+ "bgp graceful-restart stalepath-time (1-4095)",
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the max time to hold onto restarting peer's stale paths\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t stalepath;
+
+ stalepath = strtoul(argv[idx_number]->arg, NULL, 10);
+ bgp->stalepath_time = stalepath;
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_graceful_restart_restart_time,
+ bgp_graceful_restart_restart_time_cmd,
+ "bgp graceful-restart restart-time (0-4095)",
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the time to wait to delete stale routes before a BGP open message is received\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t restart;
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ restart = strtoul(argv[idx_number]->arg, NULL, 10);
+ bgp->restart_time = restart;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_SET);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_graceful_restart_select_defer_time,
+ bgp_graceful_restart_select_defer_time_cmd,
+ "bgp graceful-restart select-defer-time (0-3600)",
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the time to defer the BGP route selection after restart\n"
+ "Delay value (seconds, 0 - disable)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t defer_time;
+
+ defer_time = strtoul(argv[idx_number]->arg, NULL, 10);
+ bgp->select_defer_time = defer_time;
+ if (defer_time == 0)
+ SET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+ else
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_stalepath_time,
+ no_bgp_graceful_restart_stalepath_time_cmd,
+ "no bgp graceful-restart stalepath-time [(1-4095)]",
+ NO_STR
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the max time to hold onto restarting peer's stale paths\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_restart_time,
+ no_bgp_graceful_restart_restart_time_cmd,
+ "no bgp graceful-restart restart-time [(0-4095)]",
+ NO_STR
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the time to wait to delete stale routes before a BGP open message is received\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_select_defer_time,
+ no_bgp_graceful_restart_select_defer_time_cmd,
+ "no bgp graceful-restart select-defer-time [(0-3600)]",
+ NO_STR
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Set the time to defer the BGP route selection after restart\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_graceful_restart_preserve_fw,
+ bgp_graceful_restart_preserve_fw_cmd,
+ "bgp graceful-restart preserve-fw-state",
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Sets F-bit indication that fib is preserved while doing Graceful Restart\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_preserve_fw,
+ no_bgp_graceful_restart_preserve_fw_cmd,
+ "no bgp graceful-restart preserve-fw-state",
+ NO_STR
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Unsets F-bit indication that fib is preserved while doing Graceful Restart\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD);
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_graceful_restart_notification,
+ bgp_graceful_restart_notification_cmd,
+ "[no$no] bgp graceful-restart notification",
+ NO_STR
+ BGP_STR
+ "Graceful restart capability parameters\n"
+ "Indicate Graceful Restart support for BGP NOTIFICATION messages\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION);
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_SET);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_administrative_reset,
+ bgp_administrative_reset_cmd,
+ "[no$no] bgp hard-administrative-reset",
+ NO_STR
+ BGP_STR
+ "Send Hard Reset CEASE Notification for 'Administrative Reset'\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_graceful_restart_disable,
+ bgp_graceful_restart_disable_cmd,
+ "bgp graceful-restart-disable",
+ BGP_STR
+ GR_DISABLE)
+{
+ int ret = BGP_GR_FAILURE;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_graceful_restart_disable_cmd : START ");
+
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_graceful_restart_disable,
+ no_bgp_graceful_restart_disable_cmd,
+ "no bgp graceful-restart-disable",
+ NO_STR
+ BGP_STR
+ NO_GR_DISABLE
+ )
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_graceful_restart_disable_cmd : START ");
+
+ int ret = BGP_GR_FAILURE;
+
+ ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
+ ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_graceful_restart_disable_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (bgp_neighbor_graceful_restart_set,
+ bgp_neighbor_graceful_restart_set_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ GR_NEIGHBOR_CMD
+ )
+{
+ int idx_peer = 1;
+ struct peer *peer;
+ int ret = BGP_GR_FAILURE;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : START ");
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_neighbor_graceful_restart,
+ no_bgp_neighbor_graceful_restart_set_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ NO_GR_NEIGHBOR_CMD
+ )
+{
+ int idx_peer = 2;
+ int ret = BGP_GR_FAILURE;
+ struct peer *peer;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START ");
+
+ ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (bgp_neighbor_graceful_restart_helper_set,
+ bgp_neighbor_graceful_restart_helper_set_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart-helper",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ GR_NEIGHBOR_HELPER_CMD
+ )
+{
+ int idx_peer = 1;
+ struct peer *peer;
+ int ret = BGP_GR_FAILURE;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : START ");
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+
+ ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_neighbor_graceful_restart_helper,
+ no_bgp_neighbor_graceful_restart_helper_set_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart-helper",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ NO_GR_NEIGHBOR_HELPER_CMD
+ )
+{
+ int idx_peer = 2;
+ int ret = BGP_GR_FAILURE;
+ struct peer *peer;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START ");
+
+ ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (bgp_neighbor_graceful_restart_disable_set,
+ bgp_neighbor_graceful_restart_disable_set_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart-disable",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ GR_NEIGHBOR_DISABLE_CMD
+ )
+{
+ int idx_peer = 1;
+ struct peer *peer;
+ int ret = BGP_GR_FAILURE;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] bgp_neighbor_graceful_restart_disable_set_cmd : START ");
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
+
+ if (peer->bgp->t_startup)
+ bgp_peer_gr_flags_update(peer);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_neighbor_graceful_restart_disable,
+ no_bgp_neighbor_graceful_restart_disable_set_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> graceful-restart-disable",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ NO_GR_NEIGHBOR_DISABLE_CMD
+ )
+{
+ int idx_peer = 2;
+ int ret = BGP_GR_FAILURE;
+ struct peer *peer;
+
+ VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START ");
+
+ ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
+
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+
+ if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
+ zlog_debug(
+ "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END ");
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFPY (neighbor_graceful_shutdown,
+ neighbor_graceful_shutdown_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor graceful-shutdown",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Graceful shutdown\n")
+{
+ afi_t afi;
+ safi_t safi;
+ struct peer *peer;
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ ret = peer_flag_unset_vty(vty, neighbor,
+ PEER_FLAG_GRACEFUL_SHUTDOWN);
+ else
+ ret = peer_flag_set_vty(vty, neighbor,
+ PEER_FLAG_GRACEFUL_SHUTDOWN);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_clear(vty, bgp, afi, safi, clear_peer, BGP_CLEAR_SOFT_IN,
+ neighbor);
+ }
+
+ return ret;
+}
+
+DEFUN_HIDDEN (bgp_graceful_restart_disable_eor,
+ bgp_graceful_restart_disable_eor_cmd,
+ "bgp graceful-restart disable-eor",
+ BGP_STR
+ "Graceful restart configuration parameters\n"
+ "Disable EOR Check\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_GR_DISABLE_EOR);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (no_bgp_graceful_restart_disable_eor,
+ no_bgp_graceful_restart_disable_eor_cmd,
+ "no bgp graceful-restart disable-eor",
+ NO_STR
+ BGP_STR
+ "Graceful restart configuration parameters\n"
+ "Disable EOR Check\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GR_DISABLE_EOR);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_graceful_restart_rib_stale_time,
+ bgp_graceful_restart_rib_stale_time_cmd,
+ "bgp graceful-restart rib-stale-time (1-3600)",
+ BGP_STR
+ "Graceful restart configuration parameters\n"
+ "Specify the stale route removal timer in rib\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t stale_time;
+
+ stale_time = strtoul(argv[idx_number]->arg, NULL, 10);
+ bgp->rib_stale_time = stale_time;
+ /* Send the stale timer update message to RIB */
+ if (bgp_zebra_stale_timer_update(bgp))
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_restart_rib_stale_time,
+ no_bgp_graceful_restart_rib_stale_time_cmd,
+ "no bgp graceful-restart rib-stale-time [(1-3600)]",
+ NO_STR
+ BGP_STR
+ "Graceful restart configuration parameters\n"
+ "Specify the stale route removal timer in rib\n"
+ "Delay value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->rib_stale_time = BGP_DEFAULT_RIB_STALE_TIME;
+ /* Send the stale timer update message to RIB */
+ if (bgp_zebra_stale_timer_update(bgp))
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(bgp_llgr_stalepath_time, bgp_llgr_stalepath_time_cmd,
+ "bgp long-lived-graceful-restart stale-time (1-16777215)",
+ BGP_STR
+ "Enable Long-lived Graceful Restart\n"
+ "Specifies maximum time to wait before purging long-lived stale routes\n"
+ "Stale time value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ uint32_t llgr_stale_time;
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ llgr_stale_time = strtoul(argv[3]->arg, NULL, 10);
+ bgp->llgr_stale_time = llgr_stale_time;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR, CAPABILITY_ACTION_SET);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_llgr_stalepath_time, no_bgp_llgr_stalepath_time_cmd,
+ "no bgp long-lived-graceful-restart stale-time [(1-16777215)]",
+ NO_STR BGP_STR
+ "Enable Long-lived Graceful Restart\n"
+ "Specifies maximum time to wait before purging long-lived stale routes\n"
+ "Stale time value (seconds)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node, *nnode;
+ struct peer *peer;
+
+ bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR,
+ CAPABILITY_ACTION_UNSET);
+
+ return CMD_SUCCESS;
+}
+
+static inline void bgp_initiate_graceful_shut_unshut(struct vty *vty,
+ struct bgp *bgp)
+{
+ bgp_static_redo_import_check(bgp);
+ bgp_redistribute_redo(bgp);
+ bgp_clear_star_soft_out(vty, bgp->name);
+ bgp_clear_star_soft_in(vty, bgp->name);
+}
+
+static int bgp_global_graceful_shutdown_config_vty(struct vty *vty)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ bool vrf_cfg = false;
+
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+ return CMD_SUCCESS;
+
+ /* See if graceful-shutdown is set per-vrf and warn user to delete */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ vty_out(vty,
+ "%% graceful-shutdown configuration found in vrf %s\n",
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ?
+ VRF_DEFAULT_NAME : bgp->name);
+ vrf_cfg = true;
+ }
+ }
+
+ if (vrf_cfg) {
+ vty_out(vty,
+ "%%Failed: global graceful-shutdown not permitted\n");
+ return CMD_WARNING;
+ }
+
+ /* Set flag globally */
+ SET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);
+
+ /* Initiate processing for all BGP instances. */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ bgp_initiate_graceful_shut_unshut(vty, bgp);
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_global_graceful_shutdown_deconfig_vty(struct vty *vty)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+ return CMD_SUCCESS;
+
+ /* Unset flag globally */
+ UNSET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);
+
+ /* Initiate processing for all BGP instances. */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ bgp_initiate_graceful_shut_unshut(vty, bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp graceful-shutdown" configuration */
+DEFUN (bgp_graceful_shutdown,
+ bgp_graceful_shutdown_cmd,
+ "bgp graceful-shutdown",
+ BGP_STR
+ "Graceful shutdown parameters\n")
+{
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_graceful_shutdown_config_vty(vty);
+
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* if configured globally, per-instance config is not allowed */
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) {
+ vty_out(vty,
+ "%%Failed: per-vrf graceful-shutdown config not permitted with global graceful-shutdown\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ SET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN);
+ bgp_initiate_graceful_shut_unshut(vty, bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_graceful_shutdown,
+ no_bgp_graceful_shutdown_cmd,
+ "no bgp graceful-shutdown",
+ NO_STR
+ BGP_STR
+ "Graceful shutdown parameters\n")
+{
+ if (vty->node == CONFIG_NODE)
+ return bgp_global_graceful_shutdown_deconfig_vty(vty);
+
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* If configured globally, cannot remove from one bgp instance */
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) {
+ vty_out(vty,
+ "%%Failed: bgp graceful-shutdown configured globally. Delete per-vrf not permitted\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ UNSET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN);
+ bgp_initiate_graceful_shut_unshut(vty, bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp fast-external-failover" configuration. */
+DEFUN (bgp_fast_external_failover,
+ bgp_fast_external_failover_cmd,
+ "bgp fast-external-failover",
+ BGP_STR
+ "Immediately reset session if a link to a directly connected external peer goes down\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_fast_external_failover,
+ no_bgp_fast_external_failover_cmd,
+ "no bgp fast-external-failover",
+ NO_STR
+ BGP_STR
+ "Immediately reset session if a link to a directly connected external peer goes down\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER);
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_bestpath_aigp,
+ bgp_bestpath_aigp_cmd,
+ "[no$no] bgp bestpath aigp",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Evaluate the AIGP attribute during the best path selection process\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP);
+
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath compare-routerid" configuration. */
+DEFUN (bgp_bestpath_compare_router_id,
+ bgp_bestpath_compare_router_id_cmd,
+ "bgp bestpath compare-routerid",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Compare router-id for identical EBGP paths\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_compare_router_id,
+ no_bgp_bestpath_compare_router_id_cmd,
+ "no bgp bestpath compare-routerid",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Compare router-id for identical EBGP paths\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath as-path ignore" configuration. */
+DEFUN (bgp_bestpath_aspath_ignore,
+ bgp_bestpath_aspath_ignore_cmd,
+ "bgp bestpath as-path ignore",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Ignore as-path length in selecting a route\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_aspath_ignore,
+ no_bgp_bestpath_aspath_ignore_cmd,
+ "no bgp bestpath as-path ignore",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Ignore as-path length in selecting a route\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath as-path confed" configuration. */
+DEFUN (bgp_bestpath_aspath_confed,
+ bgp_bestpath_aspath_confed_cmd,
+ "bgp bestpath as-path confed",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Compare path lengths including confederation sets & sequences in selecting a route\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_aspath_confed,
+ no_bgp_bestpath_aspath_confed_cmd,
+ "no bgp bestpath as-path confed",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Compare path lengths including confederation sets & sequences in selecting a route\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath as-path multipath-relax" configuration. */
+DEFUN (bgp_bestpath_aspath_multipath_relax,
+ bgp_bestpath_aspath_multipath_relax_cmd,
+ "bgp bestpath as-path multipath-relax [<as-set|no-as-set>]",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Allow load sharing across routes that have different AS paths (but same length)\n"
+ "Generate an AS_SET\n"
+ "Do not generate an AS_SET\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx = 0;
+ SET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX);
+
+ /* no-as-set is now the default behavior so we can silently
+ * ignore it */
+ if (argv_find(argv, argc, "as-set", &idx))
+ SET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET);
+ else
+ UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET);
+
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_aspath_multipath_relax,
+ no_bgp_bestpath_aspath_multipath_relax_cmd,
+ "no bgp bestpath as-path multipath-relax [<as-set|no-as-set>]",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "AS-path attribute\n"
+ "Allow load sharing across routes that have different AS paths (but same length)\n"
+ "Generate an AS_SET\n"
+ "Do not generate an AS_SET\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath peer-type multipath-relax" configuration. */
+DEFUN(bgp_bestpath_peer_type_multipath_relax,
+ bgp_bestpath_peer_type_multipath_relax_cmd,
+ "bgp bestpath peer-type multipath-relax",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Peer type\n"
+ "Allow load sharing across routes learned from different peer types\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_bestpath_peer_type_multipath_relax,
+ no_bgp_bestpath_peer_type_multipath_relax_cmd,
+ "no bgp bestpath peer-type multipath-relax",
+ NO_STR BGP_STR
+ "Change the default bestpath selection\n"
+ "Peer type\n"
+ "Allow load sharing across routes learned from different peer types\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX);
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp log-neighbor-changes" configuration. */
+DEFUN (bgp_log_neighbor_changes,
+ bgp_log_neighbor_changes_cmd,
+ "bgp log-neighbor-changes",
+ BGP_STR
+ "Log neighbor up/down and reset reason\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_log_neighbor_changes,
+ no_bgp_log_neighbor_changes_cmd,
+ "no bgp log-neighbor-changes",
+ NO_STR
+ BGP_STR
+ "Log neighbor up/down and reset reason\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath med" configuration. */
+DEFUN (bgp_bestpath_med,
+ bgp_bestpath_med_cmd,
+ "bgp bestpath med <confed [missing-as-worst]|missing-as-worst [confed]>",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "MED attribute\n"
+ "Compare MED among confederation paths\n"
+ "Treat missing MED as the least preferred one\n"
+ "Treat missing MED as the least preferred one\n"
+ "Compare MED among confederation paths\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ int idx = 0;
+ if (argv_find(argv, argc, "confed", &idx))
+ SET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED);
+ idx = 0;
+ if (argv_find(argv, argc, "missing-as-worst", &idx))
+ SET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST);
+
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_med,
+ no_bgp_bestpath_med_cmd,
+ "no bgp bestpath med <confed [missing-as-worst]|missing-as-worst [confed]>",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "MED attribute\n"
+ "Compare MED among confederation paths\n"
+ "Treat missing MED as the least preferred one\n"
+ "Treat missing MED as the least preferred one\n"
+ "Compare MED among confederation paths\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ int idx = 0;
+ if (argv_find(argv, argc, "confed", &idx))
+ UNSET_FLAG(bgp->flags, BGP_FLAG_MED_CONFED);
+ idx = 0;
+ if (argv_find(argv, argc, "missing-as-worst", &idx))
+ UNSET_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST);
+
+ bgp_recalculate_all_bestpaths(bgp);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp bestpath bandwidth" configuration. */
+DEFPY (bgp_bestpath_bw,
+ bgp_bestpath_bw_cmd,
+ "bgp bestpath bandwidth <ignore|skip-missing|default-weight-for-missing>$bw_cfg",
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Link Bandwidth attribute\n"
+ "Ignore link bandwidth (i.e., do regular ECMP, not weighted)\n"
+ "Ignore paths without link bandwidth for ECMP (if other paths have it)\n"
+ "Assign a low default weight (value 1) to paths not having link bandwidth\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ safi_t safi;
+
+ if (!bw_cfg) {
+ vty_out(vty, "%% Bandwidth configuration must be specified\n");
+ return CMD_ERR_INCOMPLETE;
+ }
+ if (!strcmp(bw_cfg, "ignore"))
+ bgp->lb_handling = BGP_LINK_BW_IGNORE_BW;
+ else if (!strcmp(bw_cfg, "skip-missing"))
+ bgp->lb_handling = BGP_LINK_BW_SKIP_MISSING;
+ else if (!strcmp(bw_cfg, "default-weight-for-missing"))
+ bgp->lb_handling = BGP_LINK_BW_DEFWT_4_MISSING;
+ else
+ return CMD_ERR_NO_MATCH;
+
+ /* This config is used in route install, so redo that. */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!bgp_fibupd_safi(safi))
+ continue;
+ bgp_zebra_announce_table(bgp, afi, safi);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_bestpath_bw,
+ no_bgp_bestpath_bw_cmd,
+ "no bgp bestpath bandwidth [<ignore|skip-missing|default-weight-for-missing>$bw_cfg]",
+ NO_STR
+ BGP_STR
+ "Change the default bestpath selection\n"
+ "Link Bandwidth attribute\n"
+ "Ignore link bandwidth (i.e., do regular ECMP, not weighted)\n"
+ "Ignore paths without link bandwidth for ECMP (if other paths have it)\n"
+ "Assign a low default weight (value 1) to paths not having link bandwidth\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ safi_t safi;
+
+ bgp->lb_handling = BGP_LINK_BW_ECMP;
+
+ /* This config is used in route install, so redo that. */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!bgp_fibupd_safi(safi))
+ continue;
+ bgp_zebra_announce_table(bgp, afi, safi);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_default_afi_safi, bgp_default_afi_safi_cmd,
+ "[no] bgp default <ipv4-unicast|"
+ "ipv4-multicast|"
+ "ipv4-vpn|"
+ "ipv4-labeled-unicast|"
+ "ipv4-flowspec|"
+ "ipv6-unicast|"
+ "ipv6-multicast|"
+ "ipv6-vpn|"
+ "ipv6-labeled-unicast|"
+ "ipv6-flowspec|"
+ "l2vpn-evpn>$afi_safi",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Activate ipv4-unicast for a peer by default\n"
+ "Activate ipv4-multicast for a peer by default\n"
+ "Activate ipv4-vpn for a peer by default\n"
+ "Activate ipv4-labeled-unicast for a peer by default\n"
+ "Activate ipv4-flowspec for a peer by default\n"
+ "Activate ipv6-unicast for a peer by default\n"
+ "Activate ipv6-multicast for a peer by default\n"
+ "Activate ipv6-vpn for a peer by default\n"
+ "Activate ipv6-labeled-unicast for a peer by default\n"
+ "Activate ipv6-flowspec for a peer by default\n"
+ "Activate l2vpn-evpn for a peer by default\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ char afi_safi_str[strlen(afi_safi) + 1];
+ char *afi_safi_str_tok;
+
+ strlcpy(afi_safi_str, afi_safi, sizeof(afi_safi_str));
+ char *afi_str = strtok_r(afi_safi_str, "-", &afi_safi_str_tok);
+ char *safi_str = strtok_r(NULL, "-", &afi_safi_str_tok);
+ afi_t afi = bgp_vty_afi_from_str(afi_str);
+ safi_t safi;
+
+ /*
+ * Impossible situation but making coverity happy
+ */
+ assert(afi != AFI_MAX);
+
+ if (strmatch(safi_str, "labeled"))
+ safi = bgp_vty_safi_from_str("labeled-unicast");
+ else
+ safi = bgp_vty_safi_from_str(safi_str);
+
+ assert(safi != SAFI_MAX);
+ if (no)
+ bgp->default_af[afi][safi] = false;
+ else {
+ if ((safi == SAFI_LABELED_UNICAST
+ && bgp->default_af[afi][SAFI_UNICAST])
+ || (safi == SAFI_UNICAST
+ && bgp->default_af[afi][SAFI_LABELED_UNICAST]))
+ bgp_vty_return(vty, BGP_ERR_PEER_SAFI_CONFLICT);
+ else
+ bgp->default_af[afi][safi] = true;
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* Display hostname in certain command outputs */
+DEFUN (bgp_default_show_hostname,
+ bgp_default_show_hostname_cmd,
+ "bgp default show-hostname",
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Show hostname in certain command outputs\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_show_hostname,
+ no_bgp_default_show_hostname_cmd,
+ "no bgp default show-hostname",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Show hostname in certain command outputs\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
+/* Display hostname in certain command outputs */
+DEFUN (bgp_default_show_nexthop_hostname,
+ bgp_default_show_nexthop_hostname_cmd,
+ "bgp default show-nexthop-hostname",
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Show hostname for nexthop in certain command outputs\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_show_nexthop_hostname,
+ no_bgp_default_show_nexthop_hostname_cmd,
+ "no bgp default show-nexthop-hostname",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Show hostname for nexthop in certain command outputs\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_default_software_version_capability,
+ bgp_default_software_version_capability_cmd,
+ "[no] bgp default software-version-capability",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Advertise software version capability for all neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY);
+
+ return CMD_SUCCESS;
+}
+
+/* "bgp network import-check" configuration. */
+DEFUN (bgp_network_import_check,
+ bgp_network_import_check_cmd,
+ "bgp network import-check",
+ BGP_STR
+ "BGP network command\n"
+ "Check BGP network route exists in IGP\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ if (!CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
+ SET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
+ bgp_static_redo_import_check(bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,
+ "bgp network import-check exact",
+ BGP_STR
+ "BGP network command\n"
+ "Check BGP network route exists in IGP\n"
+ "Match route precisely\n")
+
+DEFUN (no_bgp_network_import_check,
+ no_bgp_network_import_check_cmd,
+ "no bgp network import-check",
+ NO_STR
+ BGP_STR
+ "BGP network command\n"
+ "Check BGP network route exists in IGP\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
+ UNSET_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
+ bgp_static_redo_import_check(bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_default_local_preference,
+ bgp_default_local_preference_cmd,
+ "bgp default local-preference (0-4294967295)",
+ BGP_STR
+ "Configure BGP defaults\n"
+ "local preference (higher=more preferred)\n"
+ "Configure default local preference value\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t local_pref;
+
+ local_pref = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ bgp_default_local_preference_set(bgp, local_pref);
+ bgp_clear_star_soft_in(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_local_preference,
+ no_bgp_default_local_preference_cmd,
+ "no bgp default local-preference [(0-4294967295)]",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "local preference (higher=more preferred)\n"
+ "Configure default local preference value\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_default_local_preference_unset(bgp);
+ bgp_clear_star_soft_in(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+
+DEFUN (bgp_default_subgroup_pkt_queue_max,
+ bgp_default_subgroup_pkt_queue_max_cmd,
+ "bgp default subgroup-pkt-queue-max (20-100)",
+ BGP_STR
+ "Configure BGP defaults\n"
+ "subgroup-pkt-queue-max\n"
+ "Configure subgroup packet queue max\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ uint32_t max_size;
+
+ max_size = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ bgp_default_subgroup_pkt_queue_max_set(bgp, max_size);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_subgroup_pkt_queue_max,
+ no_bgp_default_subgroup_pkt_queue_max_cmd,
+ "no bgp default subgroup-pkt-queue-max [(20-100)]",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "subgroup-pkt-queue-max\n"
+ "Configure subgroup packet queue max\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_default_subgroup_pkt_queue_max_unset(bgp);
+ return CMD_SUCCESS;
+}
+
+
+DEFUN (bgp_rr_allow_outbound_policy,
+ bgp_rr_allow_outbound_policy_cmd,
+ "bgp route-reflector allow-outbound-policy",
+ BGP_STR
+ "Allow modifications made by out route-map\n"
+ "on ibgp neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (!CHECK_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
+ SET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
+ update_group_announce_rrclients(bgp);
+ bgp_clear_star_soft_out(vty, bgp->name);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_rr_allow_outbound_policy,
+ no_bgp_rr_allow_outbound_policy_cmd,
+ "no bgp route-reflector allow-outbound-policy",
+ NO_STR
+ BGP_STR
+ "Allow modifications made by out route-map\n"
+ "on ibgp neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
+ UNSET_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY);
+ update_group_announce_rrclients(bgp);
+ bgp_clear_star_soft_out(vty, bgp->name);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_listen_limit,
+ bgp_listen_limit_cmd,
+ "bgp listen limit (1-65535)",
+ BGP_STR
+ "BGP Dynamic Neighbors listen commands\n"
+ "Maximum number of BGP Dynamic Neighbors that can be created\n"
+ "Configure Dynamic Neighbors listen limit value\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_number = 3;
+ int listen_limit;
+
+ listen_limit = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ bgp_listen_limit_set(bgp, listen_limit);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_listen_limit,
+ no_bgp_listen_limit_cmd,
+ "no bgp listen limit [(1-65535)]",
+ NO_STR
+ BGP_STR
+ "BGP Dynamic Neighbors listen commands\n"
+ "Maximum number of BGP Dynamic Neighbors that can be created\n"
+ "Configure Dynamic Neighbors listen limit value\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_listen_limit_unset(bgp);
+ return CMD_SUCCESS;
+}
+
+
+/*
+ * Check if this listen range is already configured. Check for exact
+ * match or overlap based on input.
+ */
+static struct peer_group *listen_range_exists(struct bgp *bgp,
+ struct prefix *range, int exact)
+{
+ struct listnode *node, *nnode;
+ struct listnode *node1, *nnode1;
+ struct peer_group *group;
+ struct prefix *lr;
+ afi_t afi;
+ int match;
+
+ afi = family2afi(range->family);
+ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
+ for (ALL_LIST_ELEMENTS(group->listen_range[afi], node1, nnode1,
+ lr)) {
+ if (exact)
+ match = prefix_same(range, lr);
+ else
+ match = (prefix_match(range, lr)
+ || prefix_match(lr, range));
+ if (match)
+ return group;
+ }
+ }
+
+ return NULL;
+}
+
+DEFUN (bgp_listen_range,
+ bgp_listen_range_cmd,
+ "bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME",
+ BGP_STR
+ "Configure BGP dynamic neighbors listen range\n"
+ "Configure BGP dynamic neighbors listen range\n"
+ NEIGHBOR_ADDR_STR
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct prefix range;
+ struct peer_group *group, *existing_group;
+ afi_t afi;
+ int ret;
+ int idx = 0;
+
+ argv_find(argv, argc, "A.B.C.D/M", &idx);
+ argv_find(argv, argc, "X:X::X:X/M", &idx);
+ char *prefix = argv[idx]->arg;
+ argv_find(argv, argc, "PGNAME", &idx);
+ char *peergroup = argv[idx]->arg;
+
+ /* Convert IP prefix string to struct prefix. */
+ ret = str2prefix(prefix, &range);
+ if (!ret) {
+ vty_out(vty, "%% Malformed listen range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ afi = family2afi(range.family);
+
+ if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&range.u.prefix6)) {
+ vty_out(vty,
+ "%% Malformed listen range (link-local address)\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ apply_mask(&range);
+
+ /* Check if same listen range is already configured. */
+ existing_group = listen_range_exists(bgp, &range, 1);
+ if (existing_group) {
+ if (strcmp(existing_group->name, peergroup) == 0)
+ return CMD_SUCCESS;
+ else {
+ vty_out(vty,
+ "%% Same listen range is attached to peer-group %s\n",
+ existing_group->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ /* Check if an overlapping listen range exists. */
+ if (listen_range_exists(bgp, &range, 0)) {
+ vty_out(vty,
+ "%% Listen range overlaps with existing listen range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ group = peer_group_lookup(bgp, peergroup);
+ if (!group) {
+ vty_out(vty, "%% Configure the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_group_listen_range_add(group, &range);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_bgp_listen_range,
+ no_bgp_listen_range_cmd,
+ "no bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME",
+ NO_STR
+ BGP_STR
+ "Unconfigure BGP dynamic neighbors listen range\n"
+ "Unconfigure BGP dynamic neighbors listen range\n"
+ NEIGHBOR_ADDR_STR
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct prefix range;
+ struct peer_group *group;
+ afi_t afi;
+ int ret;
+ int idx = 0;
+
+ argv_find(argv, argc, "A.B.C.D/M", &idx);
+ argv_find(argv, argc, "X:X::X:X/M", &idx);
+ char *prefix = argv[idx]->arg;
+ argv_find(argv, argc, "PGNAME", &idx);
+ char *peergroup = argv[idx]->arg;
+
+ /* Convert IP prefix string to struct prefix. */
+ ret = str2prefix(prefix, &range);
+ if (!ret) {
+ vty_out(vty, "%% Malformed listen range\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ afi = family2afi(range.family);
+
+ if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&range.u.prefix6)) {
+ vty_out(vty,
+ "%% Malformed listen range (link-local address)\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ apply_mask(&range);
+
+ group = peer_group_lookup(bgp, peergroup);
+ if (!group) {
+ vty_out(vty, "%% Peer-group does not exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_group_listen_range_del(group, &range);
+ return bgp_vty_return(vty, ret);
+}
+
+void bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode, *rnode, *nrnode;
+ struct prefix *range;
+ afi_t afi;
+
+ if (bgp->dynamic_neighbors_limit != BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT)
+ vty_out(vty, " bgp listen limit %d\n",
+ bgp->dynamic_neighbors_limit);
+
+ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (ALL_LIST_ELEMENTS(group->listen_range[afi], rnode,
+ nrnode, range)) {
+ vty_out(vty,
+ " bgp listen range %pFX peer-group %s\n",
+ range, group->name);
+ }
+ }
+ }
+}
+
+
+DEFUN (bgp_disable_connected_route_check,
+ bgp_disable_connected_route_check_cmd,
+ "bgp disable-ebgp-connected-route-check",
+ BGP_STR
+ "Disable checking if nexthop is connected on ebgp sessions\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ SET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK);
+ bgp_clear_star_soft_in(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_disable_connected_route_check,
+ no_bgp_disable_connected_route_check_cmd,
+ "no bgp disable-ebgp-connected-route-check",
+ NO_STR
+ BGP_STR
+ "Disable checking if nexthop is connected on ebgp sessions\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK);
+ bgp_clear_star_soft_in(vty, bgp->name);
+
+ return CMD_SUCCESS;
+}
+
+
+static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
+ const char *as_str)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+ as_t as;
+ int as_type = AS_SPECIFIED;
+ union sockunion su;
+
+ if (as_str[0] == 'i') {
+ as = 0;
+ as_type = AS_INTERNAL;
+ } else if (as_str[0] == 'e') {
+ as = 0;
+ as_type = AS_EXTERNAL;
+ } else if (!asn_str2asn(as_str, &as))
+ as_type = AS_UNSPECIFIED;
+
+ if (as_type == AS_UNSPECIFIED) {
+ vty_out(vty, "%% Invalid peer AS: %s\n", as_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* If peer is peer group or interface peer, call proper function. */
+ ret = str2sockunion(peer_str, &su);
+ if (ret < 0) {
+ struct peer *peer;
+
+ /* Check if existing interface peer */
+ peer = peer_lookup_by_conf_if(bgp, peer_str);
+
+ ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, as_str);
+
+ /* if not interface peer, check peer-group settings */
+ if (ret < 0 && !peer) {
+ ret = peer_group_remote_as(bgp, peer_str, &as, as_type,
+ as_str);
+ if (ret < 0) {
+ vty_out(vty,
+ "%% Create the peer-group or interface first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+ }
+ } else {
+ if (peer_address_self_check(bgp, &su)) {
+ vty_out(vty,
+ "%% Can not configure the local system as neighbor\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ret = peer_remote_as(bgp, &su, NULL, &as, as_type, as_str);
+ }
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (bgp_default_shutdown,
+ bgp_default_shutdown_cmd,
+ "[no] bgp default shutdown",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Apply administrative shutdown to newly configured peers\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->autoshutdown = !strmatch(argv[0]->text, "no");
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_shutdown_msg, bgp_shutdown_msg_cmd, "bgp shutdown message MSG...",
+ BGP_STR
+ "Administrative shutdown of the BGP instance\n"
+ "Add a shutdown message (RFC 8203)\n"
+ "Shutdown message\n")
+{
+ char *msgstr = NULL;
+
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (argc > 3)
+ msgstr = argv_concat(argv, argc, 3);
+
+ if (msgstr && strlen(msgstr) > BGP_ADMIN_SHUTDOWN_MSG_LEN) {
+ vty_out(vty, "%% Shutdown message size exceeded %d\n",
+ BGP_ADMIN_SHUTDOWN_MSG_LEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_shutdown_enable(bgp, msgstr);
+ XFREE(MTYPE_TMP, msgstr);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_shutdown, bgp_shutdown_cmd, "bgp shutdown",
+ BGP_STR "Administrative shutdown of the BGP instance\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_shutdown_enable(bgp, NULL);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_bgp_shutdown, no_bgp_shutdown_cmd, "no bgp shutdown",
+ NO_STR BGP_STR "Administrative shutdown of the BGP instance\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_shutdown_disable(bgp);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_bgp_shutdown, no_bgp_shutdown_msg_cmd,
+ "no bgp shutdown message MSG...", NO_STR BGP_STR
+ "Administrative shutdown of the BGP instance\n"
+ "Add a shutdown message (RFC 8203)\n" "Shutdown message\n")
+
+DEFUN (neighbor_remote_as,
+ neighbor_remote_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ int idx_peer = 1;
+ int idx_remote_as = 3;
+ return peer_remote_as_vty(vty, argv[idx_peer]->arg,
+ argv[idx_remote_as]->arg);
+}
+
+DEFPY (bgp_allow_martian,
+ bgp_allow_martian_cmd,
+ "[no]$no bgp allow-martian-nexthop",
+ NO_STR
+ BGP_STR
+ "Allow Martian nexthops to be received in the NLRI from a peer\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ bgp->allow_martian = false;
+ else
+ bgp->allow_martian = true;
+
+ return CMD_SUCCESS;
+}
+
+/* Enable fast convergence of bgp sessions. If this is enabled, bgp
+ * sessions do not wait for hold timer expiry to bring down the sessions
+ * when nexthop becomes unreachable
+ */
+DEFUN(bgp_fast_convergence, bgp_fast_convergence_cmd, "bgp fast-convergence",
+ BGP_STR "Fast convergence for bgp sessions\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->fast_convergence = true;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_bgp_fast_convergence, no_bgp_fast_convergence_cmd,
+ "no bgp fast-convergence",
+ NO_STR BGP_STR "Fast convergence for bgp sessions\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->fast_convergence = false;
+
+ return CMD_SUCCESS;
+}
+
+static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
+ int v6only,
+ const char *peer_group_name,
+ const char *as_str)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ as_t as = 0;
+ int as_type = AS_UNSPECIFIED;
+ struct peer *peer;
+ struct peer_group *group;
+ int ret = 0;
+
+ group = peer_group_lookup(bgp, conf_if);
+
+ if (group) {
+ vty_out(vty, "%% Name conflict with peer-group \n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (as_str) {
+ if (as_str[0] == 'i') {
+ as_type = AS_INTERNAL;
+ } else if (as_str[0] == 'e') {
+ as_type = AS_EXTERNAL;
+ } else {
+ /* Get AS number. */
+ if (asn_str2asn(as_str, &as))
+ as_type = AS_SPECIFIED;
+ }
+ }
+
+ peer = peer_lookup_by_conf_if(bgp, conf_if);
+ if (peer) {
+ if (as_str)
+ ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type,
+ as_str);
+ } else {
+ peer = peer_create(NULL, conf_if, bgp, bgp->as, as, as_type,
+ NULL, true, as_str);
+
+ if (!peer) {
+ vty_out(vty, "%% BGP failed to create peer\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (v6only)
+ peer_flag_set(peer, PEER_FLAG_IFPEER_V6ONLY);
+
+ /* Request zebra to initiate IPv6 RAs on this interface. We do
+ * this
+ * any unnumbered peer in order to not worry about run-time
+ * transitions
+ * (e.g., peering is initially IPv4, but the IPv4 /30 or /31
+ * address
+ * gets deleted later etc.)
+ */
+ if (peer->ifp)
+ bgp_zebra_initiate_radv(bgp, peer);
+ }
+
+ if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
+ || (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) {
+ if (v6only)
+ peer_flag_set(peer, PEER_FLAG_IFPEER_V6ONLY);
+ else
+ peer_flag_unset(peer, PEER_FLAG_IFPEER_V6ONLY);
+
+ /* v6only flag changed. Reset bgp seesion */
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) {
+ peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
+ bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+ } else
+ bgp_session_reset(peer);
+ }
+
+ if (!CHECK_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE)) {
+ SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
+ SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE);
+ SET_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE);
+ }
+
+ if (peer_group_name) {
+ group = peer_group_lookup(bgp, peer_group_name);
+ if (!group) {
+ vty_out(vty, "%% Configure the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_group_bind(bgp, NULL, peer, group, &as);
+ }
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_interface_config,
+ neighbor_interface_config_cmd,
+ "neighbor WORD interface [peer-group PGNAME]",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ int idx_word = 1;
+ int idx_peer_group_word = 4;
+
+ if (argc > idx_peer_group_word)
+ return peer_conf_interface_get(
+ vty, argv[idx_word]->arg, 0,
+ argv[idx_peer_group_word]->arg, NULL);
+ else
+ return peer_conf_interface_get(vty, argv[idx_word]->arg, 0,
+ NULL, NULL);
+}
+
+DEFUN (neighbor_interface_config_v6only,
+ neighbor_interface_config_v6only_cmd,
+ "neighbor WORD interface v6only [peer-group PGNAME]",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ "Enable BGP with v6 link-local only\n"
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ int idx_word = 1;
+ int idx_peer_group_word = 5;
+
+ if (argc > idx_peer_group_word)
+ return peer_conf_interface_get(
+ vty, argv[idx_word]->arg, 1,
+ argv[idx_peer_group_word]->arg, NULL);
+
+ return peer_conf_interface_get(vty, argv[idx_word]->arg, 1, NULL, NULL);
+}
+
+
+DEFUN (neighbor_interface_config_remote_as,
+ neighbor_interface_config_remote_as_cmd,
+ "neighbor WORD interface remote-as <ASNUM|internal|external>",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ int idx_word = 1;
+ int idx_remote_as = 4;
+ return peer_conf_interface_get(vty, argv[idx_word]->arg, 0, NULL,
+ argv[idx_remote_as]->arg);
+}
+
+DEFUN (neighbor_interface_v6only_config_remote_as,
+ neighbor_interface_v6only_config_remote_as_cmd,
+ "neighbor WORD interface v6only remote-as <ASNUM|internal|external>",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP with v6 link-local only\n"
+ "Enable BGP on interface\n"
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ int idx_word = 1;
+ int idx_remote_as = 5;
+ return peer_conf_interface_get(vty, argv[idx_word]->arg, 1, NULL,
+ argv[idx_remote_as]->arg);
+}
+
+DEFUN (neighbor_peer_group,
+ neighbor_peer_group_cmd,
+ "neighbor WORD peer-group",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Configure peer-group\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_word = 1;
+ struct peer *peer;
+ struct peer_group *group;
+
+ peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);
+ if (peer) {
+ vty_out(vty, "%% Name conflict with interface: \n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ group = peer_group_get(bgp, argv[idx_word]->arg);
+ if (!group) {
+ vty_out(vty, "%% BGP failed to find or create peer-group\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor,
+ no_neighbor_cmd,
+ "no neighbor <WORD|<A.B.C.D|X:X::X:X> [remote-as <(1-4294967295)|internal|external>]>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_peer = 2;
+ int ret;
+ union sockunion su;
+ struct peer_group *group;
+ struct peer *peer;
+ struct peer *other;
+
+ ret = str2sockunion(argv[idx_peer]->arg, &su);
+ if (ret < 0) {
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg);
+ if (peer) {
+ /* Request zebra to terminate IPv6 RAs on this
+ * interface. */
+ if (peer->ifp)
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+ peer_notify_unconfig(peer);
+ peer_delete(peer);
+ return CMD_SUCCESS;
+ }
+
+ group = peer_group_lookup(bgp, argv[idx_peer]->arg);
+ if (group) {
+ peer_group_notify_unconfig(group);
+ peer_group_delete(group);
+ } else {
+ vty_out(vty, "%% Create the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else {
+ peer = peer_lookup(bgp, &su);
+ if (peer) {
+ if (peer_dynamic_neighbor(peer)) {
+ vty_out(vty,
+ "%% Operation not allowed on a dynamic neighbor\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ other = peer->doppelganger;
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+
+ peer_notify_unconfig(peer);
+ peer_delete(peer);
+ if (other && other->connection->status != Deleted) {
+ peer_notify_unconfig(other);
+ peer_delete(other);
+ }
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_interface_config,
+ no_neighbor_interface_config_cmd,
+ "no neighbor WORD interface [v6only] [peer-group PGNAME] [remote-as <(1-4294967295)|internal|external>]",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n"
+ "Enable BGP with v6 link-local only\n"
+ "Member of the peer-group\n"
+ "Peer-group name\n"
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_word = 2;
+ struct peer *peer;
+
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);
+ if (peer) {
+ /* Request zebra to terminate IPv6 RAs on this interface. */
+ if (peer->ifp)
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+ peer_notify_unconfig(peer);
+ peer_delete(peer);
+ } else {
+ vty_out(vty, "%% Create the bgp interface first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_peer_group,
+ no_neighbor_peer_group_cmd,
+ "no neighbor WORD peer-group",
+ NO_STR
+ NEIGHBOR_STR
+ "Neighbor tag\n"
+ "Configure peer-group\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_word = 2;
+ struct peer_group *group;
+
+ group = peer_group_lookup(bgp, argv[idx_word]->arg);
+ if (group) {
+ peer_group_notify_unconfig(group);
+ peer_group_delete(group);
+ } else {
+ vty_out(vty, "%% Create the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_interface_peer_group_remote_as,
+ no_neighbor_interface_peer_group_remote_as_cmd,
+ "no neighbor WORD remote-as <ASNUM|internal|external>",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Specify a BGP neighbor\n"
+ AS_STR
+ "Internal BGP peer\n"
+ "External BGP peer\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_word = 2;
+ struct peer_group *group;
+ struct peer *peer;
+
+ /* look up for neighbor by interface name config. */
+ peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);
+ if (peer) {
+ peer_as_change(peer, 0, AS_UNSPECIFIED, NULL);
+ return CMD_SUCCESS;
+ }
+
+ group = peer_group_lookup(bgp, argv[idx_word]->arg);
+ if (group)
+ peer_group_remote_as_delete(group);
+ else {
+ vty_out(vty, "%% Create the peer-group or interface first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_local_as,
+ neighbor_local_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a local-as number\n"
+ "AS number expressed in dotted or plain format used as local AS\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ struct peer *peer;
+ int ret;
+ as_t as;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!asn_str2asn(argv[idx_number]->arg, &as)) {
+ vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
+ argv[idx_number]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_local_as_set(peer, as, 0, 0, argv[idx_number]->arg);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_local_as_no_prepend,
+ neighbor_local_as_no_prepend_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a local-as number\n"
+ "AS number expressed in dotted or plain format used as local AS\n"
+ "Do not prepend local-as to updates from ebgp peers\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ struct peer *peer;
+ int ret;
+ as_t as;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!asn_str2asn(argv[idx_number]->arg, &as)) {
+ vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
+ argv[idx_number]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_local_as_set(peer, as, 1, 0, argv[idx_number]->arg);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_local_as_no_prepend_replace_as,
+ neighbor_local_as_no_prepend_replace_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a local-as number\n"
+ "AS number expressed in dotted or plain format used as local AS\n"
+ "Do not prepend local-as to updates from ebgp peers\n"
+ "Do not prepend local-as to updates from ibgp peers\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ struct peer *peer;
+ int ret;
+ as_t as;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!asn_str2asn(argv[idx_number]->arg, &as)) {
+ vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
+ argv[idx_number]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_local_as_set(peer, as, 1, 1, argv[idx_number]->arg);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_neighbor_local_as,
+ no_neighbor_local_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as]]]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Specify a local-as number\n"
+ "AS number expressed in dotted or plain format used as local AS\n"
+ "Do not prepend local-as to updates from ebgp peers\n"
+ "Do not prepend local-as to updates from ibgp peers\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_local_as_unset(peer);
+ return bgp_vty_return(vty, ret);
+}
+
+
+DEFUN (neighbor_solo,
+ neighbor_solo_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> solo",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Solo peer - part of its own update group\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = update_group_adjust_soloness(peer, 1);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_neighbor_solo,
+ no_neighbor_solo_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> solo",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Solo peer - part of its own update group\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = update_group_adjust_soloness(peer, 0);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_password,
+ neighbor_password_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> password LINE",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set a password\n"
+ "The password\n")
+{
+ int idx_peer = 1;
+ int idx_line = 3;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_password_set(peer, argv[idx_line]->arg);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (no_neighbor_password,
+ no_neighbor_password_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> password [LINE]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set a password\n"
+ "The password\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_password_unset(peer);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_activate,
+ neighbor_activate_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> activate",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable the Address Family for this Neighbor\n")
+{
+ int idx_peer = 1;
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_activate(peer, bgp_node_afi(vty), bgp_node_safi(vty));
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(neighbor_activate, neighbor_activate_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> activate",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Enable the Address Family for this Neighbor\n")
+
+DEFUN (no_neighbor_activate,
+ no_neighbor_activate_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> activate",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable the Address Family for this Neighbor\n")
+{
+ int idx_peer = 2;
+ int ret;
+ struct peer *peer;
+
+ /* Lookup peer. */
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_deactivate(peer, bgp_node_afi(vty), bgp_node_safi(vty));
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(no_neighbor_activate, no_neighbor_activate_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> activate",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Enable the Address Family for this Neighbor\n")
+
+DEFUN (neighbor_set_peer_group,
+ neighbor_set_peer_group_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_peer = 1;
+ int idx_word = 3;
+ int ret;
+ as_t as;
+ union sockunion su;
+ struct peer *peer;
+ struct peer_group *group;
+
+ ret = str2sockunion(argv[idx_peer]->arg, &su);
+ if (ret < 0) {
+ peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg);
+ if (!peer) {
+ vty_out(vty, "%% Malformed address or name: %s\n",
+ argv[idx_peer]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ } else {
+ if (peer_address_self_check(bgp, &su)) {
+ vty_out(vty,
+ "%% Can not configure the local system as neighbor\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* Disallow for dynamic neighbor. */
+ peer = peer_lookup(bgp, &su);
+ if (peer && peer_dynamic_neighbor(peer)) {
+ vty_out(vty,
+ "%% Operation not allowed on a dynamic neighbor\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ group = peer_group_lookup(bgp, argv[idx_word]->arg);
+ if (!group) {
+ vty_out(vty, "%% Configure the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ ret = peer_group_bind(bgp, &su, peer, group, &as);
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+
+DEFUN (no_neighbor_set_peer_group,
+ no_neighbor_set_peer_group_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_peer = 2;
+ int idx_word = 4;
+ int ret;
+ struct peer *peer;
+ struct peer_group *group;
+
+ peer = peer_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ group = peer_group_lookup(bgp, argv[idx_word]->arg);
+ if (!group) {
+ vty_out(vty, "%% Configure the peer-group first\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+
+ peer_notify_unconfig(peer);
+ ret = peer_delete(peer);
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Member of the peer-group\n"
+ "Peer-group name\n")
+
+/* neighbor passive. */
+DEFUN (neighbor_passive,
+ neighbor_passive_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> passive",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Don't send open messages to this neighbor\n")
+{
+ int idx_peer = 1;
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE);
+}
+
+DEFUN (no_neighbor_passive,
+ no_neighbor_passive_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> passive",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Don't send open messages to this neighbor\n")
+{
+ int idx_peer = 2;
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE);
+}
+
+/* neighbor shutdown. */
+DEFUN (neighbor_shutdown_msg,
+ neighbor_shutdown_msg_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> shutdown message MSG...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n"
+ "Add a shutdown message (RFC 8203)\n"
+ "Shutdown message\n")
+{
+ int idx_peer = 1;
+
+ if (argc >= 5) {
+ struct peer *peer =
+ peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ char *message;
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+ message = argv_concat(argv, argc, 4);
+ peer_tx_shutdown_message_set(peer, message);
+ XFREE(MTYPE_TMP, message);
+ }
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg, PEER_FLAG_SHUTDOWN);
+}
+
+ALIAS(neighbor_shutdown_msg, neighbor_shutdown_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> shutdown",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n")
+
+DEFUN (no_neighbor_shutdown_msg,
+ no_neighbor_shutdown_msg_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> shutdown message MSG...",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n"
+ "Remove a shutdown message (RFC 8203)\n"
+ "Shutdown message\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_SHUTDOWN);
+}
+
+ALIAS(no_neighbor_shutdown_msg, no_neighbor_shutdown_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> shutdown",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n")
+
+DEFUN(neighbor_shutdown_rtt,
+ neighbor_shutdown_rtt_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> shutdown rtt (1-65535) [count (1-255)]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n"
+ "Shutdown if round-trip-time is higher than expected\n"
+ "Round-trip-time in milliseconds\n"
+ "Specify the number of keepalives before shutdown\n"
+ "The number of keepalives with higher RTT to shutdown\n")
+{
+ int idx_peer = 1;
+ int idx_rtt = 4;
+ int idx_count = 0;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ peer->rtt_expected = strtol(argv[idx_rtt]->arg, NULL, 10);
+
+ if (argv_find(argv, argc, "count", &idx_count))
+ peer->rtt_keepalive_conf =
+ strtol(argv[idx_count + 1]->arg, NULL, 10);
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_RTT_SHUTDOWN);
+}
+
+DEFUN(no_neighbor_shutdown_rtt,
+ no_neighbor_shutdown_rtt_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> shutdown rtt [(1-65535) [count (1-255)]]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Administratively shut down this neighbor\n"
+ "Shutdown if round-trip-time is higher than expected\n"
+ "Round-trip-time in milliseconds\n"
+ "Specify the number of keepalives before shutdown\n"
+ "The number of keepalives with higher RTT to shutdown\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ peer->rtt_expected = 0;
+ peer->rtt_keepalive_conf = 1;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_RTT_SHUTDOWN);
+}
+
+/* neighbor capability dynamic. */
+DEFUN (neighbor_capability_dynamic,
+ neighbor_capability_dynamic_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> capability dynamic",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise dynamic capability to this neighbor\n")
+{
+ int idx_peer = 1;
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DYNAMIC_CAPABILITY);
+}
+
+DEFUN (no_neighbor_capability_dynamic,
+ no_neighbor_capability_dynamic_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> capability dynamic",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise dynamic capability to this neighbor\n")
+{
+ int idx_peer = 2;
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DYNAMIC_CAPABILITY);
+}
+
+/* neighbor dont-capability-negotiate */
+DEFUN (neighbor_dont_capability_negotiate,
+ neighbor_dont_capability_negotiate_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> dont-capability-negotiate",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not perform capability negotiation\n")
+{
+ int idx_peer = 1;
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DONT_CAPABILITY);
+}
+
+DEFUN (no_neighbor_dont_capability_negotiate,
+ no_neighbor_dont_capability_negotiate_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> dont-capability-negotiate",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not perform capability negotiation\n")
+{
+ int idx_peer = 2;
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DONT_CAPABILITY);
+}
+
+/* neighbor capability extended next hop encoding */
+DEFUN (neighbor_capability_enhe,
+ neighbor_capability_enhe_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> capability extended-nexthop",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise extended next-hop capability to the peer\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (peer && peer->conf_if)
+ return CMD_SUCCESS;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_CAPABILITY_ENHE);
+}
+
+DEFUN (no_neighbor_capability_enhe,
+ no_neighbor_capability_enhe_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> capability extended-nexthop",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise extended next-hop capability to the peer\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (peer && peer->conf_if) {
+ vty_out(vty,
+ "Peer %s cannot have capability extended-nexthop turned off\n",
+ argv[idx_peer]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_CAPABILITY_ENHE);
+}
+
+/* neighbor capability software-version */
+DEFPY(neighbor_capability_software_version,
+ neighbor_capability_software_version_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor capability software-version",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise Software Version capability to the peer\n")
+{
+ struct peer *peer;
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ ret = peer_flag_unset_vty(vty, neighbor,
+ PEER_FLAG_CAPABILITY_SOFT_VERSION);
+ else
+ ret = peer_flag_set_vty(vty, neighbor,
+ PEER_FLAG_CAPABILITY_SOFT_VERSION);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_SOFT_VERSION,
+ no ? CAPABILITY_ACTION_UNSET
+ : CAPABILITY_ACTION_SET);
+
+ return ret;
+}
+
+static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
+ afi_t afi, safi_t safi, uint64_t flag,
+ int set)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (set)
+ ret = peer_af_flag_set(peer, afi, safi, flag);
+ else
+ ret = peer_af_flag_unset(peer, afi, safi, flag);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_af_flag_set_vty(struct vty *vty, const char *peer_str,
+ afi_t afi, safi_t safi, uint64_t flag)
+{
+ return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 1);
+}
+
+static int peer_af_flag_unset_vty(struct vty *vty, const char *peer_str,
+ afi_t afi, safi_t safi, uint64_t flag)
+{
+ return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 0);
+}
+
+/* neighbor capability orf prefix-list. */
+DEFUN (neighbor_capability_orf_prefix,
+ neighbor_capability_orf_prefix_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> capability orf prefix-list <both|send|receive>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise ORF capability to the peer\n"
+ "Advertise prefixlist ORF capability to this neighbor\n"
+ "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+ "Capability to RECEIVE the ORF from this neighbor\n"
+ "Capability to SEND the ORF to this neighbor\n")
+{
+ int idx_send_recv = 5;
+ char *peer_str = argv[1]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (strmatch(argv[idx_send_recv]->text, "send"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM);
+
+ if (strmatch(argv[idx_send_recv]->text, "receive"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+
+ if (strmatch(argv[idx_send_recv]->text, "both"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM)
+ | peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+
+ return CMD_WARNING_CONFIG_FAILED;
+}
+
+ALIAS_HIDDEN(
+ neighbor_capability_orf_prefix,
+ neighbor_capability_orf_prefix_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> capability orf prefix-list <both|send|receive>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise ORF capability to the peer\n"
+ "Advertise prefixlist ORF capability to this neighbor\n"
+ "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+ "Capability to RECEIVE the ORF from this neighbor\n"
+ "Capability to SEND the ORF to this neighbor\n")
+
+DEFUN (no_neighbor_capability_orf_prefix,
+ no_neighbor_capability_orf_prefix_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> capability orf prefix-list <both|send|receive>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise ORF capability to the peer\n"
+ "Advertise prefixlist ORF capability to this neighbor\n"
+ "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+ "Capability to RECEIVE the ORF from this neighbor\n"
+ "Capability to SEND the ORF to this neighbor\n")
+{
+ int idx_send_recv = 6;
+ char *peer_str = argv[2]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (strmatch(argv[idx_send_recv]->text, "send"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM);
+
+ if (strmatch(argv[idx_send_recv]->text, "receive"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+
+ if (strmatch(argv[idx_send_recv]->text, "both"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM);
+
+ return CMD_WARNING_CONFIG_FAILED;
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_capability_orf_prefix,
+ no_neighbor_capability_orf_prefix_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> capability orf prefix-list <both|send|receive>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Advertise capability to the peer\n"
+ "Advertise ORF capability to the peer\n"
+ "Advertise prefixlist ORF capability to this neighbor\n"
+ "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+ "Capability to RECEIVE the ORF from this neighbor\n"
+ "Capability to SEND the ORF to this neighbor\n")
+
+/* neighbor next-hop-self. */
+DEFUN (neighbor_nexthop_self,
+ neighbor_nexthop_self_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty), PEER_FLAG_NEXTHOP_SELF);
+}
+
+ALIAS_HIDDEN(neighbor_nexthop_self, neighbor_nexthop_self_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n")
+
+/* neighbor next-hop-self. */
+DEFUN (neighbor_nexthop_self_force,
+ neighbor_nexthop_self_force_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self force",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_FORCE_NEXTHOP_SELF);
+}
+
+ALIAS_HIDDEN(neighbor_nexthop_self_force,
+ neighbor_nexthop_self_force_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self force",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
+ALIAS_HIDDEN(neighbor_nexthop_self_force,
+ neighbor_nexthop_self_all_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self all",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
+DEFUN (no_neighbor_nexthop_self,
+ no_neighbor_nexthop_self_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_NEXTHOP_SELF);
+}
+
+ALIAS_HIDDEN(no_neighbor_nexthop_self, no_neighbor_nexthop_self_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n")
+
+DEFUN (no_neighbor_nexthop_self_force,
+ no_neighbor_nexthop_self_force_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self force",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_FORCE_NEXTHOP_SELF);
+}
+
+ALIAS_HIDDEN(no_neighbor_nexthop_self_force,
+ no_neighbor_nexthop_self_force_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self force",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
+ALIAS_HIDDEN(no_neighbor_nexthop_self_force,
+ no_neighbor_nexthop_self_all_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self all",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
+/* neighbor as-override */
+DEFUN (neighbor_as_override,
+ neighbor_as_override_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> as-override",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty), PEER_FLAG_AS_OVERRIDE);
+}
+
+ALIAS_HIDDEN(neighbor_as_override, neighbor_as_override_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> as-override",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+
+DEFUN (no_neighbor_as_override,
+ no_neighbor_as_override_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> as-override",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_AS_OVERRIDE);
+}
+
+ALIAS_HIDDEN(no_neighbor_as_override, no_neighbor_as_override_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> as-override",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Override ASNs in outbound updates if aspath equals remote-as\n")
+
+/* neighbor remove-private-AS. */
+DEFUN (neighbor_remove_private_as,
+ neighbor_remove_private_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS);
+}
+
+ALIAS_HIDDEN(neighbor_remove_private_as, neighbor_remove_private_as_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n")
+
+DEFUN (neighbor_remove_private_as_all,
+ neighbor_remove_private_as_all_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
+}
+
+ALIAS_HIDDEN(neighbor_remove_private_as_all,
+ neighbor_remove_private_as_all_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n")
+
+DEFUN (neighbor_remove_private_as_replace_as,
+ neighbor_remove_private_as_replace_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS replace-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
+}
+
+ALIAS_HIDDEN(neighbor_remove_private_as_replace_as,
+ neighbor_remove_private_as_replace_as_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS replace-AS",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+DEFUN (neighbor_remove_private_as_all_replace_as,
+ neighbor_remove_private_as_all_replace_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all replace-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE);
+}
+
+ALIAS_HIDDEN(
+ neighbor_remove_private_as_all_replace_as,
+ neighbor_remove_private_as_all_replace_as_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all replace-AS",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+DEFUN (no_neighbor_remove_private_as,
+ no_neighbor_remove_private_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS);
+}
+
+ALIAS_HIDDEN(no_neighbor_remove_private_as,
+ no_neighbor_remove_private_as_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n")
+
+DEFUN (no_neighbor_remove_private_as_all,
+ no_neighbor_remove_private_as_all_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
+}
+
+ALIAS_HIDDEN(no_neighbor_remove_private_as_all,
+ no_neighbor_remove_private_as_all_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n")
+
+DEFUN (no_neighbor_remove_private_as_replace_as,
+ no_neighbor_remove_private_as_replace_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS replace-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
+}
+
+ALIAS_HIDDEN(no_neighbor_remove_private_as_replace_as,
+ no_neighbor_remove_private_as_replace_as_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS replace-AS",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+DEFUN (no_neighbor_remove_private_as_all_replace_as,
+ no_neighbor_remove_private_as_all_replace_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all replace-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE);
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_remove_private_as_all_replace_as,
+ no_neighbor_remove_private_as_all_replace_as_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> remove-private-AS all replace-AS",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Remove private ASNs in outbound updates\n"
+ "Apply to all AS numbers\n"
+ "Replace private ASNs with our ASN in outbound updates\n")
+
+
+/* neighbor send-community. */
+DEFUN (neighbor_send_community,
+ neighbor_send_community_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> send-community",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n")
+{
+ int idx_peer = 1;
+
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_SEND_COMMUNITY);
+}
+
+ALIAS_HIDDEN(neighbor_send_community, neighbor_send_community_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> send-community",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n")
+
+DEFUN (no_neighbor_send_community,
+ no_neighbor_send_community_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n")
+{
+ int idx_peer = 2;
+
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_SEND_COMMUNITY);
+}
+
+ALIAS_HIDDEN(no_neighbor_send_community, no_neighbor_send_community_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n")
+
+/* neighbor send-community extended. */
+DEFUN (neighbor_send_community_type,
+ neighbor_send_community_type_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n"
+ "Send Standard and Extended Community attributes\n"
+ "Send Standard, Large and Extended Community attributes\n"
+ "Send Extended Community attributes\n"
+ "Send Standard Community attributes\n"
+ "Send Large Community attributes\n")
+{
+ const char *type = argv[argc - 1]->text;
+ char *peer_str = argv[1]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (strmatch(type, "standard"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY);
+
+ if (strmatch(type, "extended"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+
+ if (strmatch(type, "large"))
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ if (strmatch(type, "both")) {
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY)
+ | peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ }
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY)
+ | peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY)
+ | peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+}
+
+ALIAS_HIDDEN(
+ neighbor_send_community_type, neighbor_send_community_type_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n"
+ "Send Standard and Extended Community attributes\n"
+ "Send Standard, Large and Extended Community attributes\n"
+ "Send Extended Community attributes\n"
+ "Send Standard Community attributes\n"
+ "Send Large Community attributes\n")
+
+DEFUN (no_neighbor_send_community_type,
+ no_neighbor_send_community_type_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n"
+ "Send Standard and Extended Community attributes\n"
+ "Send Standard, Large and Extended Community attributes\n"
+ "Send Extended Community attributes\n"
+ "Send Standard Community attributes\n"
+ "Send Large Community attributes\n")
+{
+ const char *type = argv[argc - 1]->text;
+ char *peer_str = argv[2]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (strmatch(type, "standard"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY);
+
+ if (strmatch(type, "extended"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+
+ if (strmatch(type, "large"))
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ if (strmatch(type, "both")) {
+
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ }
+
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_send_community_type,
+ no_neighbor_send_community_type_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Send Community attribute to this neighbor\n"
+ "Send Standard and Extended Community attributes\n"
+ "Send Standard, Large and Extended Community attributes\n"
+ "Send Extended Community attributes\n"
+ "Send Standard Community attributes\n"
+ "Send Large Community attributes\n")
+
+/* neighbor soft-reconfig. */
+DEFUN (neighbor_soft_reconfiguration,
+ neighbor_soft_reconfiguration_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> soft-reconfiguration inbound",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Per neighbor soft reconfiguration\n"
+ "Allow inbound soft reconfiguration for this neighbor\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_SOFT_RECONFIG);
+}
+
+ALIAS_HIDDEN(neighbor_soft_reconfiguration,
+ neighbor_soft_reconfiguration_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> soft-reconfiguration inbound",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Per neighbor soft reconfiguration\n"
+ "Allow inbound soft reconfiguration for this neighbor\n")
+
+DEFUN (no_neighbor_soft_reconfiguration,
+ no_neighbor_soft_reconfiguration_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> soft-reconfiguration inbound",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Per neighbor soft reconfiguration\n"
+ "Allow inbound soft reconfiguration for this neighbor\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_SOFT_RECONFIG);
+}
+
+ALIAS_HIDDEN(no_neighbor_soft_reconfiguration,
+ no_neighbor_soft_reconfiguration_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> soft-reconfiguration inbound",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Per neighbor soft reconfiguration\n"
+ "Allow inbound soft reconfiguration for this neighbor\n")
+
+DEFUN (neighbor_route_reflector_client,
+ neighbor_route_reflector_client_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-reflector-client",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Reflector client\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_REFLECTOR_CLIENT);
+}
+
+ALIAS_HIDDEN(neighbor_route_reflector_client,
+ neighbor_route_reflector_client_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-reflector-client",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Reflector client\n")
+
+DEFUN (no_neighbor_route_reflector_client,
+ no_neighbor_route_reflector_client_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-reflector-client",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Reflector client\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_REFLECTOR_CLIENT);
+}
+
+ALIAS_HIDDEN(no_neighbor_route_reflector_client,
+ no_neighbor_route_reflector_client_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-reflector-client",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Reflector client\n")
+
+/* neighbor route-server-client. */
+DEFUN (neighbor_route_server_client,
+ neighbor_route_server_client_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-server-client",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Server client\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_RSERVER_CLIENT);
+}
+
+ALIAS_HIDDEN(neighbor_route_server_client,
+ neighbor_route_server_client_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-server-client",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Server client\n")
+
+DEFUN (no_neighbor_route_server_client,
+ no_neighbor_route_server_client_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-server-client",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Server client\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_RSERVER_CLIENT);
+}
+
+ALIAS_HIDDEN(no_neighbor_route_server_client,
+ no_neighbor_route_server_client_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-server-client",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Configure a neighbor as Route Server client\n")
+
+DEFUN (neighbor_nexthop_local_unchanged,
+ neighbor_nexthop_local_unchanged_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> nexthop-local unchanged",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure treatment of outgoing link-local nexthop attribute\n"
+ "Leave link-local nexthop unchanged for this peer\n")
+{
+ int idx_peer = 1;
+ return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty),
+ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED);
+}
+
+DEFUN (no_neighbor_nexthop_local_unchanged,
+ no_neighbor_nexthop_local_unchanged_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> nexthop-local unchanged",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Configure treatment of outgoing link-local-nexthop attribute\n"
+ "Leave link-local nexthop unchanged for this peer\n")
+{
+ int idx_peer = 2;
+ return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED);
+}
+
+DEFUN (neighbor_attr_unchanged,
+ neighbor_attr_unchanged_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> attribute-unchanged [{as-path|next-hop|med}]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP attribute is propagated unchanged to this neighbor\n"
+ "As-path attribute\n"
+ "Nexthop attribute\n"
+ "Med attribute\n")
+{
+ int idx = 0;
+ char *peer_str = argv[1]->arg;
+ struct peer *peer;
+ bool aspath = false;
+ bool nexthop = false;
+ bool med = false;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret = 0;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (argv_find(argv, argc, "as-path", &idx))
+ aspath = true;
+
+ idx = 0;
+ if (argv_find(argv, argc, "next-hop", &idx))
+ nexthop = true;
+
+ idx = 0;
+ if (argv_find(argv, argc, "med", &idx))
+ med = true;
+
+ /* no flags means all of them! */
+ if (!aspath && !nexthop && !med) {
+ ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED);
+ ret |= peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+ ret |= peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_MED_UNCHANGED);
+ } else {
+ if (!aspath) {
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED)) {
+ ret |= peer_af_flag_unset_vty(
+ vty, peer_str, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED);
+ }
+ } else
+ ret |= peer_af_flag_set_vty(
+ vty, peer_str, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED);
+
+ if (!nexthop) {
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)) {
+ ret |= peer_af_flag_unset_vty(
+ vty, peer_str, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+ }
+ } else
+ ret |= peer_af_flag_set_vty(
+ vty, peer_str, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+
+ if (!med) {
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_MED_UNCHANGED)) {
+ ret |= peer_af_flag_unset_vty(
+ vty, peer_str, afi, safi,
+ PEER_FLAG_MED_UNCHANGED);
+ }
+ } else
+ ret |= peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_MED_UNCHANGED);
+ }
+
+ return ret;
+}
+
+ALIAS_HIDDEN(
+ neighbor_attr_unchanged, neighbor_attr_unchanged_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> attribute-unchanged [{as-path|next-hop|med}]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "BGP attribute is propagated unchanged to this neighbor\n"
+ "As-path attribute\n"
+ "Nexthop attribute\n"
+ "Med attribute\n")
+
+DEFUN (no_neighbor_attr_unchanged,
+ no_neighbor_attr_unchanged_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> attribute-unchanged [{as-path|next-hop|med}]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP attribute is propagated unchanged to this neighbor\n"
+ "As-path attribute\n"
+ "Nexthop attribute\n"
+ "Med attribute\n")
+{
+ int idx = 0;
+ char *peer_str = argv[2]->arg;
+ struct peer *peer;
+ bool aspath = false;
+ bool nexthop = false;
+ bool med = false;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret = 0;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (argv_find(argv, argc, "as-path", &idx))
+ aspath = true;
+
+ idx = 0;
+ if (argv_find(argv, argc, "next-hop", &idx))
+ nexthop = true;
+
+ idx = 0;
+ if (argv_find(argv, argc, "med", &idx))
+ med = true;
+
+ if (!aspath && !nexthop && !med) // no flags means all of them!
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)
+ | peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_MED_UNCHANGED);
+
+ if (aspath)
+ ret |= peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED);
+
+ if (nexthop)
+ ret |= peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED);
+
+ if (med)
+ ret |= peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_MED_UNCHANGED);
+
+ return ret;
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_attr_unchanged, no_neighbor_attr_unchanged_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> attribute-unchanged [{as-path|next-hop|med}]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "BGP attribute is propagated unchanged to this neighbor\n"
+ "As-path attribute\n"
+ "Nexthop attribute\n"
+ "Med attribute\n")
+
+/* EBGP multihop configuration. */
+static int peer_ebgp_multihop_set_vty(struct vty *vty, const char *ip_str,
+ const char *ttl_str)
+{
+ struct peer *peer;
+ unsigned int ttl;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->conf_if)
+ return bgp_vty_return(vty, BGP_ERR_INVALID_FOR_DIRECT_PEER);
+
+ if (!ttl_str)
+ ttl = MAXTTL;
+ else
+ ttl = strtoul(ttl_str, NULL, 10);
+
+ return bgp_vty_return(vty, peer_ebgp_multihop_set(peer, ttl));
+}
+
+static int peer_ebgp_multihop_unset_vty(struct vty *vty, const char *ip_str)
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return bgp_vty_return(vty, peer_ebgp_multihop_unset(peer));
+}
+
+/* neighbor ebgp-multihop. */
+DEFUN (neighbor_ebgp_multihop,
+ neighbor_ebgp_multihop_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> ebgp-multihop",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Allow EBGP neighbors not on directly connected networks\n")
+{
+ int idx_peer = 1;
+ return peer_ebgp_multihop_set_vty(vty, argv[idx_peer]->arg, NULL);
+}
+
+DEFUN (neighbor_ebgp_multihop_ttl,
+ neighbor_ebgp_multihop_ttl_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> ebgp-multihop (1-255)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Allow EBGP neighbors not on directly connected networks\n"
+ "maximum hop count\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ return peer_ebgp_multihop_set_vty(vty, argv[idx_peer]->arg,
+ argv[idx_number]->arg);
+}
+
+DEFUN (no_neighbor_ebgp_multihop,
+ no_neighbor_ebgp_multihop_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> ebgp-multihop [(1-255)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Allow EBGP neighbors not on directly connected networks\n"
+ "maximum hop count\n")
+{
+ int idx_peer = 2;
+ return peer_ebgp_multihop_unset_vty(vty, argv[idx_peer]->arg);
+}
+
+DEFPY (neighbor_aigp,
+ neighbor_aigp_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor aigp",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable send and receive of the AIGP attribute per neighbor\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ return peer_flag_unset_vty(vty, neighbor, PEER_FLAG_AIGP);
+ else
+ return peer_flag_set_vty(vty, neighbor, PEER_FLAG_AIGP);
+}
+
+static uint8_t get_role_by_name(const char *role_str)
+{
+ if (strncmp(role_str, "peer", 2) == 0)
+ return ROLE_PEER;
+ if (strncmp(role_str, "provider", 2) == 0)
+ return ROLE_PROVIDER;
+ if (strncmp(role_str, "customer", 2) == 0)
+ return ROLE_CUSTOMER;
+ if (strncmp(role_str, "rs-server", 4) == 0)
+ return ROLE_RS_SERVER;
+ if (strncmp(role_str, "rs-client", 4) == 0)
+ return ROLE_RS_CLIENT;
+ return ROLE_UNDEFINED;
+}
+
+static int peer_role_set_vty(struct vty *vty, struct peer *peer,
+ const char *role_str, bool strict_mode)
+{
+ uint8_t role = get_role_by_name(role_str);
+
+ if (role == ROLE_UNDEFINED)
+ return bgp_vty_return(vty, BGP_ERR_INVALID_ROLE_NAME);
+ return bgp_vty_return(vty, peer_role_set(peer, role, strict_mode));
+}
+
+DEFPY(neighbor_role,
+ neighbor_role_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer>$role",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set session role\n"
+ ROLE_STR)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_role_set_vty(vty, peer, role, false);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
+}
+
+DEFPY(neighbor_role_strict,
+ neighbor_role_strict_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer>$role strict-mode",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set session role\n"
+ ROLE_STR
+ "Use additional restriction on peer\n")
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_role_set_vty(vty, peer, role, true);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
+}
+
+DEFPY(no_neighbor_role,
+ no_neighbor_role_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer> [strict-mode]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set session role\n"
+ ROLE_STR
+ "Use additional restriction on peer\n")
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = bgp_vty_return(vty, peer_role_unset(peer));
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_UNSET);
+
+ return ret;
+}
+
+/* disable-connected-check */
+DEFUN (neighbor_disable_connected_check,
+ neighbor_disable_connected_check_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> <disable-connected-check|enforce-multihop>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "one-hop away EBGP peer using loopback address\n"
+ "Enforce EBGP neighbors perform multihop\n")
+{
+ int idx_peer = 1;
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_CONNECTED_CHECK);
+}
+
+DEFUN (no_neighbor_disable_connected_check,
+ no_neighbor_disable_connected_check_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> <disable-connected-check|enforce-multihop>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "one-hop away EBGP peer using loopback address\n"
+ "Enforce EBGP neighbors perform multihop\n")
+{
+ int idx_peer = 2;
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_CONNECTED_CHECK);
+}
+
+/* disable-link-bw-encoding-ieee */
+DEFUN(neighbor_disable_link_bw_encoding_ieee,
+ neighbor_disable_link_bw_encoding_ieee_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> disable-link-bw-encoding-ieee",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable IEEE floating-point encoding for extended community bandwidth\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
+}
+
+DEFUN(no_neighbor_disable_link_bw_encoding_ieee,
+ no_neighbor_disable_link_bw_encoding_ieee_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> disable-link-bw-encoding-ieee",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable IEEE floating-point encoding for extended community bandwidth\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
+}
+
+/* extended-optional-parameters */
+DEFUN(neighbor_extended_optional_parameters,
+ neighbor_extended_optional_parameters_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Force the extended optional parameters format for OPEN messages\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
+
+DEFUN(no_neighbor_extended_optional_parameters,
+ no_neighbor_extended_optional_parameters_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Force the extended optional parameters format for OPEN messages\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
+
+/* enforce-first-as */
+DEFUN (neighbor_enforce_first_as,
+ neighbor_enforce_first_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enforce the first AS for EBGP routes\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_ENFORCE_FIRST_AS);
+}
+
+DEFUN (no_neighbor_enforce_first_as,
+ no_neighbor_enforce_first_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enforce the first AS for EBGP routes\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_ENFORCE_FIRST_AS);
+}
+
+
+DEFUN (neighbor_description,
+ neighbor_description_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> description LINE...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Neighbor specific description\n"
+ "Up to 80 characters describing this neighbor\n")
+{
+ int idx_peer = 1;
+ int idx_line = 3;
+ struct peer *peer;
+ char *str;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ str = argv_concat(argv, argc, idx_line);
+
+ peer_description_set(peer, str);
+
+ XFREE(MTYPE_TMP, str);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_description,
+ no_neighbor_description_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> description",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Neighbor specific description\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ peer_description_unset(peer);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_neighbor_description, no_neighbor_description_comment_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> description LINE...",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Neighbor specific description\n"
+ "Up to 80 characters describing this neighbor\n")
+
+/* Neighbor update-source. */
+static int peer_update_source_vty(struct vty *vty, const char *peer_str,
+ const char *source_str)
+{
+ struct peer *peer;
+ struct prefix p;
+ union sockunion su;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->conf_if)
+ return CMD_WARNING;
+
+ if (source_str) {
+ if (str2sockunion(source_str, &su) == 0)
+ peer_update_source_addr_set(peer, &su);
+ else {
+ if (str2prefix(source_str, &p)) {
+ vty_out(vty,
+ "%% Invalid update-source, remove prefix length \n");
+ return CMD_WARNING_CONFIG_FAILED;
+ } else
+ peer_update_source_if_set(peer, source_str);
+ }
+ } else
+ peer_update_source_unset(peer);
+
+ return CMD_SUCCESS;
+}
+
+#define BGP_UPDATE_SOURCE_HELP_STR \
+ "IPv4 address\n" \
+ "IPv6 address\n" \
+ "Interface name (requires zebra to be running)\n"
+
+DEFUN (neighbor_update_source,
+ neighbor_update_source_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> update-source <A.B.C.D|X:X::X:X|WORD>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Source of routing updates\n"
+ BGP_UPDATE_SOURCE_HELP_STR)
+{
+ int idx_peer = 1;
+ int idx_peer_2 = 3;
+ return peer_update_source_vty(vty, argv[idx_peer]->arg,
+ argv[idx_peer_2]->arg);
+}
+
+DEFUN (no_neighbor_update_source,
+ no_neighbor_update_source_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> update-source [<A.B.C.D|X:X::X:X|WORD>]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Source of routing updates\n"
+ BGP_UPDATE_SOURCE_HELP_STR)
+{
+ int idx_peer = 2;
+ return peer_update_source_vty(vty, argv[idx_peer]->arg, NULL);
+}
+
+static int peer_default_originate_set_vty(struct vty *vty, const char *peer_str,
+ afi_t afi, safi_t safi,
+ const char *rmap, int set)
+{
+ int ret;
+ struct peer *peer;
+ struct route_map *route_map = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (set) {
+ if (rmap)
+ route_map = route_map_lookup_warn_noexist(vty, rmap);
+ ret = peer_default_originate_set(peer, afi, safi,
+ rmap, route_map);
+ } else
+ ret = peer_default_originate_unset(peer, afi, safi);
+
+ return bgp_vty_return(vty, ret);
+}
+
+/* neighbor default-originate. */
+DEFUN (neighbor_default_originate,
+ neighbor_default_originate_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> default-originate",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n")
+{
+ int idx_peer = 1;
+ return peer_default_originate_set_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty),
+ bgp_node_safi(vty), NULL, 1);
+}
+
+ALIAS_HIDDEN(neighbor_default_originate, neighbor_default_originate_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> default-originate",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n")
+
+DEFUN (neighbor_default_originate_rmap,
+ neighbor_default_originate_rmap_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> default-originate route-map RMAP_NAME",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n"
+ "Route-map to specify criteria to originate default\n"
+ "route-map name\n")
+{
+ int idx_peer = 1;
+ int idx_word = 4;
+ return peer_default_originate_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_word]->arg, 1);
+}
+
+ALIAS_HIDDEN(
+ neighbor_default_originate_rmap,
+ neighbor_default_originate_rmap_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> default-originate route-map RMAP_NAME",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n"
+ "Route-map to specify criteria to originate default\n"
+ "route-map name\n")
+
+DEFUN (no_neighbor_default_originate,
+ no_neighbor_default_originate_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> default-originate [route-map RMAP_NAME]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n"
+ "Route-map to specify criteria to originate default\n"
+ "route-map name\n")
+{
+ int idx_peer = 2;
+ return peer_default_originate_set_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty),
+ bgp_node_safi(vty), NULL, 0);
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_default_originate, no_neighbor_default_originate_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> default-originate [route-map RMAP_NAME]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Originate default route to this neighbor\n"
+ "Route-map to specify criteria to originate default\n"
+ "route-map name\n")
+
+
+/* Set neighbor's BGP port. */
+static int peer_port_vty(struct vty *vty, const char *ip_str, int afi,
+ const char *port_str)
+{
+ struct peer *peer;
+ uint16_t port;
+ struct servent *sp;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!port_str) {
+ sp = getservbyname("bgp", "tcp");
+ port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port);
+ } else {
+ port = strtoul(port_str, NULL, 10);
+ }
+
+ peer_port_set(peer, port);
+
+ return CMD_SUCCESS;
+}
+
+/* Set specified peer's BGP port. */
+DEFUN (neighbor_port,
+ neighbor_port_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> port (0-65535)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Neighbor's BGP port\n"
+ "TCP port number\n")
+{
+ int idx_ip = 1;
+ int idx_number = 3;
+ return peer_port_vty(vty, argv[idx_ip]->arg, AFI_IP,
+ argv[idx_number]->arg);
+}
+
+DEFUN (no_neighbor_port,
+ no_neighbor_port_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> port [(0-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Neighbor's BGP port\n"
+ "TCP port number\n")
+{
+ int idx_ip = 2;
+ return peer_port_vty(vty, argv[idx_ip]->arg, AFI_IP, NULL);
+}
+
+
+/* neighbor weight. */
+static int peer_weight_set_vty(struct vty *vty, const char *ip_str, afi_t afi,
+ safi_t safi, const char *weight_str)
+{
+ int ret;
+ struct peer *peer;
+ unsigned long weight;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ weight = strtoul(weight_str, NULL, 10);
+
+ ret = peer_weight_set(peer, afi, safi, weight);
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_weight_unset_vty(struct vty *vty, const char *ip_str, afi_t afi,
+ safi_t safi)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_weight_unset(peer, afi, safi);
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_weight,
+ neighbor_weight_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> weight (0-65535)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set default weight for routes from this neighbor\n"
+ "default weight\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ return peer_weight_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty), argv[idx_number]->arg);
+}
+
+ALIAS_HIDDEN(neighbor_weight, neighbor_weight_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> weight (0-65535)",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Set default weight for routes from this neighbor\n"
+ "default weight\n")
+
+DEFUN (no_neighbor_weight,
+ no_neighbor_weight_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> weight [(0-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set default weight for routes from this neighbor\n"
+ "default weight\n")
+{
+ int idx_peer = 2;
+ return peer_weight_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty));
+}
+
+ALIAS_HIDDEN(no_neighbor_weight, no_neighbor_weight_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> weight [(0-65535)]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Set default weight for routes from this neighbor\n"
+ "default weight\n")
+
+
+/* Override capability negotiation. */
+DEFUN (neighbor_override_capability,
+ neighbor_override_capability_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> override-capability",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override capability negotiation result\n")
+{
+ int idx_peer = 1;
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_OVERRIDE_CAPABILITY);
+}
+
+DEFUN (no_neighbor_override_capability,
+ no_neighbor_override_capability_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> override-capability",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Override capability negotiation result\n")
+{
+ int idx_peer = 2;
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_OVERRIDE_CAPABILITY);
+}
+
+DEFUN (neighbor_strict_capability,
+ neighbor_strict_capability_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> strict-capability-match",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Strict capability negotiation match\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_STRICT_CAP_MATCH);
+}
+
+DEFUN (no_neighbor_strict_capability,
+ no_neighbor_strict_capability_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> strict-capability-match",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Strict capability negotiation match\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_STRICT_CAP_MATCH);
+}
+
+static int peer_timers_set_vty(struct vty *vty, const char *ip_str,
+ const char *keep_str, const char *hold_str)
+{
+ int ret;
+ struct peer *peer;
+ uint32_t keepalive;
+ uint32_t holdtime;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ keepalive = strtoul(keep_str, NULL, 10);
+ holdtime = strtoul(hold_str, NULL, 10);
+
+ ret = peer_timers_set(peer, keepalive, holdtime);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_timers_unset_vty(struct vty *vty, const char *ip_str)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_timers_unset(peer);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_timers,
+ neighbor_timers_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> timers (0-65535) (0-65535)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "Keepalive interval\n"
+ "Holdtime\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ return peer_timers_set_vty(vty, argv[idx_peer]->arg,
+ argv[idx_number]->arg,
+ argv[idx_number_2]->arg);
+}
+
+DEFUN (no_neighbor_timers,
+ no_neighbor_timers_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> timers [(0-65535) (0-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "Keepalive interval\n"
+ "Holdtime\n")
+{
+ int idx_peer = 2;
+ return peer_timers_unset_vty(vty, argv[idx_peer]->arg);
+}
+
+
+static int peer_timers_connect_set_vty(struct vty *vty, const char *ip_str,
+ const char *time_str)
+{
+ int ret;
+ struct peer *peer;
+ uint32_t connect;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ connect = strtoul(time_str, NULL, 10);
+
+ ret = peer_timers_connect_set(peer, connect);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_timers_connect_unset_vty(struct vty *vty, const char *ip_str)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_timers_connect_unset(peer);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_timers_connect,
+ neighbor_timers_connect_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> timers connect (1-65535)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "BGP connect timer\n"
+ "Connect timer\n")
+{
+ int idx_peer = 1;
+ int idx_number = 4;
+ return peer_timers_connect_set_vty(vty, argv[idx_peer]->arg,
+ argv[idx_number]->arg);
+}
+
+DEFUN (no_neighbor_timers_connect,
+ no_neighbor_timers_connect_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> timers connect [(1-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "BGP connect timer\n"
+ "Connect timer\n")
+{
+ int idx_peer = 2;
+ return peer_timers_connect_unset_vty(vty, argv[idx_peer]->arg);
+}
+
+DEFPY (neighbor_timers_delayopen,
+ neighbor_timers_delayopen_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor timers delayopen (1-240)$interval",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "RFC 4271 DelayOpenTimer\n"
+ "DelayOpenTime timer interval\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!interval) {
+ if (peer_timers_delayopen_unset(peer))
+ return CMD_WARNING_CONFIG_FAILED;
+ } else {
+ if (peer_timers_delayopen_set(peer, interval))
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_neighbor_timers_delayopen,
+ no_neighbor_timers_delayopen_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor timers delayopen [(0-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP per neighbor timers\n"
+ "RFC 4271 DelayOpenTimer\n"
+ "DelayOpenTime timer interval\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer_timers_delayopen_unset(peer))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return CMD_SUCCESS;
+}
+
+static int peer_advertise_interval_vty(struct vty *vty, const char *ip_str,
+ const char *time_str, int set)
+{
+ int ret;
+ struct peer *peer;
+ uint32_t routeadv = 0;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (time_str)
+ routeadv = strtoul(time_str, NULL, 10);
+
+ if (set)
+ ret = peer_advertise_interval_set(peer, routeadv);
+ else
+ ret = peer_advertise_interval_unset(peer);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_advertise_interval,
+ neighbor_advertise_interval_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> advertisement-interval (0-600)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Minimum interval between sending BGP routing updates\n"
+ "time in seconds\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ return peer_advertise_interval_vty(vty, argv[idx_peer]->arg,
+ argv[idx_number]->arg, 1);
+}
+
+DEFUN (no_neighbor_advertise_interval,
+ no_neighbor_advertise_interval_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> advertisement-interval [(0-600)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Minimum interval between sending BGP routing updates\n"
+ "time in seconds\n")
+{
+ int idx_peer = 2;
+ return peer_advertise_interval_vty(vty, argv[idx_peer]->arg, NULL, 0);
+}
+
+
+/* Time to wait before processing route-map updates */
+DEFUN (bgp_set_route_map_delay_timer,
+ bgp_set_route_map_delay_timer_cmd,
+ "bgp route-map delay-timer (0-600)",
+ SET_STR
+ "BGP route-map delay timer\n"
+ "Time in secs to wait before processing route-map changes\n"
+ "0 disables the timer, no route updates happen when route-maps change\n")
+{
+ int idx_number = 3;
+ uint32_t rmap_delay_timer;
+
+ if (argv[idx_number]->arg) {
+ rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
+ bm->rmap_update_timer = rmap_delay_timer;
+
+ /* if the dynamic update handling is being disabled, and a timer
+ * is
+ * running, stop the timer and act as if the timer has already
+ * fired.
+ */
+ if (!rmap_delay_timer && bm->t_rmap_update) {
+ EVENT_OFF(bm->t_rmap_update);
+ event_execute(bm->master, bgp_route_map_update_timer,
+ NULL, 0, NULL);
+ }
+ return CMD_SUCCESS;
+ } else {
+ vty_out(vty, "%% BGP invalid route-map delay-timer\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+}
+
+DEFUN (no_bgp_set_route_map_delay_timer,
+ no_bgp_set_route_map_delay_timer_cmd,
+ "no bgp route-map delay-timer [(0-600)]",
+ NO_STR
+ BGP_STR
+ "Default BGP route-map delay timer\n"
+ "Reset to default time to wait for processing route-map changes\n"
+ "0 disables the timer, no route updates happen when route-maps change\n")
+{
+
+ bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
+
+ return CMD_SUCCESS;
+}
+
+/* neighbor interface */
+static int peer_interface_vty(struct vty *vty, const char *ip_str,
+ const char *str)
+{
+ struct peer *peer;
+
+ peer = peer_lookup_vty(vty, ip_str);
+ if (!peer || peer->conf_if) {
+ vty_out(vty, "%% BGP invalid peer %s\n", ip_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (str)
+ peer_interface_set(peer, str);
+ else
+ peer_interface_unset(peer);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_interface,
+ neighbor_interface_cmd,
+ "neighbor <A.B.C.D|X:X::X:X> interface WORD",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR
+ "Interface\n"
+ "Interface name\n")
+{
+ int idx_ip = 1;
+ int idx_word = 3;
+
+ return peer_interface_vty(vty, argv[idx_ip]->arg, argv[idx_word]->arg);
+}
+
+DEFUN (no_neighbor_interface,
+ no_neighbor_interface_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X> interface WORD",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR
+ "Interface\n"
+ "Interface name\n")
+{
+ int idx_peer = 2;
+
+ return peer_interface_vty(vty, argv[idx_peer]->arg, NULL);
+}
+
+DEFUN (neighbor_distribute_list,
+ neighbor_distribute_list_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list ACCESSLIST_NAME <in|out>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "IP Access-list name\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+{
+ int idx_peer = 1;
+ int idx_acl = 3;
+ int direct, ret;
+ struct peer *peer;
+
+ const char *pstr = argv[idx_peer]->arg;
+ const char *acl = argv[idx_acl]->arg;
+ const char *inout = argv[argc - 1]->text;
+
+ peer = peer_and_group_lookup_vty(vty, pstr);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ direct = strmatch(inout, "in") ? FILTER_IN : FILTER_OUT;
+ ret = peer_distribute_set(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ direct, acl);
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(
+ neighbor_distribute_list, neighbor_distribute_list_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list ACCESSLIST_NAME <in|out>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "IP Access-list name\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+
+DEFUN (no_neighbor_distribute_list,
+ no_neighbor_distribute_list_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list ACCESSLIST_NAME <in|out>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "IP Access-list name\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+{
+ int idx_peer = 2;
+ int direct, ret;
+ struct peer *peer;
+
+ const char *pstr = argv[idx_peer]->arg;
+ const char *inout = argv[argc - 1]->text;
+
+ peer = peer_and_group_lookup_vty(vty, pstr);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ direct = strmatch(inout, "in") ? FILTER_IN : FILTER_OUT;
+ ret = peer_distribute_unset(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ direct);
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_distribute_list, no_neighbor_distribute_list_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> distribute-list ACCESSLIST_NAME <in|out>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "IP Access-list name\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+
+/* Set prefix list to the peer. */
+static int peer_prefix_list_set_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *name_str,
+ const char *direct_str)
+{
+ int ret;
+ int direct = FILTER_IN;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "i", 1) == 0)
+ direct = FILTER_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = FILTER_OUT;
+
+ ret = peer_prefix_list_set(peer, afi, safi, direct, name_str);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_prefix_list_unset_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *direct_str)
+{
+ int ret;
+ struct peer *peer;
+ int direct = FILTER_IN;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "i", 1) == 0)
+ direct = FILTER_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = FILTER_OUT;
+
+ ret = peer_prefix_list_unset(peer, afi, safi, direct);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_prefix_list,
+ neighbor_prefix_list_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "Name of a prefix list\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+{
+ int idx_peer = 1;
+ int idx_word = 3;
+ int idx_in_out = 4;
+ return peer_prefix_list_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_word]->arg, argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(neighbor_prefix_list, neighbor_prefix_list_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "Name of a prefix list\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+
+DEFUN (no_neighbor_prefix_list,
+ no_neighbor_prefix_list_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "Name of a prefix list\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+{
+ int idx_peer = 2;
+ int idx_in_out = 5;
+ return peer_prefix_list_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(no_neighbor_prefix_list, no_neighbor_prefix_list_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Filter updates to/from this neighbor\n"
+ "Name of a prefix list\n"
+ "Filter incoming updates\n"
+ "Filter outgoing updates\n")
+
+static int peer_aslist_set_vty(struct vty *vty, const char *ip_str, afi_t afi,
+ safi_t safi, const char *name_str,
+ const char *direct_str)
+{
+ int ret;
+ struct peer *peer;
+ int direct = FILTER_IN;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "i", 1) == 0)
+ direct = FILTER_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = FILTER_OUT;
+
+ ret = peer_aslist_set(peer, afi, safi, direct, name_str);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_aslist_unset_vty(struct vty *vty, const char *ip_str, afi_t afi,
+ safi_t safi, const char *direct_str)
+{
+ int ret;
+ struct peer *peer;
+ int direct = FILTER_IN;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "i", 1) == 0)
+ direct = FILTER_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = FILTER_OUT;
+
+ ret = peer_aslist_unset(peer, afi, safi, direct);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_filter_list,
+ neighbor_filter_list_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Establish BGP filters\n"
+ "AS path access-list name\n"
+ "Filter incoming routes\n"
+ "Filter outgoing routes\n")
+{
+ int idx_peer = 1;
+ int idx_word = 3;
+ int idx_in_out = 4;
+ return peer_aslist_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
+ bgp_node_safi(vty), argv[idx_word]->arg,
+ argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Establish BGP filters\n"
+ "AS path access-list name\n"
+ "Filter incoming routes\n"
+ "Filter outgoing routes\n")
+
+DEFUN (no_neighbor_filter_list,
+ no_neighbor_filter_list_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Establish BGP filters\n"
+ "AS path access-list name\n"
+ "Filter incoming routes\n"
+ "Filter outgoing routes\n")
+{
+ int idx_peer = 2;
+ int idx_in_out = 5;
+ return peer_aslist_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> filter-list AS_PATH_FILTER_NAME <in|out>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Establish BGP filters\n"
+ "AS path access-list name\n"
+ "Filter incoming routes\n"
+ "Filter outgoing routes\n")
+
+/* Set advertise-map to the peer. */
+static int peer_advertise_map_set_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *advertise_str,
+ const char *condition_str, bool condition,
+ bool set)
+{
+ int ret = CMD_WARNING_CONFIG_FAILED;
+ struct peer *peer;
+ struct route_map *advertise_map;
+ struct route_map *condition_map;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return ret;
+
+ condition_map = route_map_lookup_warn_noexist(vty, condition_str);
+ advertise_map = route_map_lookup_warn_noexist(vty, advertise_str);
+
+ if (set)
+ ret = peer_advertise_map_set(peer, afi, safi, advertise_str,
+ advertise_map, condition_str,
+ condition_map, condition);
+ else
+ ret = peer_advertise_map_unset(peer, afi, safi, advertise_str,
+ advertise_map, condition_str,
+ condition_map, condition);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFPY (bgp_condadv_period,
+ bgp_condadv_period_cmd,
+ "[no$no] bgp conditional-advertisement timer (5-240)$period",
+ NO_STR
+ BGP_STR
+ "Conditional advertisement settings\n"
+ "Set period to rescan BGP table to check if condition is met\n"
+ "Period between BGP table scans, in seconds; default 60\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->condition_check_period =
+ no ? DEFAULT_CONDITIONAL_ROUTES_POLL_TIME : period;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_def_originate_eval,
+ bgp_def_originate_eval_cmd,
+ "[no$no] bgp default-originate timer (0-3600)$timer",
+ NO_STR
+ BGP_STR
+ "Control default-originate\n"
+ "Set period to rescan BGP table to check if default-originate condition is met\n"
+ "Period between BGP table scans, in seconds; default 5\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp->rmap_def_originate_eval_timer =
+ no ? RMAP_DEFAULT_ORIGINATE_EVAL_TIMER : timer;
+
+ if (bgp->t_rmap_def_originate_eval)
+ EVENT_OFF(bgp->t_rmap_def_originate_eval);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (neighbor_advertise_map,
+ neighbor_advertise_map_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map RMAP_NAME$advertise_str <exist-map|non-exist-map>$exist RMAP_NAME$condition_str",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Route-map to conditionally advertise routes\n"
+ "Name of advertise map\n"
+ "Advertise routes only if prefixes in exist-map are installed in BGP table\n"
+ "Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
+ "Name of the exist or non exist map\n")
+{
+ bool condition = CONDITION_EXIST;
+
+ if (!strcmp(exist, "non-exist-map"))
+ condition = CONDITION_NON_EXIST;
+
+ return peer_advertise_map_set_vty(vty, neighbor, bgp_node_afi(vty),
+ bgp_node_safi(vty), advertise_str,
+ condition_str, condition, !no);
+}
+
+ALIAS_HIDDEN(neighbor_advertise_map, neighbor_advertise_map_hidden_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map RMAP_NAME$advertise_str <exist-map|non-exist-map>$exist RMAP_NAME$condition_str",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Route-map to conditionally advertise routes\n"
+ "Name of advertise map\n"
+ "Advertise routes only if prefixes in exist-map are installed in BGP table\n"
+ "Advertise routes only if prefixes in non-exist-map are not installed in BGP table\n"
+ "Name of the exist or non exist map\n")
+
+/* Set route-map to the peer. */
+static int peer_route_map_set_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi, const char *name_str,
+ const char *direct_str)
+{
+ int ret;
+ struct peer *peer;
+ int direct = RMAP_IN;
+ struct route_map *route_map;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "in", 2) == 0)
+ direct = RMAP_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = RMAP_OUT;
+
+ route_map = route_map_lookup_warn_noexist(vty, name_str);
+ ret = peer_route_map_set(peer, afi, safi, direct, name_str, route_map);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_route_map_unset_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *direct_str)
+{
+ int ret;
+ struct peer *peer;
+ int direct = RMAP_IN;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* Check filter direction. */
+ if (strncmp(direct_str, "in", 2) == 0)
+ direct = RMAP_IN;
+ else if (strncmp(direct_str, "o", 1) == 0)
+ direct = RMAP_OUT;
+
+ ret = peer_route_map_unset(peer, afi, safi, direct);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_route_map,
+ neighbor_route_map_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-map RMAP_NAME <in|out>",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Apply route map to neighbor\n"
+ "Name of route map\n"
+ "Apply map to incoming routes\n"
+ "Apply map to outbound routes\n")
+{
+ int idx_peer = 1;
+ int idx_word = 3;
+ int idx_in_out = 4;
+ return peer_route_map_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_word]->arg, argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(neighbor_route_map, neighbor_route_map_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> route-map RMAP_NAME <in|out>",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Apply route map to neighbor\n"
+ "Name of route map\n"
+ "Apply map to incoming routes\n"
+ "Apply map to outbound routes\n")
+
+DEFUN (no_neighbor_route_map,
+ no_neighbor_route_map_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-map RMAP_NAME <in|out>",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Apply route map to neighbor\n"
+ "Name of route map\n"
+ "Apply map to incoming routes\n"
+ "Apply map to outbound routes\n")
+{
+ int idx_peer = 2;
+ int idx_in_out = 5;
+ return peer_route_map_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_in_out]->arg);
+}
+
+ALIAS_HIDDEN(no_neighbor_route_map, no_neighbor_route_map_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> route-map RMAP_NAME <in|out>",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Apply route map to neighbor\n"
+ "Name of route map\n"
+ "Apply map to incoming routes\n"
+ "Apply map to outbound routes\n")
+
+/* Set unsuppress-map to the peer. */
+static int peer_unsuppress_map_set_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *name_str)
+{
+ int ret;
+ struct peer *peer;
+ struct route_map *route_map;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ route_map = route_map_lookup_warn_noexist(vty, name_str);
+ ret = peer_unsuppress_map_set(peer, afi, safi, name_str, route_map);
+
+ return bgp_vty_return(vty, ret);
+}
+
+/* Unset route-map from the peer. */
+static int peer_unsuppress_map_unset_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_unsuppress_map_unset(peer, afi, safi);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN (neighbor_unsuppress_map,
+ neighbor_unsuppress_map_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> unsuppress-map WORD",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Route-map to selectively unsuppress suppressed routes\n"
+ "Name of route map\n")
+{
+ int idx_peer = 1;
+ int idx_word = 3;
+ return peer_unsuppress_map_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_word]->arg);
+}
+
+ALIAS_HIDDEN(neighbor_unsuppress_map, neighbor_unsuppress_map_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> unsuppress-map WORD",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Route-map to selectively unsuppress suppressed routes\n"
+ "Name of route map\n")
+
+DEFUN (no_neighbor_unsuppress_map,
+ no_neighbor_unsuppress_map_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> unsuppress-map WORD",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Route-map to selectively unsuppress suppressed routes\n"
+ "Name of route map\n")
+{
+ int idx_peer = 2;
+ return peer_unsuppress_map_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty),
+ bgp_node_safi(vty));
+}
+
+ALIAS_HIDDEN(no_neighbor_unsuppress_map, no_neighbor_unsuppress_map_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> unsuppress-map WORD",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Route-map to selectively unsuppress suppressed routes\n"
+ "Name of route map\n")
+
+static int peer_maximum_prefix_set_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi,
+ const char *num_str,
+ const char *threshold_str, int warning,
+ const char *restart_str,
+ const char *force_str)
+{
+ int ret;
+ struct peer *peer;
+ uint32_t max;
+ uint8_t threshold;
+ uint16_t restart;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ max = strtoul(num_str, NULL, 10);
+ if (threshold_str)
+ threshold = atoi(threshold_str);
+ else
+ threshold = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
+
+ if (restart_str)
+ restart = atoi(restart_str);
+ else
+ restart = 0;
+
+ ret = peer_maximum_prefix_set(peer, afi, safi, max, threshold, warning,
+ restart, force_str ? true : false);
+
+ return bgp_vty_return(vty, ret);
+}
+
+static int peer_maximum_prefix_unset_vty(struct vty *vty, const char *ip_str,
+ afi_t afi, safi_t safi)
+{
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, ip_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_maximum_prefix_unset(peer, afi, safi);
+
+ return bgp_vty_return(vty, ret);
+}
+
+/* Maximum number of prefix to be sent to the neighbor. */
+DEFUN(neighbor_maximum_prefix_out,
+ neighbor_maximum_prefix_out_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix-out (1-4294967295)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to be sent to this peer\n"
+ "Maximum no. of prefix limit\n")
+{
+ int ret;
+ int idx_peer = 1;
+ int idx_number = 3;
+ struct peer *peer;
+ uint32_t max;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ max = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ ret = peer_maximum_prefix_out_set(peer, afi, safi, max);
+
+ return bgp_vty_return(vty, ret);
+}
+
+DEFUN(no_neighbor_maximum_prefix_out,
+ no_neighbor_maximum_prefix_out_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix-out [(1-4294967295)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to be sent to this peer\n"
+ "Maximum no. of prefix limit\n")
+{
+ int ret;
+ int idx_peer = 2;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_maximum_prefix_out_unset(peer, afi, safi);
+
+ return bgp_vty_return(vty, ret);
+}
+
+/* Maximum number of prefix configuration. Prefix count is different
+ for each peer configuration. So this configuration can be set for
+ each peer configuration. */
+DEFUN (neighbor_maximum_prefix,
+ neighbor_maximum_prefix_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, NULL, 0, NULL, force);
+}
+
+ALIAS_HIDDEN(neighbor_maximum_prefix, neighbor_maximum_prefix_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (neighbor_maximum_prefix_threshold,
+ neighbor_maximum_prefix_threshold_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, argv[idx_number_2]->arg, 0, NULL, force);
+}
+
+ALIAS_HIDDEN(
+ neighbor_maximum_prefix_threshold,
+ neighbor_maximum_prefix_threshold_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (neighbor_maximum_prefix_warning,
+ neighbor_maximum_prefix_warning_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) warning-only [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, NULL, 1, NULL, force);
+}
+
+ALIAS_HIDDEN(
+ neighbor_maximum_prefix_warning,
+ neighbor_maximum_prefix_warning_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) warning-only [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (neighbor_maximum_prefix_threshold_warning,
+ neighbor_maximum_prefix_threshold_warning_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) warning-only [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, argv[idx_number_2]->arg, 1, NULL, force);
+}
+
+ALIAS_HIDDEN(
+ neighbor_maximum_prefix_threshold_warning,
+ neighbor_maximum_prefix_threshold_warning_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) warning-only [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (neighbor_maximum_prefix_restart,
+ neighbor_maximum_prefix_restart_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) restart (1-65535) [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_number_2 = 5;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, NULL, 0, argv[idx_number_2]->arg, force);
+}
+
+ALIAS_HIDDEN(
+ neighbor_maximum_prefix_restart,
+ neighbor_maximum_prefix_restart_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) restart (1-65535) [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefix accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (neighbor_maximum_prefix_threshold_restart,
+ neighbor_maximum_prefix_threshold_restart_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) restart (1-65535) [force]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 1;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_number_3 = 6;
+ int idx_force = 0;
+ char *force = NULL;
+
+ if (argv_find(argv, argc, "force", &idx_force))
+ force = argv[idx_force]->arg;
+
+ return peer_maximum_prefix_set_vty(
+ vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty),
+ argv[idx_number]->arg, argv[idx_number_2]->arg, 0,
+ argv[idx_number_3]->arg, force);
+}
+
+ALIAS_HIDDEN(
+ neighbor_maximum_prefix_threshold_restart,
+ neighbor_maximum_prefix_threshold_restart_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295) (1-100) restart (1-65535) [force]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Force checking all received routes not only accepted\n")
+
+DEFUN (no_neighbor_maximum_prefix,
+ no_neighbor_maximum_prefix_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix [(1-4294967295) [(1-100)] [restart (1-65535)] [warning-only] [force]]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+{
+ int idx_peer = 2;
+ return peer_maximum_prefix_unset_vty(vty, argv[idx_peer]->arg,
+ bgp_node_afi(vty),
+ bgp_node_safi(vty));
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_maximum_prefix, no_neighbor_maximum_prefix_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix [(1-4294967295) [(1-100)] [restart (1-65535)] [warning-only] [force]]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Maximum number of prefixes to accept from this peer\n"
+ "maximum no. of prefix limit\n"
+ "Threshold value (%) at which to generate a warning msg\n"
+ "Restart bgp connection after limit is exceeded\n"
+ "Restart interval in minutes\n"
+ "Only give warning message when limit is exceeded\n"
+ "Force checking all received routes not only accepted\n")
+
+/* "neighbor accept-own" */
+DEFPY (neighbor_accept_own,
+ neighbor_accept_own_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor accept-own",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable handling of self-originated VPN routes containing ACCEPT_OWN community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ ret = peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ACCEPT_OWN);
+ else
+ ret = peer_af_flag_set(peer, afi, safi, PEER_FLAG_ACCEPT_OWN);
+
+ return bgp_vty_return(vty, ret);
+}
+
+/* "neighbor soo" */
+DEFPY (neighbor_soo,
+ neighbor_soo_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor soo ASN:NN_OR_IP-ADDRESS:NN$soo",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set the Site-of-Origin (SoO) extended community\n"
+ "VPN extended community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ struct ecommunity *ecomm_soo;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ecomm_soo = ecommunity_str2com(soo, ECOMMUNITY_SITE_ORIGIN, 0);
+ if (!ecomm_soo) {
+ vty_out(vty, "%% Malformed SoO extended community\n");
+ return CMD_WARNING;
+ }
+ ecommunity_str(ecomm_soo);
+
+ if (!ecommunity_match(peer->soo[afi][safi], ecomm_soo)) {
+ ecommunity_free(&peer->soo[afi][safi]);
+ peer->soo[afi][safi] = ecomm_soo;
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_SOO);
+ } else {
+ ecommunity_free(&ecomm_soo);
+ }
+
+ return bgp_vty_return(vty,
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_SOO));
+}
+
+DEFPY (no_neighbor_soo,
+ no_neighbor_soo_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor soo [ASN:NN_OR_IP-ADDRESS:NN$soo]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set the Site-of-Origin (SoO) extended community\n"
+ "VPN extended community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ecommunity_free(&peer->soo[afi][safi]);
+
+ return bgp_vty_return(
+ vty, peer_af_flag_unset(peer, afi, safi, PEER_FLAG_SOO));
+}
+
+/* "neighbor allowas-in" */
+DEFUN (neighbor_allowas_in,
+ neighbor_allowas_in_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Accept as-path with my AS present in it\n"
+ "Number of occurrences of AS number\n"
+ "Only accept my AS in the as-path if the route was originated in my AS\n")
+{
+ int idx_peer = 1;
+ int idx_number_origin = 3;
+ int ret;
+ int origin = 0;
+ struct peer *peer;
+ int allow_num = 0;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (argc <= idx_number_origin)
+ allow_num = 3;
+ else {
+ if (argv[idx_number_origin]->type == WORD_TKN)
+ origin = 1;
+ else
+ allow_num = atoi(argv[idx_number_origin]->arg);
+ }
+
+ ret = peer_allowas_in_set(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ allow_num, origin);
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(
+ neighbor_allowas_in, neighbor_allowas_in_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Accept as-path with my AS present in it\n"
+ "Number of occurrences of AS number\n"
+ "Only accept my AS in the as-path if the route was originated in my AS\n")
+
+DEFUN (no_neighbor_allowas_in,
+ no_neighbor_allowas_in_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "allow local ASN appears in aspath attribute\n"
+ "Number of occurrences of AS number\n"
+ "Only accept my AS in the as-path if the route was originated in my AS\n")
+{
+ int idx_peer = 2;
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_allowas_in_unset(peer, bgp_node_afi(vty),
+ bgp_node_safi(vty));
+
+ return bgp_vty_return(vty, ret);
+}
+
+ALIAS_HIDDEN(
+ no_neighbor_allowas_in, no_neighbor_allowas_in_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "allow local ASN appears in aspath attribute\n"
+ "Number of occurrences of AS number\n"
+ "Only accept my AS in the as-path if the route was originated in my AS\n")
+
+DEFUN (neighbor_ttl_security,
+ neighbor_ttl_security_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> ttl-security hops (1-254)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP ttl-security parameters\n"
+ "Specify the maximum number of hops to the BGP peer\n"
+ "Number of hops to BGP peer\n")
+{
+ int idx_peer = 1;
+ int idx_number = 4;
+ struct peer *peer;
+ int gtsm_hops;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ gtsm_hops = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ /*
+ * If 'neighbor swpX', then this is for directly connected peers,
+ * we should not accept a ttl-security hops value greater than 1.
+ */
+ if (peer->conf_if && (gtsm_hops > BGP_GTSM_HOPS_CONNECTED)) {
+ vty_out(vty,
+ "%s is directly connected peer, hops cannot exceed 1\n",
+ argv[idx_peer]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return bgp_vty_return(vty, peer_ttl_security_hops_set(peer, gtsm_hops));
+}
+
+DEFUN (no_neighbor_ttl_security,
+ no_neighbor_ttl_security_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> ttl-security hops (1-254)",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "BGP ttl-security parameters\n"
+ "Specify the maximum number of hops to the BGP peer\n"
+ "Number of hops to BGP peer\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return bgp_vty_return(vty, peer_ttl_security_hops_unset(peer));
+}
+
+/* disable-addpath-rx */
+DEFUN(neighbor_disable_addpath_rx,
+ neighbor_disable_addpath_rx_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> disable-addpath-rx",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not accept additional paths\n")
+{
+ char *peer_str = argv[1]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+}
+
+DEFUN(no_neighbor_disable_addpath_rx,
+ no_neighbor_disable_addpath_rx_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> disable-addpath-rx",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not accept additional paths\n")
+{
+ char *peer_str = argv[2]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+}
+
+DEFUN (neighbor_addpath_tx_all_paths,
+ neighbor_addpath_tx_all_paths_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise all paths to a neighbor\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_ALL, 0);
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(neighbor_addpath_tx_all_paths,
+ neighbor_addpath_tx_all_paths_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise all paths to a neighbor\n")
+
+DEFUN (no_neighbor_addpath_tx_all_paths,
+ no_neighbor_addpath_tx_all_paths_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise all paths to a neighbor\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
+ != BGP_ADDPATH_ALL) {
+ vty_out(vty,
+ "%% Peer not currently configured to transmit all paths.");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_NONE, 0);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(no_neighbor_addpath_tx_all_paths,
+ no_neighbor_addpath_tx_all_paths_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise all paths to a neighbor\n")
+
+DEFPY (neighbor_addpath_tx_best_selected_paths,
+ neighbor_addpath_tx_best_selected_paths_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-tx-best-selected (1-6)$paths",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise best selected paths to a neighbor\n"
+ "The number of best paths\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_BEST_SELECTED, paths);
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_neighbor_addpath_tx_best_selected_paths,
+ no_neighbor_addpath_tx_best_selected_paths_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-tx-best-selected [(1-6)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise best selected paths to a neighbor\n"
+ "The number of best paths\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_BEST_SELECTED, 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_addpath_tx_bestpath_per_as,
+ neighbor_addpath_tx_bestpath_per_as_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise the bestpath per each neighboring AS\n")
+{
+ int idx_peer = 1;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_BEST_PER_AS, 0);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(neighbor_addpath_tx_bestpath_per_as,
+ neighbor_addpath_tx_bestpath_per_as_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise the bestpath per each neighboring AS\n")
+
+DEFUN (no_neighbor_addpath_tx_bestpath_per_as,
+ no_neighbor_addpath_tx_bestpath_per_as_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise the bestpath per each neighboring AS\n")
+{
+ int idx_peer = 2;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
+ != BGP_ADDPATH_BEST_PER_AS) {
+ vty_out(vty,
+ "%% Peer not currently configured to transmit all best path per as.");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ BGP_ADDPATH_NONE, 0);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as,
+ no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Use addpath to advertise the bestpath per each neighboring AS\n")
+
+DEFPY(
+ neighbor_aspath_loop_detection, neighbor_aspath_loop_detection_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor sender-as-path-loop-detection",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Detect AS loops before sending to neighbor\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ peer->as_path_loop_detection = true;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(
+ no_neighbor_aspath_loop_detection,
+ no_neighbor_aspath_loop_detection_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor sender-as-path-loop-detection",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Detect AS loops before sending to neighbor\n")
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ peer->as_path_loop_detection = false;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(neighbor_path_attribute_discard,
+ neighbor_path_attribute_discard_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard (1-255)...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Drop specified attributes from incoming UPDATE messages\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ char *discard_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ discard_attrs = argv_concat(argv, argc, idx);
+
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs, true);
+
+ XFREE(MTYPE_TMP, discard_attrs);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_neighbor_path_attribute_discard,
+ no_neighbor_path_attribute_discard_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard [(1-255)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Drop specified attributes from incoming UPDATE messages\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ char *discard_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ discard_attrs = argv[idx]->arg;
+
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs, false);
+
+ XFREE(MTYPE_TMP, discard_attrs);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(neighbor_path_attribute_treat_as_withdraw,
+ neighbor_path_attribute_treat_as_withdraw_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute treat-as-withdraw (1-255)...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Treat-as-withdraw any incoming BGP UPDATE messages that contain the specified attribute\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ char *withdraw_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ withdraw_attrs = argv_concat(argv, argc, idx);
+
+ bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, true);
+
+ XFREE(MTYPE_TMP, withdraw_attrs);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_neighbor_path_attribute_treat_as_withdraw,
+ no_neighbor_path_attribute_treat_as_withdraw_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute treat-as-withdraw (1-255)...",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Treat-as-withdraw any incoming BGP UPDATE messages that contain the specified attribute\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ char *withdraw_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ withdraw_attrs = argv_concat(argv, argc, idx);
+
+ bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, false);
+
+ XFREE(MTYPE_TMP, withdraw_attrs);
+
+ return CMD_SUCCESS;
+}
+
+static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
+ struct ecommunity **list, bool is_rt6)
+{
+ struct ecommunity *ecom = NULL;
+ struct ecommunity *ecomadd;
+
+ for (; argc; --argc, ++argv) {
+ if (is_rt6)
+ ecomadd = ecommunity_str2com_ipv6(argv[0]->arg,
+ ECOMMUNITY_ROUTE_TARGET,
+ 0);
+ else
+ ecomadd = ecommunity_str2com(argv[0]->arg,
+ ECOMMUNITY_ROUTE_TARGET,
+ 0);
+ if (!ecomadd) {
+ vty_out(vty, "Malformed community-list value\n");
+ if (ecom)
+ ecommunity_free(&ecom);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (ecom) {
+ ecommunity_merge(ecom, ecomadd);
+ ecommunity_free(&ecomadd);
+ } else {
+ ecom = ecomadd;
+ }
+ }
+
+ if (*list) {
+ ecommunity_free(&*list);
+ }
+ *list = ecom;
+
+ return CMD_SUCCESS;
+}
+
+/*
+ * v2vimport is true if we are handling a `import vrf ...` command
+ */
+static afi_t vpn_policy_getafi(struct vty *vty, struct bgp *bgp, bool v2vimport)
+{
+ afi_t afi;
+
+ switch (vty->node) {
+ case BGP_IPV4_NODE:
+ afi = AFI_IP;
+ break;
+ case BGP_IPV6_NODE:
+ afi = AFI_IP6;
+ break;
+ default:
+ vty_out(vty,
+ "%% context error: valid only in address-family <ipv4|ipv6> unicast block\n");
+ return AFI_MAX;
+ }
+
+ if (!v2vimport) {
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)
+ || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
+ vty_out(vty,
+ "%% error: Please unconfigure import vrf commands before using vpn commands\n");
+ return AFI_MAX;
+ }
+ } else {
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
+ || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
+ vty_out(vty,
+ "%% error: Please unconfigure vpn to vrf commands before using import vrf commands\n");
+ return AFI_MAX;
+ }
+ }
+ return afi;
+}
+
+DEFPY (af_rd_vpn_export,
+ af_rd_vpn_export_cmd,
+ "[no] rd vpn export ASN:NN_OR_IP-ADDRESS:NN$rd_str",
+ NO_STR
+ "Specify route distinguisher\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n"
+ "Route Distinguisher (<as-number>:<number> | <ip-address>:<number>)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct prefix_rd prd;
+ int ret;
+ afi_t afi;
+ int idx = 0;
+ bool yes = true;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ if (yes) {
+ ret = str2prefix_rd(rd_str, &prd);
+ if (!ret) {
+ vty_out(vty, "%% Malformed rd\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /*
+ * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+ */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ if (yes) {
+ bgp->vpn_policy[afi].tovpn_rd_pretty =
+ XSTRDUP(MTYPE_BGP, rd_str);
+ bgp->vpn_policy[afi].tovpn_rd = prd;
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET);
+ } else {
+ XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET);
+ }
+
+ /* post-change: re-export vpn routes */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (af_rd_vpn_export,
+ af_no_rd_vpn_export_cmd,
+ "no rd vpn export",
+ NO_STR
+ "Specify route distinguisher\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n")
+
+DEFPY(af_label_vpn_export_allocation_mode,
+ af_label_vpn_export_allocation_mode_cmd,
+ "[no$no] label vpn export allocation-mode <per-vrf$label_per_vrf|per-nexthop$label_per_nh>",
+ NO_STR
+ "label value for VRF\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n"
+ "Label allocation mode\n"
+ "Allocate one label for all BGP updates of the VRF\n"
+ "Allocate a label per connected next-hop in the VRF\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ bool old_per_nexthop, new_per_nexthop;
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ old_per_nexthop = !!CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP);
+ if (no) {
+ if (old_per_nexthop == false && label_per_nh)
+ return CMD_ERR_NO_MATCH;
+ if (old_per_nexthop == true && label_per_vrf)
+ return CMD_ERR_NO_MATCH;
+ new_per_nexthop = false;
+ } else {
+ if (label_per_nh)
+ new_per_nexthop = true;
+ else
+ new_per_nexthop = false;
+ }
+
+ /* no change */
+ if (old_per_nexthop == new_per_nexthop)
+ return CMD_SUCCESS;
+
+ /*
+ * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+ */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(),
+ bgp);
+
+ if (new_per_nexthop)
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP);
+ else
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP);
+
+ /* post-change: re-export vpn routes */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(),
+ bgp);
+
+ hook_call(bgp_snmp_update_last_changed, bgp);
+ return CMD_SUCCESS;
+}
+
+DEFPY (af_label_vpn_export,
+ af_label_vpn_export_cmd,
+ "[no] label vpn export <(0-1048575)$label_val|auto$label_auto>",
+ NO_STR
+ "label value for VRF\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n"
+ "Label Value <0-1048575>\n"
+ "Automatically assign a label\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ mpls_label_t label = MPLS_LABEL_NONE;
+ afi_t afi;
+ int idx = 0;
+ bool yes = true;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ /* If "no ...", squash trailing parameter */
+ if (!yes)
+ label_auto = NULL;
+
+ if (yes) {
+ if (!label_auto)
+ label = label_val; /* parser should force unsigned */
+ }
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+
+ if (label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO))
+ /* no change */
+ return CMD_SUCCESS;
+
+ /*
+ * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+ */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ if (!label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+
+ if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
+
+ /*
+ * label has previously been automatically
+ * assigned by labelpool: release it
+ *
+ * NB if tovpn_label == MPLS_LABEL_NONE it
+ * means the automatic assignment is in flight
+ * and therefore the labelpool callback must
+ * detect that the auto label is not needed.
+ */
+
+ bgp_lp_release(LP_TYPE_VRF,
+ &bgp->vpn_policy[afi],
+ bgp->vpn_policy[afi].tovpn_label);
+ }
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
+ }
+
+ bgp->vpn_policy[afi].tovpn_label = label;
+ if (label_auto) {
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
+ bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
+ vpn_leak_label_callback);
+ }
+
+ /* post-change: re-export vpn routes */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ hook_call(bgp_snmp_update_last_changed, bgp);
+ return CMD_SUCCESS;
+}
+
+DEFPY (af_sid_vpn_export,
+ af_sid_vpn_export_cmd,
+ "[no] sid vpn export <(1-1048575)$sid_idx|auto$sid_auto>",
+ NO_STR
+ "sid value for VRF\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n"
+ "Sid allocation index\n"
+ "Automatically assign a label\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ int debug = 0;
+ int idx = 0;
+ bool yes = true;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+ debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+ BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!yes) {
+ /* when SID is not set, do nothing */
+ if ((bgp->vpn_policy[afi].tovpn_sid_index == 0) &&
+ !CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO))
+ return CMD_SUCCESS;
+
+ /* pre-change */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+ bgp->vpn_policy[afi].tovpn_sid_index = 0;
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO);
+
+ /* post-change */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+ }
+
+ if (bgp->tovpn_sid_index != 0 ||
+ CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) {
+ vty_out(vty,
+ "per-vrf sid and per-af sid are mutually exclusive\n"
+ "Failed: per-vrf sid is configured. Remove per-vrf sid before configuring per-af sid\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* skip when it's already configured */
+ if ((sid_idx != 0 && bgp->vpn_policy[afi].tovpn_sid_index != 0)
+ || (sid_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO)))
+ return CMD_SUCCESS;
+
+ /*
+ * mode change between sid_idx and sid_auto isn't supported.
+ * user must negate sid vpn export when they want to change the mode
+ */
+ if ((sid_auto && bgp->vpn_policy[afi].tovpn_sid_index != 0)
+ || (sid_idx != 0 && CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO))) {
+ vty_out(vty, "it's already configured as %s.\n",
+ sid_auto ? "auto-mode" : "idx-mode");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* pre-change */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ if (sid_auto) {
+ /* SID allocation auto-mode */
+ if (debug)
+ zlog_debug("%s: auto sid alloc.", __func__);
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO);
+ } else if (sid_idx != 0) {
+ /* SID allocation index-mode */
+ if (debug)
+ zlog_debug("%s: idx %ld sid alloc.", __func__, sid_idx);
+ bgp->vpn_policy[afi].tovpn_sid_index = sid_idx;
+ }
+
+ /* post-change */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_sid_vpn_export,
+ bgp_sid_vpn_export_cmd,
+ "[no] sid vpn per-vrf export <(1-1048575)$sid_idx|auto$sid_auto>",
+ NO_STR
+ "sid value for VRF\n"
+ "Between current vrf and vpn\n"
+ "sid per-VRF (both IPv4 and IPv6 address families)\n"
+ "For routes leaked from current vrf to vpn\n"
+ "Sid allocation index\n"
+ "Automatically assign a label\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int debug;
+
+ debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+ BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
+ if (no) {
+ /* when per-VRF SID is not set, do nothing */
+ if (bgp->tovpn_sid_index == 0 &&
+ !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
+ return CMD_SUCCESS;
+
+ sid_idx = 0;
+ sid_auto = false;
+ bgp->tovpn_sid_index = 0;
+ UNSET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
+ }
+
+ if (bgp->vpn_policy[AFI_IP].tovpn_sid_index != 0 ||
+ CHECK_FLAG(bgp->vpn_policy[AFI_IP].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO) ||
+ bgp->vpn_policy[AFI_IP6].tovpn_sid_index != 0 ||
+ CHECK_FLAG(bgp->vpn_policy[AFI_IP6].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO)) {
+ vty_out(vty,
+ "per-vrf sid and per-af sid are mutually exclusive\n"
+ "Failed: per-af sid is configured. Remove per-af sid before configuring per-vrf sid\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* skip when it's already configured */
+ if ((sid_idx != 0 && bgp->tovpn_sid_index != 0) ||
+ (sid_auto && CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)))
+ return CMD_SUCCESS;
+
+ /*
+ * mode change between sid_idx and sid_auto isn't supported.
+ * user must negate sid vpn export when they want to change the mode
+ */
+ if ((sid_auto && bgp->tovpn_sid_index != 0) ||
+ (sid_idx != 0 &&
+ CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))) {
+ vty_out(vty, "it's already configured as %s.\n",
+ sid_auto ? "auto-mode" : "idx-mode");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* pre-change */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(),
+ bgp);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(),
+ bgp);
+
+ if (sid_auto) {
+ /* SID allocation auto-mode */
+ if (debug)
+ zlog_debug("%s: auto per-vrf sid alloc.", __func__);
+ SET_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
+ } else if (sid_idx != 0) {
+ /* SID allocation index-mode */
+ if (debug)
+ zlog_debug("%s: idx %ld per-vrf sid alloc.", __func__,
+ sid_idx);
+ bgp->tovpn_sid_index = sid_idx;
+ }
+
+ /* post-change */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(),
+ bgp);
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6,
+ bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (af_label_vpn_export,
+ af_no_label_vpn_export_cmd,
+ "no label vpn export",
+ NO_STR
+ "label value for VRF\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n")
+
+ALIAS (bgp_sid_vpn_export,
+ no_bgp_sid_vpn_export_cmd,
+ "no$no sid vpn per-vrf export",
+ NO_STR
+ "sid value for VRF\n"
+ "Between current vrf and vpn\n"
+ "sid per-VRF (both IPv4 and IPv6 address families)\n"
+ "For routes leaked from current vrf to vpn\n")
+
+DEFPY (af_nexthop_vpn_export,
+ af_nexthop_vpn_export_cmd,
+ "[no] nexthop vpn export [<A.B.C.D|X:X::X:X>$nexthop_su]",
+ NO_STR
+ "Specify next hop to use for VRF advertised prefixes\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from current address-family to vpn\n"
+ "IPv4 prefix\n"
+ "IPv6 prefix\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ struct prefix p;
+
+ if (!no) {
+ if (!nexthop_su) {
+ vty_out(vty, "%% Nexthop required\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (!sockunion2hostprefix(nexthop_su, &p))
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /*
+ * pre-change: un-export vpn routes (vpn->vrf routes unaffected)
+ */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ if (!no) {
+ bgp->vpn_policy[afi].tovpn_nexthop = p;
+ SET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+ } else {
+ UNSET_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
+ }
+
+ /* post-change: re-export vpn routes */
+ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
+ bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+}
+
+static int vpn_policy_getdirs(struct vty *vty, const char *dstr, int *dodir)
+{
+ if (!strcmp(dstr, "import")) {
+ dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+ } else if (!strcmp(dstr, "export")) {
+ dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+ } else if (!strcmp(dstr, "both")) {
+ dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
+ dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
+ } else {
+ vty_out(vty, "%% direction parse error\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY (af_rt_vpn_imexport,
+ af_rt_vpn_imexport_cmd,
+ "[no] <rt|route-target> vpn <import|export|both>$direction_str RTLIST...",
+ NO_STR
+ "Specify route target list\n"
+ "Specify route target list\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from vpn to current address-family: match any\n"
+ "For routes leaked from current address-family to vpn: set\n"
+ "both import: match any and export: set\n"
+ "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+ struct ecommunity *ecom = NULL;
+ int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
+ enum vpn_policy_direction dir;
+ afi_t afi;
+ int idx = 0;
+ bool yes = true;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = vpn_policy_getdirs(vty, direction_str, dodir);
+ if (ret != CMD_SUCCESS)
+ return ret;
+
+ if (yes) {
+ if (!argv_find(argv, argc, "RTLIST", &idx)) {
+ vty_out(vty, "%% Missing RTLIST\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom, false);
+ if (ret != CMD_SUCCESS) {
+ return ret;
+ }
+ }
+
+ for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+ if (!dodir[dir])
+ continue;
+
+ vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+
+ if (yes) {
+ if (bgp->vpn_policy[afi].rtlist[dir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[dir]);
+ bgp->vpn_policy[afi].rtlist[dir] =
+ ecommunity_dup(ecom);
+ } else {
+ if (bgp->vpn_policy[afi].rtlist[dir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[dir]);
+ bgp->vpn_policy[afi].rtlist[dir] = NULL;
+ }
+
+ vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
+ }
+
+ if (ecom)
+ ecommunity_free(&ecom);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (af_rt_vpn_imexport,
+ af_no_rt_vpn_imexport_cmd,
+ "no <rt|route-target> vpn <import|export|both>$direction_str",
+ NO_STR
+ "Specify route target list\n"
+ "Specify route target list\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from vpn to current address-family\n"
+ "For routes leaked from current address-family to vpn\n"
+ "both import and export\n")
+
+DEFPY (af_route_map_vpn_imexport,
+ af_route_map_vpn_imexport_cmd,
+/* future: "route-map <vpn|evpn|vrf NAME> <import|export> RMAP" */
+ "[no] route-map vpn <import|export>$direction_str RMAP$rmap_str",
+ NO_STR
+ "Specify route map\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from vpn to current address-family\n"
+ "For routes leaked from current address-family to vpn\n"
+ "name of route-map\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+ int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
+ enum vpn_policy_direction dir;
+ afi_t afi;
+ int idx = 0;
+ bool yes = true;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = vpn_policy_getdirs(vty, direction_str, dodir);
+ if (ret != CMD_SUCCESS)
+ return ret;
+
+ for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+ if (!dodir[dir])
+ continue;
+
+ vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+
+ if (yes) {
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
+ MTYPE_ROUTE_MAP_NAME, rmap_str);
+ bgp->vpn_policy[afi].rmap[dir] =
+ route_map_lookup_warn_noexist(vty, rmap_str);
+ if (!bgp->vpn_policy[afi].rmap[dir])
+ return CMD_SUCCESS;
+ } else {
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap_name[dir] = NULL;
+ bgp->vpn_policy[afi].rmap[dir] = NULL;
+ }
+
+ vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (af_route_map_vpn_imexport,
+ af_no_route_map_vpn_imexport_cmd,
+ "no route-map vpn <import|export>$direction_str",
+ NO_STR
+ "Specify route map\n"
+ "Between current address-family and vpn\n"
+ "For routes leaked from vpn to current address-family\n"
+ "For routes leaked from current address-family to vpn\n")
+
+DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,
+ "import vrf route-map RMAP$rmap_str",
+ "Import routes from another VRF\n"
+ "Vrf routes being filtered\n"
+ "Specify route map\n"
+ "name of route-map\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ enum vpn_policy_direction dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ afi_t afi;
+ struct bgp *bgp_default;
+
+ afi = vpn_policy_getafi(vty, bgp, true);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp_default = bgp_get_default();
+ if (!bgp_default) {
+ int32_t ret;
+ as_t as = bgp->as;
+
+ /* Auto-create assuming the same AS */
+ ret = bgp_get_vty(&bgp_default, &as, NULL,
+ BGP_INSTANCE_TYPE_DEFAULT, NULL,
+ ASNOTATION_UNDEFINED);
+
+ if (ret) {
+ vty_out(vty,
+ "VRF default is not configured as a bgp instance\n");
+ return CMD_WARNING;
+ }
+ }
+
+ vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap_name[dir] =
+ XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
+ bgp->vpn_policy[afi].rmap[dir] =
+ route_map_lookup_warn_noexist(vty, rmap_str);
+ if (!bgp->vpn_policy[afi].rmap[dir])
+ return CMD_SUCCESS;
+
+ SET_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT);
+
+ vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(af_no_import_vrf_route_map, af_no_import_vrf_route_map_cmd,
+ "no import vrf route-map [RMAP$rmap_str]",
+ NO_STR
+ "Import routes from another VRF\n"
+ "Vrf routes being filtered\n"
+ "Specify route map\n"
+ "name of route-map\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ enum vpn_policy_direction dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ afi_t afi;
+
+ afi = vpn_policy_getafi(vty, bgp, true);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
+
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap_name[dir] = NULL;
+ bgp->vpn_policy[afi].rmap[dir] = NULL;
+
+ if (bgp->vpn_policy[afi].import_vrf->count == 0)
+ UNSET_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT);
+
+ vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
+ "[no] import vrf VIEWVRFNAME$import_name",
+ NO_STR
+ "Import routes from another VRF\n"
+ "VRF to import from\n"
+ "The name of the VRF\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ struct listnode *node;
+ struct bgp *vrf_bgp, *bgp_default;
+ int32_t ret = 0;
+ as_t as = bgp->as;
+ bool remove = false;
+ int32_t idx = 0;
+ char *vname;
+ enum bgp_instance_type bgp_type = BGP_INSTANCE_TYPE_VRF;
+ safi_t safi;
+ afi_t afi;
+
+ if (import_name == NULL) {
+ vty_out(vty, "%% Missing import name\n");
+ return CMD_WARNING;
+ }
+
+ if (strcmp(import_name, "route-map") == 0) {
+ vty_out(vty, "%% Must include route-map name\n");
+ return CMD_WARNING;
+ }
+
+ if (argv_find(argv, argc, "no", &idx))
+ remove = true;
+
+ afi = vpn_policy_getafi(vty, bgp, true);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ safi = bgp_node_safi(vty);
+
+ if (((BGP_INSTANCE_TYPE_DEFAULT == bgp->inst_type)
+ && (strcmp(import_name, VRF_DEFAULT_NAME) == 0))
+ || (bgp->name && (strcmp(import_name, bgp->name) == 0))) {
+ vty_out(vty, "%% Cannot %s vrf %s into itself\n",
+ remove ? "unimport" : "import", import_name);
+ return CMD_WARNING;
+ }
+
+ bgp_default = bgp_get_default();
+ if (!bgp_default) {
+ /* Auto-create assuming the same AS */
+ ret = bgp_get_vty(&bgp_default, &as, NULL,
+ BGP_INSTANCE_TYPE_DEFAULT, NULL,
+ ASNOTATION_UNDEFINED);
+
+ if (ret) {
+ vty_out(vty,
+ "VRF default is not configured as a bgp instance\n");
+ return CMD_WARNING;
+ }
+ }
+
+ vrf_bgp = bgp_lookup_by_name(import_name);
+ if (!vrf_bgp) {
+ if (strcmp(import_name, VRF_DEFAULT_NAME) == 0)
+ vrf_bgp = bgp_default;
+ else
+ /* Auto-create assuming the same AS */
+ ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type,
+ NULL, ASNOTATION_UNDEFINED);
+ if (ret) {
+ vty_out(vty,
+ "VRF %s is not configured as a bgp instance\n",
+ import_name);
+ return CMD_WARNING;
+ }
+ }
+
+ if (remove) {
+ vrf_unimport_from_vrf(bgp, vrf_bgp, afi, safi);
+ } else {
+ /* Already importing from "import_vrf"? */
+ for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
+ vname)) {
+ if (strcmp(vname, import_name) == 0)
+ return CMD_WARNING;
+ }
+
+ vrf_import_from_vrf(bgp, vrf_bgp, afi, safi);
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* This command is valid only in a bgp vrf instance or the default instance */
+DEFPY (bgp_imexport_vpn,
+ bgp_imexport_vpn_cmd,
+ "[no] <import|export>$direction_str vpn",
+ NO_STR
+ "Import routes to this address-family\n"
+ "Export routes from this address-family\n"
+ "to/from default instance VPN RIB\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int previous_state;
+ afi_t afi;
+ safi_t safi;
+ int idx = 0;
+ bool yes = true;
+ int flag;
+ enum vpn_policy_direction dir;
+ struct bgp *bgp_default = bgp_get_default();
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type &&
+ BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
+
+ vty_out(vty, "%% import|export vpn valid only for bgp vrf or default instance\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ afi = bgp_node_afi(vty);
+ safi = bgp_node_safi(vty);
+ if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
+ vty_out(vty, "%% import|export vpn valid only for unicast ipv4|ipv6\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!strcmp(direction_str, "import")) {
+ flag = BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT;
+ dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ } else if (!strcmp(direction_str, "export")) {
+ flag = BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT;
+ dir = BGP_VPN_POLICY_DIR_TOVPN;
+ } else {
+ vty_out(vty, "%% unknown direction %s\n", direction_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ previous_state = CHECK_FLAG(bgp->af_flags[afi][safi], flag);
+
+ if (yes) {
+ SET_FLAG(bgp->af_flags[afi][safi], flag);
+ if (!previous_state) {
+ /* trigger export current vrf */
+ vpn_leak_postchange(dir, afi, bgp_default, bgp);
+ }
+ } else {
+ if (previous_state) {
+ /* trigger un-export current vrf */
+ vpn_leak_prechange(dir, afi, bgp_default, bgp);
+ }
+ UNSET_FLAG(bgp->af_flags[afi][safi], flag);
+ if (previous_state && bgp_default &&
+ !CHECK_FLAG(bgp_default->af_flags[afi][SAFI_MPLS_VPN],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
+ vpn_leak_no_retain(bgp, bgp_default, afi);
+ }
+
+ hook_call(bgp_snmp_init_stats, bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (af_routetarget_import,
+ af_routetarget_import_cmd,
+ "[no] <rt|route-target|route-target6|rt6> redirect import RTLIST...",
+ NO_STR
+ "Specify route target list\n"
+ "Specify route target list\n"
+ "Specify route target list\n"
+ "Specify route target list\n"
+ "Flow-spec redirect type route target\n"
+ "Import routes to this address-family\n"
+ "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|IPV6:MN)\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+ struct ecommunity *ecom = NULL;
+ afi_t afi;
+ int idx = 0, idx_unused = 0;
+ bool yes = true;
+ bool rt6 = false;
+
+ if (argv_find(argv, argc, "no", &idx))
+ yes = false;
+
+ if (argv_find(argv, argc, "rt6", &idx_unused) ||
+ argv_find(argv, argc, "route-target6", &idx_unused))
+ rt6 = true;
+
+ afi = vpn_policy_getafi(vty, bgp, false);
+ if (afi == AFI_MAX)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (rt6 && afi != AFI_IP6)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (yes) {
+ if (!argv_find(argv, argc, "RTLIST", &idx)) {
+ vty_out(vty, "%% Missing RTLIST\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom, rt6);
+ if (ret != CMD_SUCCESS)
+ return ret;
+ }
+
+ if (yes) {
+ if (bgp->vpn_policy[afi].import_redirect_rtlist)
+ ecommunity_free(&bgp->vpn_policy[afi]
+ .import_redirect_rtlist);
+ bgp->vpn_policy[afi].import_redirect_rtlist =
+ ecommunity_dup(ecom);
+ } else {
+ if (bgp->vpn_policy[afi].import_redirect_rtlist)
+ ecommunity_free(&bgp->vpn_policy[afi]
+ .import_redirect_rtlist);
+ bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
+ }
+
+ if (ecom)
+ ecommunity_free(&ecom);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (address_family_ipv4_safi,
+ address_family_ipv4_safi_cmd,
+ "address-family ipv4 [<unicast|multicast|vpn|labeled-unicast|flowspec>]",
+ "Enter Address Family command mode\n"
+ BGP_AF_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR)
+{
+
+ if (argc == 3) {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ safi_t safi = bgp_vty_safi_from_str(argv[2]->text);
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
+ && safi != SAFI_UNICAST && safi != SAFI_MULTICAST
+ && safi != SAFI_EVPN) {
+ vty_out(vty,
+ "Only Unicast/Multicast/EVPN SAFIs supported in non-core instances.\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ vty->node = bgp_node_type(AFI_IP, safi);
+ } else
+ vty->node = BGP_IPV4_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (address_family_ipv6_safi,
+ address_family_ipv6_safi_cmd,
+ "address-family ipv6 [<unicast|multicast|vpn|labeled-unicast|flowspec>]",
+ "Enter Address Family command mode\n"
+ BGP_AF_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR)
+{
+ if (argc == 3) {
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ safi_t safi = bgp_vty_safi_from_str(argv[2]->text);
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
+ && safi != SAFI_UNICAST && safi != SAFI_MULTICAST
+ && safi != SAFI_EVPN) {
+ vty_out(vty,
+ "Only Unicast/Multicast/EVPN SAFIs supported in non-core instances.\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ vty->node = bgp_node_type(AFI_IP6, safi);
+ } else
+ vty->node = BGP_IPV6_NODE;
+
+ return CMD_SUCCESS;
+}
+
+#ifdef KEEP_OLD_VPN_COMMANDS
+DEFUN_NOSH (address_family_vpnv4,
+ address_family_vpnv4_cmd,
+ "address-family vpnv4 [unicast]",
+ "Enter Address Family command mode\n"
+ BGP_AF_STR
+ BGP_AF_MODIFIER_STR)
+{
+ vty->node = BGP_VPNV4_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (address_family_vpnv6,
+ address_family_vpnv6_cmd,
+ "address-family vpnv6 [unicast]",
+ "Enter Address Family command mode\n"
+ BGP_AF_STR
+ BGP_AF_MODIFIER_STR)
+{
+ vty->node = BGP_VPNV6_NODE;
+ return CMD_SUCCESS;
+}
+#endif /* KEEP_OLD_VPN_COMMANDS */
+
+DEFUN_NOSH (address_family_evpn,
+ address_family_evpn_cmd,
+ "address-family l2vpn evpn",
+ "Enter Address Family command mode\n"
+ BGP_AF_STR
+ BGP_AF_MODIFIER_STR)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ vty->node = BGP_EVPN_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (bgp_segment_routing_srv6,
+ bgp_segment_routing_srv6_cmd,
+ "segment-routing srv6",
+ "Segment-Routing configuration\n"
+ "Segment-Routing SRv6 configuration\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp->srv6_enabled = true;
+ vty->node = BGP_SRV6_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_segment_routing_srv6,
+ no_bgp_segment_routing_srv6_cmd,
+ "no segment-routing srv6",
+ NO_STR
+ "Segment-Routing configuration\n"
+ "Segment-Routing SRv6 configuration\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (strlen(bgp->srv6_locator_name) > 0)
+ if (bgp_srv6_locator_unset(bgp) < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ bgp->srv6_enabled = false;
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_srv6_locator,
+ bgp_srv6_locator_cmd,
+ "locator NAME$name",
+ "Specify SRv6 locator\n"
+ "Specify SRv6 locator\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int ret;
+
+ if (strlen(bgp->srv6_locator_name) > 0
+ && strcmp(name, bgp->srv6_locator_name) != 0) {
+ vty_out(vty, "srv6 locator is already configured\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ snprintf(bgp->srv6_locator_name,
+ sizeof(bgp->srv6_locator_name), "%s", name);
+
+ ret = bgp_zebra_srv6_manager_get_locator_chunk(name);
+ if (ret < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_srv6_locator,
+ no_bgp_srv6_locator_cmd,
+ "no locator NAME$name",
+ NO_STR
+ "Specify SRv6 locator\n"
+ "Specify SRv6 locator\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ /* when locator isn't configured, do nothing */
+ if (strlen(bgp->srv6_locator_name) < 1)
+ return CMD_SUCCESS;
+
+ /* name validation */
+ if (strcmp(name, bgp->srv6_locator_name) != 0) {
+ vty_out(vty, "%% No srv6 locator is configured\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* unset locator */
+ if (bgp_srv6_locator_unset(bgp) < 0)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_bgp_srv6,
+ show_bgp_srv6_cmd,
+ "show bgp segment-routing srv6",
+ SHOW_STR
+ BGP_STR
+ "BGP Segment Routing\n"
+ "BGP Segment Routing SRv6\n")
+{
+ struct bgp *bgp;
+ struct listnode *node;
+ struct srv6_locator_chunk *chunk;
+ struct bgp_srv6_function *func;
+
+ bgp = bgp_get_default();
+ if (!bgp)
+ return CMD_SUCCESS;
+
+ vty_out(vty, "locator_name: %s\n", bgp->srv6_locator_name);
+ vty_out(vty, "locator_chunks:\n");
+ for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
+ vty_out(vty, "- %pFX\n", &chunk->prefix);
+ vty_out(vty, " block-length: %d\n", chunk->block_bits_length);
+ vty_out(vty, " node-length: %d\n", chunk->node_bits_length);
+ vty_out(vty, " func-length: %d\n",
+ chunk->function_bits_length);
+ vty_out(vty, " arg-length: %d\n", chunk->argument_bits_length);
+ }
+
+ vty_out(vty, "functions:\n");
+ for (ALL_LIST_ELEMENTS_RO(bgp->srv6_functions, node, func)) {
+ vty_out(vty, "- sid: %pI6\n", &func->sid);
+ vty_out(vty, " locator: %s\n", func->locator_name);
+ }
+
+ vty_out(vty, "bgps:\n");
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ vty_out(vty, "- name: %s\n",
+ bgp->name ? bgp->name : "default");
+
+ vty_out(vty, " vpn_policy[AFI_IP].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP].tovpn_sid);
+ vty_out(vty, " vpn_policy[AFI_IP6].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP6].tovpn_sid);
+ vty_out(vty, " per-vrf tovpn_sid: %pI6\n", bgp->tovpn_sid);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (exit_address_family,
+ exit_address_family_cmd,
+ "exit-address-family",
+ "Exit from Address Family configuration mode\n")
+{
+ if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE
+ || vty->node == BGP_IPV4L_NODE || vty->node == BGP_VPNV4_NODE
+ || vty->node == BGP_IPV6_NODE || vty->node == BGP_IPV6M_NODE
+ || vty->node == BGP_IPV6L_NODE || vty->node == BGP_VPNV6_NODE
+ || vty->node == BGP_EVPN_NODE
+ || vty->node == BGP_FLOWSPECV4_NODE
+ || vty->node == BGP_FLOWSPECV6_NODE)
+ vty->node = BGP_NODE;
+ return CMD_SUCCESS;
+}
+
+/* Recalculate bestpath and re-advertise a prefix */
+static int bgp_clear_prefix(struct vty *vty, const char *view_name,
+ const char *ip_str, afi_t afi, safi_t safi,
+ struct prefix_rd *prd)
+{
+ int ret;
+ struct prefix match;
+ struct bgp_dest *dest;
+ struct bgp_dest *rm;
+ struct bgp *bgp;
+ struct bgp_table *table;
+ struct bgp_table *rib;
+
+ /* BGP structure lookup. */
+ if (view_name) {
+ bgp = bgp_lookup_by_name(view_name);
+ if (bgp == NULL) {
+ vty_out(vty, "%% Can't find BGP instance %s\n",
+ view_name);
+ return CMD_WARNING;
+ }
+ } else {
+ bgp = bgp_get_default();
+ if (bgp == NULL) {
+ vty_out(vty, "%% No BGP process is configured\n");
+ return CMD_WARNING;
+ }
+ }
+
+ /* Check IP address argument. */
+ ret = str2prefix(ip_str, &match);
+ if (!ret) {
+ vty_out(vty, "%% address is malformed\n");
+ return CMD_WARNING;
+ }
+
+ match.family = afi2family(afi);
+ rib = bgp->rib[afi][safi];
+
+ if (safi == SAFI_MPLS_VPN) {
+ for (dest = bgp_table_top(rib); dest;
+ dest = bgp_route_next(dest)) {
+ const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+
+ if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
+ continue;
+
+ table = bgp_dest_get_bgp_table_info(dest);
+ if (table == NULL)
+ continue;
+
+ rm = bgp_node_match(table, &match);
+ if (rm != NULL) {
+ const struct prefix *rm_p =
+ bgp_dest_get_prefix(rm);
+
+ if (rm_p->prefixlen == match.prefixlen) {
+ SET_FLAG(rm->flags,
+ BGP_NODE_USER_CLEAR);
+ bgp_process(bgp, rm, afi, safi);
+ }
+ bgp_dest_unlock_node(rm);
+ }
+ }
+ } else {
+ dest = bgp_node_match(rib, &match);
+ if (dest != NULL) {
+ const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+
+ if (dest_p->prefixlen == match.prefixlen) {
+ SET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
+ bgp_process(bgp, dest, afi, safi);
+ }
+ bgp_dest_unlock_node(dest);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* one clear bgp command to rule them all */
+DEFUN (clear_ip_bgp_all,
+ clear_ip_bgp_all_cmd,
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_AF_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ BGP_AF_MODIFIER_STR
+ "Clear all peers\n"
+ "BGP IPv4 neighbor to clear\n"
+ "BGP IPv6 neighbor to clear\n"
+ "BGP neighbor on interface to clear\n"
+ "Clear peers with the AS number in plain or dotted format\n"
+ "Clear all external peers\n"
+ "Clear all members of peer-group\n"
+ "BGP peer-group name\n"
+ BGP_SOFT_STR
+ BGP_SOFT_IN_STR
+ BGP_SOFT_OUT_STR
+ BGP_SOFT_IN_STR
+ "Push out prefix-list ORF and do inbound soft reconfig\n"
+ BGP_SOFT_OUT_STR
+ "Reset message statistics\n")
+{
+ char *vrf = NULL;
+
+ afi_t afi = AFI_UNSPEC;
+ safi_t safi = SAFI_UNSPEC;
+ enum clear_sort clr_sort = clear_peer;
+ enum bgp_clear_type clr_type;
+ char *clr_arg = NULL;
+
+ int idx = 0;
+
+ /* clear [ip] bgp */
+ if (argv_find(argv, argc, "ip", &idx))
+ afi = AFI_IP;
+
+ /* [<vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ idx += 2;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ } else if (argv_find(argv, argc, "view", &idx)) {
+ /* [<view> VIEWVRFNAME] */
+ vrf = argv[idx + 1]->arg;
+ idx += 2;
+ }
+ /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
+ if (argv_find_and_parse_afi(argv, argc, &idx, &afi))
+ argv_find_and_parse_safi(argv, argc, &idx, &safi);
+
+ /* <*|A.B.C.D|X:X::X:X|WORD|ASNUM|external|peer-group PGNAME> */
+ if (argv_find(argv, argc, "*", &idx)) {
+ clr_sort = clear_all;
+ } else if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ clr_sort = clear_peer;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "X:X::X:X", &idx)) {
+ clr_sort = clear_peer;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "peer-group", &idx)) {
+ clr_sort = clear_group;
+ idx++;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "PGNAME", &idx)) {
+ clr_sort = clear_peer;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "WORD", &idx)) {
+ clr_sort = clear_peer;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "ASNUM", &idx)) {
+ clr_sort = clear_as;
+ clr_arg = argv[idx]->arg;
+ } else if (argv_find(argv, argc, "external", &idx)) {
+ clr_sort = clear_external;
+ }
+
+ /* [<soft [<in|out>]|in [prefix-filter]|out|message-stats>] */
+ if (argv_find(argv, argc, "soft", &idx)) {
+ if (argv_find(argv, argc, "in", &idx)
+ || argv_find(argv, argc, "out", &idx))
+ clr_type = strmatch(argv[idx]->text, "in")
+ ? BGP_CLEAR_SOFT_IN
+ : BGP_CLEAR_SOFT_OUT;
+ else
+ clr_type = BGP_CLEAR_SOFT_BOTH;
+ } else if (argv_find(argv, argc, "in", &idx)) {
+ clr_type = argv_find(argv, argc, "prefix-filter", &idx)
+ ? BGP_CLEAR_SOFT_IN_ORF_PREFIX
+ : BGP_CLEAR_SOFT_IN;
+ } else if (argv_find(argv, argc, "out", &idx)) {
+ clr_type = BGP_CLEAR_SOFT_OUT;
+ } else if (argv_find(argv, argc, "message-stats", &idx)) {
+ clr_type = BGP_CLEAR_MESSAGE_STATS;
+ } else
+ clr_type = BGP_CLEAR_SOFT_NONE;
+
+ return bgp_clear_vty(vty, vrf, afi, safi, clr_sort, clr_type, clr_arg);
+}
+
+DEFUN (clear_ip_bgp_prefix,
+ clear_ip_bgp_prefix_cmd,
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] prefix A.B.C.D/M",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ "Clear bestpath and re-advertise\n"
+ "IPv4 prefix\n")
+{
+ char *vrf = NULL;
+ char *prefix = NULL;
+
+ int idx = 0;
+
+ /* [<view|vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ idx += 2;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ } else if (argv_find(argv, argc, "view", &idx)) {
+ /* [<view> VIEWVRFNAME] */
+ vrf = argv[idx + 1]->arg;
+ idx += 2;
+ }
+
+ prefix = argv[argc - 1]->arg;
+
+ return bgp_clear_prefix(vty, vrf, prefix, AFI_IP, SAFI_UNICAST, NULL);
+}
+
+DEFUN (clear_bgp_ipv6_safi_prefix,
+ clear_bgp_ipv6_safi_prefix_cmd,
+ "clear [ip] bgp ipv6 "BGP_SAFI_CMD_STR" prefix X:X::X:X/M",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ BGP_AF_STR
+ BGP_SAFI_HELP_STR
+ "Clear bestpath and re-advertise\n"
+ "IPv6 prefix\n")
+{
+ int idx_safi = 0;
+ int idx_ipv6_prefix = 0;
+ safi_t safi = SAFI_UNICAST;
+ char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ?
+ argv[idx_ipv6_prefix]->arg : NULL;
+
+ argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
+ return bgp_clear_prefix(
+ vty, NULL, prefix, AFI_IP6,
+ safi, NULL);
+}
+
+DEFUN (clear_bgp_instance_ipv6_safi_prefix,
+ clear_bgp_instance_ipv6_safi_prefix_cmd,
+ "clear [ip] bgp <view|vrf> VIEWVRFNAME ipv6 "BGP_SAFI_CMD_STR" prefix X:X::X:X/M",
+ CLEAR_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AF_STR
+ BGP_SAFI_HELP_STR
+ "Clear bestpath and re-advertise\n"
+ "IPv6 prefix\n")
+{
+ int idx_safi = 0;
+ int idx_vrfview = 0;
+ int idx_ipv6_prefix = 0;
+ safi_t safi = SAFI_UNICAST;
+ char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ?
+ argv[idx_ipv6_prefix]->arg : NULL;
+ char *vrfview = NULL;
+
+ /* [<view|vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx_vrfview)) {
+ vrfview = argv[idx_vrfview + 1]->arg;
+ if (vrfview && strmatch(vrfview, VRF_DEFAULT_NAME))
+ vrfview = NULL;
+ } else if (argv_find(argv, argc, "view", &idx_vrfview)) {
+ /* [<view> VIEWVRFNAME] */
+ vrfview = argv[idx_vrfview + 1]->arg;
+ }
+ argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
+
+ return bgp_clear_prefix(
+ vty, vrfview, prefix,
+ AFI_IP6, safi, NULL);
+}
+
+DEFUN (show_bgp_views,
+ show_bgp_views_cmd,
+ "show [ip] bgp views",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Show the defined BGP views\n")
+{
+ struct list *inst = bm->bgp;
+ struct listnode *node;
+ struct bgp *bgp;
+
+ vty_out(vty, "Defined BGP views:\n");
+ for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) {
+ /* Skip VRFs. */
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+ continue;
+ vty_out(vty, "\t%s (AS%s)\n", bgp->name ? bgp->name : "(null)",
+ bgp->as_pretty);
+ }
+
+ return CMD_SUCCESS;
+}
+
+static inline void calc_peers_cfgd_estbd(struct bgp *bgp, int *peers_cfgd,
+ int *peers_estbd)
+{
+ struct peer *peer;
+ struct listnode *node;
+
+ *peers_cfgd = *peers_estbd = 0;
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+ (*peers_cfgd)++;
+ if (peer_established(peer->connection))
+ (*peers_estbd)++;
+ }
+}
+
+static void print_bgp_vrfs(struct bgp *bgp, struct vty *vty, json_object *json,
+ const char *type)
+{
+ int peers_cfg, peers_estb;
+
+ calc_peers_cfgd_estbd(bgp, &peers_cfg, &peers_estb);
+
+ if (json) {
+ int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
+ ? -1
+ : (int64_t)bgp->vrf_id;
+ json_object_string_add(json, "type", type);
+ json_object_int_add(json, "vrfId", vrf_id_ui);
+ json_object_string_addf(json, "routerId", "%pI4",
+ &bgp->router_id);
+ json_object_int_add(json, "numConfiguredPeers", peers_cfg);
+ json_object_int_add(json, "numEstablishedPeers", peers_estb);
+ json_object_int_add(json, "l3vni", bgp->l3vni);
+ json_object_string_addf(json, "rmac", "%pEA", &bgp->rmac);
+ json_object_string_add(
+ json, "interface",
+ ifindex2ifname(bgp->l3vni_svi_ifindex, bgp->vrf_id));
+ }
+}
+
+static int show_bgp_vrfs_detail_common(struct vty *vty, struct bgp *bgp,
+ json_object *json, const char *name,
+ const char *type, bool use_vrf)
+{
+ int peers_cfg, peers_estb;
+
+ calc_peers_cfgd_estbd(bgp, &peers_cfg, &peers_estb);
+
+ if (use_vrf) {
+ if (json) {
+ print_bgp_vrfs(bgp, vty, json, type);
+ } else {
+ vty_out(vty, "BGP instance %s VRF id %d\n",
+ bgp->name_pretty,
+ bgp->vrf_id == VRF_UNKNOWN ? -1
+ : (int)bgp->vrf_id);
+ vty_out(vty, "Router Id %pI4\n", &bgp->router_id);
+ vty_out(vty,
+ "Num Configured Peers %d, Established %d\n",
+ peers_cfg, peers_estb);
+ if (bgp->l3vni) {
+ vty_out(vty,
+ "L3VNI %u, L3VNI-SVI %s, Router MAC %pEA\n",
+ bgp->l3vni,
+ ifindex2ifname(bgp->l3vni_svi_ifindex,
+ bgp->vrf_id),
+ &bgp->rmac);
+ }
+ }
+ } else {
+ if (json) {
+ print_bgp_vrfs(bgp, vty, json, type);
+ } else {
+ vty_out(vty, "%4s %-5d %-16pI4 %-9u %-10u %-37s\n",
+ type,
+ bgp->vrf_id == VRF_UNKNOWN ? -1
+ : (int)bgp->vrf_id,
+ &bgp->router_id, peers_cfg, peers_estb, name);
+ vty_out(vty, "%11s %-16u %-21pEA %-20s\n", " ",
+ bgp->l3vni, &bgp->rmac,
+ ifindex2ifname(bgp->l3vni_svi_ifindex,
+ bgp->vrf_id));
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_bgp_vrfs,
+ show_bgp_vrfs_cmd,
+ "show [ip] bgp vrfs [<VRFNAME$vrf_name>] [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Show BGP VRFs\n"
+ "Specific VRF name\n"
+ JSON_STR)
+{
+ struct list *inst = bm->bgp;
+ struct listnode *node;
+ struct bgp *bgp;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
+ json_object *json_vrfs = NULL;
+ json_object *json_vrf = NULL;
+ int count = 0;
+ const char *name = vrf_name;
+ const char *type;
+
+ if (uj)
+ json = json_object_new_object();
+
+ if (name) {
+ if (strmatch(name, VRF_DEFAULT_NAME)) {
+ bgp = bgp_get_default();
+ type = "DFLT";
+ } else {
+ bgp = bgp_lookup_by_name(name);
+ type = "VRF";
+ }
+ if (!bgp) {
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty,
+ "%% Specified BGP instance not found\n");
+
+ return CMD_WARNING;
+ }
+ }
+
+ if (vrf_name) {
+ if (uj)
+ json_vrf = json_object_new_object();
+
+ show_bgp_vrfs_detail_common(vty, bgp, json_vrf, name, type,
+ true);
+
+ if (uj) {
+ json_object_object_add(json, name, json_vrf);
+ vty_json(vty, json);
+ }
+
+ return CMD_SUCCESS;
+ }
+
+ if (uj)
+ json_vrfs = json_object_new_object();
+
+ for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) {
+ const char *name;
+
+ /* Skip Views. */
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+ continue;
+
+ count++;
+ if (!uj && count == 1) {
+ vty_out(vty,
+ "%4s %-5s %-16s %9s %10s %-37s\n",
+ "Type", "Id", "routerId", "#PeersCfg",
+ "#PeersEstb", "Name");
+ vty_out(vty, "%11s %-16s %-21s %-6s\n", " ",
+ "L3-VNI", "RouterMAC", "Interface");
+ }
+ if (uj)
+ json_vrf = json_object_new_object();
+
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ name = VRF_DEFAULT_NAME;
+ type = "DFLT";
+ } else {
+ name = bgp->name;
+ type = "VRF";
+ }
+
+ show_bgp_vrfs_detail_common(vty, bgp, json_vrf, name, type,
+ false);
+
+ if (uj)
+ json_object_object_add(json_vrfs, name, json_vrf);
+ }
+
+ if (uj) {
+ json_object_object_add(json, "vrfs", json_vrfs);
+ json_object_int_add(json, "totalVrfs", count);
+ vty_json(vty, json);
+ } else {
+ if (count)
+ vty_out(vty,
+ "\nTotal number of VRFs (including default): %d\n",
+ count);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_mac_hash,
+ show_bgp_mac_hash_cmd,
+ "show bgp mac hash",
+ SHOW_STR
+ BGP_STR
+ "Mac Address\n"
+ "Mac Address database\n")
+{
+ bgp_mac_dump_table(vty);
+
+ return CMD_SUCCESS;
+}
+
+static void show_tip_entry(struct hash_bucket *bucket, void *args)
+{
+ struct vty *vty = (struct vty *)args;
+ struct tip_addr *tip = (struct tip_addr *)bucket->data;
+
+ vty_out(vty, "addr: %pI4, count: %d\n", &tip->addr, tip->refcnt);
+}
+
+static void bgp_show_martian_nexthops(struct vty *vty, struct bgp *bgp)
+{
+ vty_out(vty, "self nexthop database:\n");
+ bgp_nexthop_show_address_hash(vty, bgp);
+
+ vty_out(vty, "Tunnel-ip database:\n");
+ hash_iterate(bgp->tip_hash,
+ (void (*)(struct hash_bucket *, void *))show_tip_entry,
+ vty);
+}
+
+DEFUN(show_bgp_martian_nexthop_db, show_bgp_martian_nexthop_db_cmd,
+ "show bgp [<view|vrf> VIEWVRFNAME] martian next-hop",
+ SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR
+ "martian next-hops\n"
+ "martian next-hop database\n")
+{
+ struct bgp *bgp = NULL;
+ int idx = 0;
+ char *name = NULL;
+
+ /* [<vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ name = argv[idx + 1]->arg;
+ if (name && strmatch(name, VRF_DEFAULT_NAME))
+ name = NULL;
+ } else if (argv_find(argv, argc, "view", &idx))
+ /* [<view> VIEWVRFNAME] */
+ name = argv[idx + 1]->arg;
+ if (name)
+ bgp = bgp_lookup_by_name(name);
+ else
+ bgp = bgp_get_default();
+
+ if (!bgp) {
+ vty_out(vty, "%% No BGP process is configured\n");
+ return CMD_WARNING;
+ }
+ bgp_show_martian_nexthops(vty, bgp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_memory,
+ show_bgp_memory_cmd,
+ "show [ip] bgp memory",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Global BGP memory statistics\n")
+{
+ char memstrbuf[MTYPE_MEMSTR_LEN];
+ unsigned long count;
+
+ /* RIB related usage stats */
+ count = mtype_stats_alloc(MTYPE_BGP_NODE);
+ vty_out(vty, "%ld RIB nodes, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_dest)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE);
+ vty_out(vty, "%ld BGP routes, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info)));
+ if ((count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA)))
+ vty_out(vty, "%ld BGP route ancillaries, using %s of memory\n",
+ count,
+ mtype_memstr(
+ memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_EVPN);
+ if (count)
+ vty_out(vty, "%ld BGP extra info for EVPN, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_evpn)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_FS);
+ if (count)
+ vty_out(vty,
+ "%ld BGP extra info for flowspec, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_fs)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK);
+ if (count)
+ vty_out(vty,
+ "%ld BGP extra info for vrf leaking, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_vrfleak)));
+
+ if ((count = mtype_stats_alloc(MTYPE_BGP_STATIC)))
+ vty_out(vty, "%ld Static routes, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_static)));
+
+ if ((count = mtype_stats_alloc(MTYPE_BGP_PACKET)))
+ vty_out(vty, "%ld Packets, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bpacket)));
+
+ /* Adj-In/Out */
+ if ((count = mtype_stats_alloc(MTYPE_BGP_ADJ_IN)))
+ vty_out(vty, "%ld Adj-In entries, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_adj_in)));
+ if ((count = mtype_stats_alloc(MTYPE_BGP_ADJ_OUT)))
+ vty_out(vty, "%ld Adj-Out entries, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_adj_out)));
+
+ if ((count = mtype_stats_alloc(MTYPE_BGP_NEXTHOP_CACHE)))
+ vty_out(vty, "%ld Nexthop cache entries, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_nexthop_cache)));
+
+ if ((count = mtype_stats_alloc(MTYPE_BGP_DAMP_INFO)))
+ vty_out(vty, "%ld Dampening entries, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_damp_info)));
+
+ /* Attributes */
+ count = attr_count();
+ vty_out(vty, "%ld BGP attributes, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct attr)));
+
+ if ((count = attr_unknown_count()))
+ vty_out(vty, "%ld unknown attributes\n", count);
+
+ /* AS_PATH attributes */
+ count = aspath_count();
+ vty_out(vty, "%ld BGP AS-PATH entries, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct aspath)));
+
+ count = mtype_stats_alloc(MTYPE_AS_SEG);
+ vty_out(vty, "%ld BGP AS-PATH segments, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct assegment)));
+
+ /* Other attributes */
+ if ((count = community_count()))
+ vty_out(vty, "%ld BGP community entries, using %s of memory\n",
+ count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct community)));
+ if ((count = mtype_stats_alloc(MTYPE_ECOMMUNITY)))
+ vty_out(vty,
+ "%ld BGP ext-community entries, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct ecommunity)));
+ if ((count = mtype_stats_alloc(MTYPE_LCOMMUNITY)))
+ vty_out(vty,
+ "%ld BGP large-community entries, using %s of memory\n",
+ count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct lcommunity)));
+
+ if ((count = mtype_stats_alloc(MTYPE_CLUSTER)))
+ vty_out(vty, "%ld Cluster lists, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct cluster_list)));
+
+ /* Peer related usage */
+ count = mtype_stats_alloc(MTYPE_BGP_PEER);
+ vty_out(vty, "%ld peers, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct peer)));
+
+ if ((count = mtype_stats_alloc(MTYPE_PEER_GROUP)))
+ vty_out(vty, "%ld peer groups, using %s of memory\n", count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct peer_group)));
+
+ /* Other */
+ if ((count = mtype_stats_alloc(MTYPE_BGP_REGEXP)))
+ vty_out(vty, "%ld compiled regexes, using %s of memory\n",
+ count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(regex_t)));
+ return CMD_SUCCESS;
+}
+
+static void bgp_show_bestpath_json(struct bgp *bgp, json_object *json)
+{
+ json_object *bestpath = json_object_new_object();
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE))
+ json_object_string_add(bestpath, "asPath", "ignore");
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED))
+ json_object_string_add(bestpath, "asPath", "confed");
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MULTIPATH_RELAX_AS_SET))
+ json_object_string_add(bestpath, "multiPathRelax",
+ "as-set");
+ else
+ json_object_string_add(bestpath, "multiPathRelax",
+ "true");
+ } else
+ json_object_string_add(bestpath, "multiPathRelax", "false");
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
+ json_object_boolean_true_add(bestpath, "peerTypeRelax");
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID))
+ json_object_string_add(bestpath, "compareRouterId", "true");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED)
+ || CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED))
+ json_object_string_add(bestpath, "med", "confed");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
+ json_object_string_add(bestpath, "med",
+ "missing-as-worst");
+ else
+ json_object_string_add(bestpath, "med", "true");
+ }
+
+ json_object_object_add(json, "bestPath", bestpath);
+}
+
+/* Print the error code/subcode for why the peer is down */
+static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
+ json_object *json_peer, bool use_json)
+{
+ const char *code_str;
+ const char *subcode_str;
+
+ if (use_json) {
+ if (peer->last_reset == PEER_DOWN_NOTIFY_SEND
+ || peer->last_reset == PEER_DOWN_NOTIFY_RECEIVED) {
+ char errorcodesubcode_hexstr[5];
+ char errorcodesubcode_str[256];
+
+ code_str = bgp_notify_code_str(peer->notify.code);
+ subcode_str = bgp_notify_subcode_str(
+ peer->notify.code,
+ peer->notify.subcode);
+
+ snprintf(errorcodesubcode_hexstr,
+ sizeof(errorcodesubcode_hexstr), "%02X%02X",
+ peer->notify.code, peer->notify.subcode);
+ json_object_string_add(json_peer,
+ "lastErrorCodeSubcode",
+ errorcodesubcode_hexstr);
+ snprintf(errorcodesubcode_str, 255, "%s%s",
+ code_str, subcode_str);
+ json_object_string_add(json_peer,
+ "lastNotificationReason",
+ errorcodesubcode_str);
+ json_object_boolean_add(json_peer,
+ "lastNotificationHardReset",
+ peer->notify.hard_reset);
+ if (peer->last_reset == PEER_DOWN_NOTIFY_RECEIVED
+ && peer->notify.code == BGP_NOTIFY_CEASE
+ && (peer->notify.subcode
+ == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN
+ || peer->notify.subcode
+ == BGP_NOTIFY_CEASE_ADMIN_RESET)
+ && peer->notify.length) {
+ char msgbuf[1024];
+ const char *msg_str;
+
+ msg_str = bgp_notify_admin_message(
+ msgbuf, sizeof(msgbuf),
+ (uint8_t *)peer->notify.data,
+ peer->notify.length);
+ json_object_string_add(json_peer,
+ "lastShutdownDescription",
+ msg_str);
+ }
+
+ }
+ json_object_string_add(json_peer, "lastResetDueTo",
+ peer_down_str[(int)peer->last_reset]);
+ json_object_int_add(json_peer, "lastResetCode",
+ peer->last_reset);
+ json_object_string_add(json_peer, "softwareVersion",
+ peer->soft_version ? peer->soft_version
+ : "n/a");
+ } else {
+ if (peer->last_reset == PEER_DOWN_NOTIFY_SEND
+ || peer->last_reset == PEER_DOWN_NOTIFY_RECEIVED) {
+ code_str = bgp_notify_code_str(peer->notify.code);
+ subcode_str =
+ bgp_notify_subcode_str(peer->notify.code,
+ peer->notify.subcode);
+ vty_out(vty, " Notification %s (%s%s%s)\n",
+ peer->last_reset == PEER_DOWN_NOTIFY_SEND
+ ? "sent"
+ : "received",
+ code_str, subcode_str,
+ peer->notify.hard_reset
+ ? bgp_notify_subcode_str(
+ BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_HARD_RESET)
+ : "");
+ } else {
+ vty_out(vty, " %s (%s)\n",
+ peer_down_str[(int)peer->last_reset],
+ peer->soft_version ? peer->soft_version
+ : "n/a");
+ }
+ }
+}
+
+static inline bool bgp_has_peer_failed(struct peer *peer, afi_t afi,
+ safi_t safi)
+{
+ return ((!peer_established(peer->connection)) ||
+ !peer->afc_recv[afi][safi]);
+}
+
+static void bgp_show_failed_summary(struct vty *vty, struct bgp *bgp,
+ struct peer *peer, json_object *json_peer,
+ int max_neighbor_width, bool use_json)
+{
+ char timebuf[BGP_UPTIME_LEN], dn_flag[2];
+ int len;
+
+ if (use_json) {
+ if (peer_dynamic_neighbor(peer))
+ json_object_boolean_true_add(json_peer,
+ "dynamicPeer");
+ if (peer->hostname)
+ json_object_string_add(json_peer, "hostname",
+ peer->hostname);
+
+ if (peer->domainname)
+ json_object_string_add(json_peer, "domainname",
+ peer->domainname);
+ json_object_int_add(json_peer, "connectionsEstablished",
+ peer->established);
+ json_object_int_add(json_peer, "connectionsDropped",
+ peer->dropped);
+ peer_uptime(peer->uptime, timebuf, BGP_UPTIME_LEN,
+ use_json, json_peer);
+ if (peer_established(peer->connection))
+ json_object_string_add(json_peer, "lastResetDueTo",
+ "AFI/SAFI Not Negotiated");
+ else
+ bgp_show_peer_reset(NULL, peer, json_peer, true);
+ } else {
+ dn_flag[1] = '\0';
+ dn_flag[0] = peer_dynamic_neighbor(peer) ? '*' : '\0';
+ if (peer->hostname
+ && CHECK_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME))
+ len = vty_out(vty, "%s%s(%s)", dn_flag,
+ peer->hostname, peer->host);
+ else
+ len = vty_out(vty, "%s%s", dn_flag, peer->host);
+
+ /* pad the neighbor column with spaces */
+ if (len < max_neighbor_width)
+ vty_out(vty, "%*s", max_neighbor_width - len,
+ " ");
+ vty_out(vty, "%7d %7d %9s", peer->established,
+ peer->dropped,
+ peer_uptime(peer->uptime, timebuf,
+ BGP_UPTIME_LEN, 0, NULL));
+ if (peer_established(peer->connection))
+ vty_out(vty, " AFI/SAFI Not Negotiated\n");
+ else
+ bgp_show_peer_reset(vty, peer, NULL,
+ false);
+ }
+}
+
+/* Strip peer's description to the given size. */
+static char *bgp_peer_description_stripped(char *desc, uint32_t size)
+{
+ static char stripped[BUFSIZ];
+ uint32_t i = 0;
+ uint32_t last_space = size;
+
+ while (i < size) {
+ if (*(desc + i) == '\0') {
+ stripped[i] = '\0';
+ return stripped;
+ }
+ if (i != 0 && *(desc + i) == ' ' && last_space != i - 1)
+ last_space = i;
+ stripped[i] = *(desc + i);
+ i++;
+ }
+
+ stripped[last_space] = '\0';
+
+ return stripped;
+}
+
+/* Determine whether var peer should be filtered out of the summary. */
+static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
+ struct peer *fpeer, int as_type,
+ as_t as)
+{
+
+ /* filter neighbor XXXX */
+ if (fpeer && fpeer != peer)
+ return true;
+
+ /* filter remote-as (internal|external) */
+ if (as_type != AS_UNSPECIFIED) {
+ if (peer->as_type == AS_SPECIFIED) {
+ if (as_type == AS_INTERNAL) {
+ if (peer->as != peer->local_as)
+ return true;
+ } else if (peer->as == peer->local_as)
+ return true;
+ } else if (as_type != peer->as_type)
+ return true;
+ } else if (as && as != peer->as) /* filter remote-as XXX */
+ return true;
+
+ return false;
+}
+
+/* Show BGP peer's summary information.
+ *
+ * Peer's description is stripped according to if `wide` option is given
+ * or not.
+ *
+ * When adding new columns to `show bgp summary` output, please make
+ * sure `Desc` is the lastest column to show because it can contain
+ * whitespaces and the whole output will be tricky.
+ */
+static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
+ struct peer *fpeer, int as_type, as_t as,
+ uint16_t show_flags)
+{
+ struct peer *peer;
+ struct listnode *node, *nnode;
+ unsigned int count = 0, dn_count = 0;
+ char timebuf[BGP_UPTIME_LEN], dn_flag[2];
+ char neighbor_buf[VTY_BUFSIZ];
+ int neighbor_col_default_width = 16;
+ int len, failed_count = 0;
+ unsigned int filtered_count = 0;
+ int max_neighbor_width = 0;
+ int pfx_rcd_safi;
+ json_object *json = NULL;
+ json_object *json_peer = NULL;
+ json_object *json_peers = NULL;
+ struct peer_af *paf;
+ struct bgp_filter *filter;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ bool show_failed = CHECK_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
+ bool show_established =
+ CHECK_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
+ bool show_wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
+ bool show_terse = CHECK_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
+
+ /* labeled-unicast routes are installed in the unicast table so in order
+ * to
+ * display the correct PfxRcd value we must look at SAFI_UNICAST
+ */
+
+ if (safi == SAFI_LABELED_UNICAST)
+ pfx_rcd_safi = SAFI_UNICAST;
+ else
+ pfx_rcd_safi = safi;
+
+ if (use_json) {
+ json = json_object_new_object();
+ json_peers = json_object_new_object();
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (bgp_show_summary_is_peer_filtered(peer, fpeer,
+ as_type, as)) {
+ filtered_count++;
+ count++;
+ continue;
+ }
+
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ if (peer->afc[afi][safi]) {
+ /* See if we have at least a single failed peer */
+ if (bgp_has_peer_failed(peer, afi, safi))
+ failed_count++;
+ count++;
+ }
+ if (peer_dynamic_neighbor(peer))
+ dn_count++;
+ }
+
+ } else {
+ /* Loop over all neighbors that will be displayed to determine
+ * how many
+ * characters are needed for the Neighbor column
+ */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (bgp_show_summary_is_peer_filtered(peer, fpeer,
+ as_type, as)) {
+ filtered_count++;
+ count++;
+ continue;
+ }
+
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ if (peer->afc[afi][safi]) {
+ memset(dn_flag, '\0', sizeof(dn_flag));
+ if (peer_dynamic_neighbor(peer))
+ dn_flag[0] = '*';
+
+ if (peer->hostname
+ && CHECK_FLAG(bgp->flags,
+ BGP_FLAG_SHOW_HOSTNAME))
+ snprintf(neighbor_buf,
+ sizeof(neighbor_buf),
+ "%s%s(%s) ", dn_flag,
+ peer->hostname, peer->host);
+ else
+ snprintf(neighbor_buf,
+ sizeof(neighbor_buf), "%s%s ",
+ dn_flag, peer->host);
+
+ len = strlen(neighbor_buf);
+
+ if (len > max_neighbor_width)
+ max_neighbor_width = len;
+
+ /* See if we have at least a single failed peer */
+ if (bgp_has_peer_failed(peer, afi, safi))
+ failed_count++;
+ count++;
+ }
+ }
+
+ /* Originally we displayed the Neighbor column as 16
+ * characters wide so make that the default
+ */
+ if (max_neighbor_width < neighbor_col_default_width)
+ max_neighbor_width = neighbor_col_default_width;
+ }
+
+ if (show_failed && !failed_count) {
+ if (use_json) {
+ json_object_int_add(json, "failedPeersCount", 0);
+ json_object_int_add(json, "dynamicPeers", dn_count);
+ json_object_int_add(json, "totalPeers", count);
+
+ vty_json(vty, json);
+ } else {
+ vty_out(vty, "%% No failed BGP neighbors found\n");
+ }
+ return CMD_SUCCESS;
+ }
+
+ count = 0; /* Reset the value as its used again */
+ filtered_count = 0;
+ dn_count = 0;
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ if (!peer->afc[afi][safi])
+ continue;
+
+ if (!count) {
+ unsigned long ents;
+ char memstrbuf[MTYPE_MEMSTR_LEN];
+ int64_t vrf_id_ui;
+
+ vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
+ ? -1
+ : (int64_t)bgp->vrf_id;
+
+ /* Usage summary and header */
+ if (use_json) {
+ json_object_string_addf(json, "routerId",
+ "%pI4",
+ &bgp->router_id);
+ asn_asn2json(json, "as", bgp->as,
+ bgp->asnotation);
+ json_object_int_add(json, "vrfId", vrf_id_ui);
+ json_object_string_add(
+ json, "vrfName",
+ (bgp->inst_type
+ == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+ } else {
+ vty_out(vty,
+ "BGP router identifier %pI4, local AS number %s vrf-id %d",
+ &bgp->router_id, bgp->as_pretty,
+ bgp->vrf_id == VRF_UNKNOWN
+ ? -1
+ : (int)bgp->vrf_id);
+ vty_out(vty, "\n");
+ }
+
+ if (bgp_update_delay_configured(bgp)) {
+ if (use_json) {
+ json_object_int_add(
+ json, "updateDelayLimit",
+ bgp->v_update_delay);
+
+ if (bgp->v_update_delay
+ != bgp->v_establish_wait)
+ json_object_int_add(
+ json,
+ "updateDelayEstablishWait",
+ bgp->v_establish_wait);
+
+ if (bgp_update_delay_active(bgp)) {
+ json_object_string_add(
+ json,
+ "updateDelayFirstNeighbor",
+ bgp->update_delay_begin_time);
+ json_object_boolean_true_add(
+ json,
+ "updateDelayInProgress");
+ } else {
+ if (bgp->update_delay_over) {
+ json_object_string_add(
+ json,
+ "updateDelayFirstNeighbor",
+ bgp->update_delay_begin_time);
+ json_object_string_add(
+ json,
+ "updateDelayBestpathResumed",
+ bgp->update_delay_end_time);
+ json_object_string_add(
+ json,
+ "updateDelayZebraUpdateResume",
+ bgp->update_delay_zebra_resume_time);
+ json_object_string_add(
+ json,
+ "updateDelayPeerUpdateResume",
+ bgp->update_delay_peers_resume_time);
+ }
+ }
+ } else {
+ vty_out(vty,
+ "Read-only mode update-delay limit: %d seconds\n",
+ bgp->v_update_delay);
+ if (bgp->v_update_delay
+ != bgp->v_establish_wait)
+ vty_out(vty,
+ " Establish wait: %d seconds\n",
+ bgp->v_establish_wait);
+
+ if (bgp_update_delay_active(bgp)) {
+ vty_out(vty,
+ " First neighbor established: %s\n",
+ bgp->update_delay_begin_time);
+ vty_out(vty,
+ " Delay in progress\n");
+ } else {
+ if (bgp->update_delay_over) {
+ vty_out(vty,
+ " First neighbor established: %s\n",
+ bgp->update_delay_begin_time);
+ vty_out(vty,
+ " Best-paths resumed: %s\n",
+ bgp->update_delay_end_time);
+ vty_out(vty,
+ " zebra update resumed: %s\n",
+ bgp->update_delay_zebra_resume_time);
+ vty_out(vty,
+ " peers update resumed: %s\n",
+ bgp->update_delay_peers_resume_time);
+ }
+ }
+ }
+ }
+
+ if (use_json) {
+ if (bgp_maxmed_onstartup_configured(bgp)
+ && bgp->maxmed_active)
+ json_object_boolean_true_add(
+ json, "maxMedOnStartup");
+ if (bgp->v_maxmed_admin)
+ json_object_boolean_true_add(
+ json, "maxMedAdministrative");
+
+ json_object_int_add(
+ json, "tableVersion",
+ bgp_table_version(bgp->rib[afi][safi]));
+
+ ents = bgp_table_count(bgp->rib[afi][safi]);
+ json_object_int_add(json, "ribCount", ents);
+ json_object_int_add(
+ json, "ribMemory",
+ ents * sizeof(struct bgp_dest));
+
+ ents = bgp->af_peer_count[afi][safi];
+ json_object_int_add(json, "peerCount", ents);
+ json_object_int_add(json, "peerMemory",
+ ents * sizeof(struct peer));
+
+ if ((ents = listcount(bgp->group))) {
+ json_object_int_add(
+ json, "peerGroupCount", ents);
+ json_object_int_add(
+ json, "peerGroupMemory",
+ ents * sizeof(struct
+ peer_group));
+ }
+
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_DAMPENING))
+ json_object_boolean_true_add(
+ json, "dampeningEnabled");
+ } else {
+ if (!show_terse) {
+ if (bgp_maxmed_onstartup_configured(bgp)
+ && bgp->maxmed_active)
+ vty_out(vty,
+ "Max-med on-startup active\n");
+ if (bgp->v_maxmed_admin)
+ vty_out(vty,
+ "Max-med administrative active\n");
+
+ vty_out(vty,
+ "BGP table version %" PRIu64
+ "\n",
+ bgp_table_version(
+ bgp->rib[afi][safi]));
+
+ ents = bgp_table_count(
+ bgp->rib[afi][safi]);
+ vty_out(vty,
+ "RIB entries %ld, using %s of memory\n",
+ ents,
+ mtype_memstr(
+ memstrbuf,
+ sizeof(memstrbuf),
+ ents
+ * sizeof(
+ struct
+ bgp_dest)));
+
+ /* Peer related usage */
+ ents = bgp->af_peer_count[afi][safi];
+ vty_out(vty,
+ "Peers %ld, using %s of memory\n",
+ ents,
+ mtype_memstr(
+ memstrbuf,
+ sizeof(memstrbuf),
+ ents
+ * sizeof(
+ struct
+ peer)));
+
+ if ((ents = listcount(bgp->group)))
+ vty_out(vty,
+ "Peer groups %ld, using %s of memory\n",
+ ents,
+ mtype_memstr(
+ memstrbuf,
+ sizeof(memstrbuf),
+ ents
+ * sizeof(
+ struct
+ peer_group)));
+
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_DAMPENING))
+ vty_out(vty,
+ "Dampening enabled.\n");
+ }
+ if (show_failed) {
+ vty_out(vty, "\n");
+
+ /* Subtract 8 here because 'Neighbor' is
+ * 8 characters */
+ vty_out(vty, "Neighbor");
+ vty_out(vty, "%*s",
+ max_neighbor_width - 8, " ");
+ vty_out(vty,
+ BGP_SHOW_SUMMARY_HEADER_FAILED);
+ }
+ }
+ }
+
+ paf = peer_af_find(peer, afi, safi);
+ filter = &peer->filter[afi][safi];
+
+ count++;
+ /* Works for both failed & successful cases */
+ if (peer_dynamic_neighbor(peer))
+ dn_count++;
+
+ if (use_json) {
+ json_peer = NULL;
+ if (bgp_show_summary_is_peer_filtered(peer, fpeer,
+ as_type, as)) {
+ filtered_count++;
+ continue;
+ }
+ if (show_failed &&
+ bgp_has_peer_failed(peer, afi, safi)) {
+ json_peer = json_object_new_object();
+ bgp_show_failed_summary(vty, bgp, peer,
+ json_peer, 0, use_json);
+ } else if (!show_failed) {
+ if (show_established
+ && bgp_has_peer_failed(peer, afi, safi)) {
+ filtered_count++;
+ continue;
+ }
+
+ json_peer = json_object_new_object();
+ if (peer_dynamic_neighbor(peer)) {
+ json_object_boolean_true_add(json_peer,
+ "dynamicPeer");
+ }
+
+ if (peer->hostname)
+ json_object_string_add(json_peer, "hostname",
+ peer->hostname);
+
+ if (peer->domainname)
+ json_object_string_add(json_peer, "domainname",
+ peer->domainname);
+
+ asn_asn2json(json_peer, "remoteAs", peer->as,
+ bgp->asnotation);
+ asn_asn2json(json_peer, "localAs",
+ peer->change_local_as
+ ? peer->change_local_as
+ : peer->local_as,
+ bgp->asnotation);
+ json_object_int_add(json_peer, "version", 4);
+ json_object_int_add(json_peer, "msgRcvd",
+ PEER_TOTAL_RX(peer));
+ json_object_int_add(json_peer, "msgSent",
+ PEER_TOTAL_TX(peer));
+
+ atomic_size_t outq_count, inq_count;
+ outq_count =
+ atomic_load_explicit(&peer->connection
+ ->obuf
+ ->count,
+ memory_order_relaxed);
+ inq_count =
+ atomic_load_explicit(&peer->connection
+ ->ibuf
+ ->count,
+ memory_order_relaxed);
+
+ json_object_int_add(
+ json_peer, "tableVersion",
+ (paf && PAF_SUBGRP(paf))
+ ? paf->subgroup->version
+ : 0);
+ json_object_int_add(json_peer, "outq",
+ outq_count);
+ json_object_int_add(json_peer, "inq",
+ inq_count);
+ peer_uptime(peer->uptime, timebuf, BGP_UPTIME_LEN,
+ use_json, json_peer);
+
+ json_object_int_add(json_peer, "pfxRcd",
+ peer->pcount[afi][pfx_rcd_safi]);
+
+ if (paf && PAF_SUBGRP(paf))
+ json_object_int_add(
+ json_peer, "pfxSnt",
+ (PAF_SUBGRP(paf))->scount);
+ else
+ json_object_int_add(json_peer, "pfxSnt",
+ 0);
+
+ /* BGP FSM state */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(peer->bgp->flags,
+ BGP_FLAG_SHUTDOWN))
+ json_object_string_add(json_peer,
+ "state",
+ "Idle (Admin)");
+ else if (peer->afc_recv[afi][safi])
+ json_object_string_add(
+ json_peer, "state",
+ lookup_msg(bgp_status_msg,
+ peer->connection->status,
+ NULL));
+ else if (CHECK_FLAG(
+ peer->sflags,
+ PEER_STATUS_PREFIX_OVERFLOW))
+ json_object_string_add(json_peer,
+ "state",
+ "Idle (PfxCt)");
+ else
+ json_object_string_add(
+ json_peer, "state",
+ lookup_msg(bgp_status_msg,
+ peer->connection->status,
+ NULL));
+
+ /* BGP peer state */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(peer->bgp->flags,
+ BGP_FLAG_SHUTDOWN))
+ json_object_string_add(json_peer,
+ "peerState",
+ "Admin");
+ else if (CHECK_FLAG(
+ peer->sflags,
+ PEER_STATUS_PREFIX_OVERFLOW))
+ json_object_string_add(json_peer,
+ "peerState",
+ "PfxCt");
+ else if (CHECK_FLAG(peer->flags,
+ PEER_FLAG_PASSIVE))
+ json_object_string_add(json_peer,
+ "peerState",
+ "Passive");
+ else if (CHECK_FLAG(peer->sflags,
+ PEER_STATUS_NSF_WAIT))
+ json_object_string_add(json_peer,
+ "peerState",
+ "NSF passive");
+ else if (CHECK_FLAG(
+ peer->bgp->flags,
+ BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && (!bgp_inbound_policy_exists(peer,
+ filter)
+ || !bgp_outbound_policy_exists(
+ peer, filter)))
+ json_object_string_add(json_peer,
+ "peerState",
+ "Policy");
+ else
+ json_object_string_add(
+ json_peer, "peerState", "OK");
+
+ json_object_int_add(json_peer, "connectionsEstablished",
+ peer->established);
+ json_object_int_add(json_peer, "connectionsDropped",
+ peer->dropped);
+ if (peer->desc)
+ json_object_string_add(
+ json_peer, "desc", peer->desc);
+ }
+ /* Avoid creating empty peer dicts in JSON */
+ if (json_peer == NULL)
+ continue;
+
+ if (peer->conf_if)
+ json_object_string_add(json_peer, "idType",
+ "interface");
+ else if (peer->connection->su.sa.sa_family == AF_INET)
+ json_object_string_add(json_peer, "idType",
+ "ipv4");
+ else if (peer->connection->su.sa.sa_family == AF_INET6)
+ json_object_string_add(json_peer, "idType",
+ "ipv6");
+ json_object_object_add(json_peers, peer->host,
+ json_peer);
+ } else {
+ if (bgp_show_summary_is_peer_filtered(peer, fpeer,
+ as_type, as)) {
+ filtered_count++;
+ continue;
+ }
+ if (show_failed &&
+ bgp_has_peer_failed(peer, afi, safi)) {
+ bgp_show_failed_summary(vty, bgp, peer, NULL,
+ max_neighbor_width,
+ use_json);
+ } else if (!show_failed) {
+ if (show_established
+ && bgp_has_peer_failed(peer, afi, safi)) {
+ filtered_count++;
+ continue;
+ }
+
+ if ((count - filtered_count) == 1) {
+ /* display headline before the first
+ * neighbor line */
+ vty_out(vty, "\n");
+
+ /* Subtract 8 here because 'Neighbor' is
+ * 8 characters */
+ vty_out(vty, "Neighbor");
+ vty_out(vty, "%*s",
+ max_neighbor_width - 8, " ");
+ vty_out(vty,
+ show_wide
+ ? BGP_SHOW_SUMMARY_HEADER_ALL_WIDE
+ : BGP_SHOW_SUMMARY_HEADER_ALL);
+ }
+
+ memset(dn_flag, '\0', sizeof(dn_flag));
+ if (peer_dynamic_neighbor(peer)) {
+ dn_flag[0] = '*';
+ }
+
+ if (peer->hostname
+ && CHECK_FLAG(bgp->flags,
+ BGP_FLAG_SHOW_HOSTNAME))
+ len = vty_out(vty, "%s%s(%s)", dn_flag,
+ peer->hostname,
+ peer->host);
+ else
+ len = vty_out(vty, "%s%s", dn_flag, peer->host);
+
+ /* pad the neighbor column with spaces */
+ if (len < max_neighbor_width)
+ vty_out(vty, "%*s", max_neighbor_width - len,
+ " ");
+
+ atomic_size_t outq_count, inq_count;
+ outq_count =
+ atomic_load_explicit(&peer->connection
+ ->obuf
+ ->count,
+ memory_order_relaxed);
+ inq_count =
+ atomic_load_explicit(&peer->connection
+ ->ibuf
+ ->count,
+ memory_order_relaxed);
+
+ vty_out(vty, "4");
+ vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation),
+ &peer->as);
+ if (show_wide)
+ vty_out(vty,
+ ASN_FORMAT_SPACE(
+ bgp->asnotation),
+ peer->change_local_as
+ ? &peer->change_local_as
+ : &peer->local_as);
+ vty_out(vty,
+ " %9u %9u %8" PRIu64 " %4zu %4zu %8s",
+ PEER_TOTAL_RX(peer),
+ PEER_TOTAL_TX(peer),
+ (paf && PAF_SUBGRP(paf))
+ ? paf->subgroup->version
+ : 0,
+ inq_count, outq_count,
+ peer_uptime(peer->uptime, timebuf,
+ BGP_UPTIME_LEN, 0, NULL));
+
+ if (peer_established(peer->connection)) {
+ if (peer->afc_recv[afi][safi]) {
+ if (CHECK_FLAG(
+ bgp->flags,
+ BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && !bgp_inbound_policy_exists(
+ peer, filter))
+ vty_out(vty, " %12s",
+ "(Policy)");
+ else
+ vty_out(vty,
+ " %12u",
+ peer->pcount
+ [afi]
+ [pfx_rcd_safi]);
+ } else {
+ vty_out(vty, " NoNeg");
+ }
+
+ if (paf && PAF_SUBGRP(paf)) {
+ if (CHECK_FLAG(
+ bgp->flags,
+ BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && !bgp_outbound_policy_exists(
+ peer, filter))
+ vty_out(vty, " %8s",
+ "(Policy)");
+ else
+ vty_out(vty,
+ " %8u",
+ (PAF_SUBGRP(
+ paf))
+ ->scount);
+ } else {
+ vty_out(vty, " NoNeg");
+ }
+ } else {
+ if (CHECK_FLAG(peer->flags,
+ PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(peer->bgp->flags,
+ BGP_FLAG_SHUTDOWN))
+ vty_out(vty, " Idle (Admin)");
+ else if (CHECK_FLAG(
+ peer->sflags,
+ PEER_STATUS_PREFIX_OVERFLOW))
+ vty_out(vty, " Idle (PfxCt)");
+ else
+ vty_out(vty, " %12s",
+ lookup_msg(bgp_status_msg,
+ peer->connection
+ ->status,
+ NULL));
+
+ vty_out(vty, " %8u", 0);
+ }
+ /* Make sure `Desc` column is the lastest in
+ * the output.
+ * If the description is not set, try
+ * to print the software version if the
+ * capability is enabled and received.
+ */
+ if (peer->desc)
+ vty_out(vty, " %s",
+ bgp_peer_description_stripped(
+ peer->desc,
+ show_wide ? 64 : 20));
+ else if (peer->soft_version) {
+ vty_out(vty, " %s",
+ bgp_peer_description_stripped(
+ peer->soft_version,
+ show_wide ? 64 : 20));
+ } else {
+ vty_out(vty, " N/A");
+ }
+ vty_out(vty, "\n");
+ }
+
+ }
+ }
+
+ if (use_json) {
+ json_object_object_add(json, "peers", json_peers);
+ json_object_int_add(json, "failedPeers", failed_count);
+ json_object_int_add(json, "displayedPeers",
+ count - filtered_count);
+ json_object_int_add(json, "totalPeers", count);
+ json_object_int_add(json, "dynamicPeers", dn_count);
+
+ if (!show_failed)
+ bgp_show_bestpath_json(bgp, json);
+
+ vty_json(vty, json);
+ } else {
+ if (count) {
+ if (filtered_count == count)
+ vty_out(vty, "\n%% No matching neighbor\n");
+ else {
+ if (show_failed)
+ vty_out(vty, "\nDisplayed neighbors %d",
+ failed_count);
+ else if (as_type != AS_UNSPECIFIED || as
+ || fpeer || show_established)
+ vty_out(vty, "\nDisplayed neighbors %d",
+ count - filtered_count);
+
+ vty_out(vty, "\nTotal number of neighbors %d\n",
+ count);
+ }
+ } else {
+ vty_out(vty, "No %s neighbor is configured\n",
+ get_afi_safi_str(afi, safi, false));
+ }
+
+ if (dn_count) {
+ vty_out(vty, "* - dynamic neighbor\n");
+ vty_out(vty, "%d dynamic neighbor(s), limit %d\n",
+ dn_count, bgp->dynamic_neighbors_limit);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
+ int safi, struct peer *fpeer, int as_type,
+ as_t as, uint16_t show_flags)
+{
+ int is_first = 1;
+ int afi_wildcard = (afi == AFI_MAX);
+ int safi_wildcard = (safi == SAFI_MAX);
+ int is_wildcard = (afi_wildcard || safi_wildcard);
+ bool nbr_output = false;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
+ if (use_json && is_wildcard)
+ vty_out(vty, "{\n");
+ if (afi_wildcard)
+ afi = 1; /* AFI_IP */
+ while (afi < AFI_MAX) {
+ if (safi_wildcard)
+ safi = 1; /* SAFI_UNICAST */
+ while (safi < SAFI_MAX) {
+ if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
+ nbr_output = true;
+
+ if (is_wildcard) {
+ /*
+ * So limit output to those afi/safi
+ * pairs that
+ * actualy have something interesting in
+ * them
+ */
+ if (use_json) {
+ if (!is_first)
+ vty_out(vty, ",\n");
+ else
+ is_first = 0;
+
+ vty_out(vty, "\"%s\":",
+ get_afi_safi_str(afi,
+ safi,
+ true));
+ } else {
+ vty_out(vty,
+ "\n%s Summary (%s):\n",
+ get_afi_safi_str(afi,
+ safi,
+ false),
+ bgp->name_pretty);
+ }
+ }
+ bgp_show_summary(vty, bgp, afi, safi, fpeer,
+ as_type, as, show_flags);
+ }
+ safi++;
+ if (!safi_wildcard)
+ safi = SAFI_MAX;
+ }
+ afi++;
+ if (!afi_wildcard)
+ afi = AFI_MAX;
+ }
+
+ if (use_json && is_wildcard)
+ vty_out(vty, "}\n");
+ else if (!nbr_output) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% No BGP neighbors found in %s\n",
+ bgp->name_pretty);
+ }
+}
+
+static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
+ safi_t safi,
+ const char *neighbor,
+ int as_type, as_t as,
+ uint16_t show_flags)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ struct peer *fpeer = NULL;
+ int is_first = 1;
+ bool nbr_output = false;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
+ if (use_json)
+ vty_out(vty, "{\n");
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ nbr_output = true;
+ if (use_json) {
+ if (!is_first)
+ vty_out(vty, ",\n");
+ else
+ is_first = 0;
+
+ vty_out(vty, "\"%s\":",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+ }
+ if (neighbor) {
+ fpeer = peer_lookup_in_view(vty, bgp, neighbor,
+ use_json);
+ if (!fpeer)
+ continue;
+ }
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer, as_type,
+ as, show_flags);
+ }
+
+ if (use_json)
+ vty_out(vty, "}\n");
+ else if (!nbr_output)
+ vty_out(vty, "%% BGP instance not found\n");
+}
+
+int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
+ safi_t safi, const char *neighbor, int as_type,
+ as_t as, uint16_t show_flags)
+{
+ struct bgp *bgp;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ struct peer *fpeer = NULL;
+
+ if (name) {
+ if (strmatch(name, "all")) {
+ bgp_show_all_instances_summary_vty(vty, afi, safi,
+ neighbor, as_type,
+ as, show_flags);
+ return CMD_SUCCESS;
+ } else {
+ bgp = bgp_lookup_by_name(name);
+
+ if (!bgp) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty,
+ "%% BGP instance not found\n");
+ return CMD_WARNING;
+ }
+
+ if (neighbor) {
+ fpeer = peer_lookup_in_view(vty, bgp, neighbor,
+ use_json);
+ if (!fpeer)
+ return CMD_WARNING;
+ }
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer,
+ as_type, as, show_flags);
+ return CMD_SUCCESS;
+ }
+ }
+
+ bgp = bgp_get_default();
+
+ if (bgp) {
+ if (neighbor) {
+ fpeer = peer_lookup_in_view(vty, bgp, neighbor,
+ use_json);
+ if (!fpeer)
+ return CMD_WARNING;
+ }
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer, as_type,
+ as, show_flags);
+ } else {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% BGP instance not found\n");
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* `show [ip] bgp summary' commands. */
+DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
+ " [" BGP_SAFI_WITH_LABEL_CMD_STR
+ "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <ASNUM|internal|external>>] [terse] [wide] [json$uj]",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display the entries for all address families\n"
+ "Summary of BGP neighbor status\n"
+ "Show only sessions in Established state\n"
+ "Show only sessions not in Established state\n"
+ "Show only the specified neighbor session\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on BGP configured interface\n"
+ "Show only the specified remote AS sessions\n" AS_STR
+ "Internal (iBGP) AS sessions\n"
+ "External (eBGP) AS sessions\n"
+ "Shorten the information on BGP instances\n"
+ "Increase table width for longer output\n" JSON_STR)
+{
+ char *vrf = NULL;
+ afi_t afi = AFI_MAX;
+ safi_t safi = SAFI_MAX;
+ as_t as = 0; /* 0 means AS filter not set */
+ int as_type = AS_UNSPECIFIED;
+ uint16_t show_flags = 0;
+
+ int idx = 0;
+
+ /* show [ip] bgp */
+ if (!all && argv_find(argv, argc, "ip", &idx))
+ afi = AFI_IP;
+ /* [<vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ } else if (argv_find(argv, argc, "view", &idx))
+ /* [<view> VIEWVRFNAME] */
+ vrf = argv[idx + 1]->arg;
+ /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
+ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
+ argv_find_and_parse_safi(argv, argc, &idx, &safi);
+ }
+
+ if (argv_find(argv, argc, "failed", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
+
+ if (argv_find(argv, argc, "established", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
+
+ if (argv_find(argv, argc, "remote-as", &idx)) {
+ if (argv[idx + 1]->arg[0] == 'i')
+ as_type = AS_INTERNAL;
+ else if (argv[idx + 1]->arg[0] == 'e')
+ as_type = AS_EXTERNAL;
+ else if (!asn_str2asn(argv[idx + 1]->arg, &as)) {
+ vty_out(vty,
+ "%% Invalid neighbor remote-as value: %s\n",
+ argv[idx + 1]->arg);
+ return CMD_SUCCESS;
+ }
+ }
+
+ if (argv_find(argv, argc, "terse", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
+
+ if (argv_find(argv, argc, "wide", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
+
+ if (argv_find(argv, argc, "json", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
+ return bgp_show_summary_vty(vty, vrf, afi, safi, neighbor, as_type, as,
+ show_flags);
+}
+
+const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json)
+{
+ if (for_json)
+ return get_afi_safi_json_str(afi, safi);
+ else
+ return get_afi_safi_vty_str(afi, safi);
+}
+
+
+static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p,
+ afi_t afi, safi_t safi,
+ uint16_t adv_smcap, uint16_t adv_rmcap,
+ uint16_t rcv_smcap, uint16_t rcv_rmcap,
+ bool use_json, json_object *json_pref)
+{
+ /* Send-Mode */
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap)
+ || CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap)) {
+ if (use_json) {
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap)
+ && CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap))
+ json_object_string_add(json_pref, "sendMode",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap))
+ json_object_string_add(json_pref, "sendMode",
+ "advertised");
+ else if (CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap))
+ json_object_string_add(json_pref, "sendMode",
+ "received");
+ } else {
+ vty_out(vty, " Send-mode: ");
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap))
+ vty_out(vty, "advertised");
+ if (CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap))
+ vty_out(vty, "%sreceived",
+ CHECK_FLAG(p->af_cap[afi][safi],
+ adv_smcap)
+ ? ", "
+ : "");
+ vty_out(vty, "\n");
+ }
+ }
+
+ /* Receive-Mode */
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap)
+ || CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap)) {
+ if (use_json) {
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap)
+ && CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap))
+ json_object_string_add(json_pref, "recvMode",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap))
+ json_object_string_add(json_pref, "recvMode",
+ "advertised");
+ else if (CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap))
+ json_object_string_add(json_pref, "recvMode",
+ "received");
+ } else {
+ vty_out(vty, " Receive-mode: ");
+ if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap))
+ vty_out(vty, "advertised");
+ if (CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap))
+ vty_out(vty, "%sreceived",
+ CHECK_FLAG(p->af_cap[afi][safi],
+ adv_rmcap)
+ ? ", "
+ : "");
+ vty_out(vty, "\n");
+ }
+ }
+}
+
+static void bgp_show_neighnor_graceful_restart_flags(struct vty *vty,
+ struct peer *p,
+ json_object *json)
+{
+ bool rbit = false;
+ bool nbit = false;
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV) &&
+ (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) &&
+ (peer_established(p->connection))) {
+ rbit = CHECK_FLAG(p->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
+ nbit = CHECK_FLAG(p->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
+ }
+
+ if (json) {
+ json_object_boolean_add(json, "rBit", rbit);
+ json_object_boolean_add(json, "nBit", nbit);
+ } else {
+ vty_out(vty, "\n R bit: %s", rbit ? "True" : "False");
+ vty_out(vty, "\n N bit: %s\n", nbit ? "True" : "False");
+ }
+}
+
+static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty,
+ struct peer *peer,
+ json_object *json)
+{
+ const char *mode = "NotApplicable";
+
+ if (!json)
+ vty_out(vty, "\n Remote GR Mode: ");
+
+ if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) &&
+ (peer_established(peer->connection))) {
+ if ((peer->nsf_af_count == 0)
+ && !CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
+
+ mode = "Disable";
+
+ } else if (peer->nsf_af_count == 0
+ && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
+
+ mode = "Helper";
+
+ } else if (peer->nsf_af_count != 0
+ && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
+
+ mode = "Restart";
+ }
+ }
+
+ if (json)
+ json_object_string_add(json, "remoteGrMode", mode);
+ else
+ vty_out(vty, "%s\n", mode);
+}
+
+static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
+ struct peer *p,
+ json_object *json)
+{
+ const char *mode = "Invalid";
+
+ if (!json)
+ vty_out(vty, " Local GR Mode: ");
+
+ if (bgp_peer_gr_mode_get(p) == PEER_HELPER)
+ mode = "Helper";
+ else if (bgp_peer_gr_mode_get(p) == PEER_GR)
+ mode = "Restart";
+ else if (bgp_peer_gr_mode_get(p) == PEER_DISABLE)
+ mode = "Disable";
+ else if (bgp_peer_gr_mode_get(p) == PEER_GLOBAL_INHERIT) {
+ if (bgp_global_gr_mode_get(p->bgp) == GLOBAL_HELPER)
+ mode = "Helper*";
+ else if (bgp_global_gr_mode_get(p->bgp) == GLOBAL_GR)
+ mode = "Restart*";
+ else if (bgp_global_gr_mode_get(p->bgp) == GLOBAL_DISABLE)
+ mode = "Disable*";
+ else
+ mode = "Invalid*";
+ }
+
+ if (json)
+ json_object_string_add(json, "localGrMode", mode);
+ else
+ vty_out(vty, "%s\n", mode);
+}
+
+static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
+ struct vty *vty, struct peer *peer, json_object *json)
+{
+ afi_t afi;
+ safi_t safi;
+ json_object *json_afi_safi = NULL;
+ json_object *json_timer = NULL;
+ json_object *json_endofrib_status = NULL;
+ bool eor_flag = false;
+
+ FOREACH_AFI_SAFI_NSF (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) ||
+ !CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV))
+ continue;
+
+ if (json) {
+ json_afi_safi = json_object_new_object();
+ json_endofrib_status = json_object_new_object();
+ json_timer = json_object_new_object();
+ }
+
+ if (peer->eor_stime[afi][safi] >= peer->pkt_stime[afi][safi])
+ eor_flag = true;
+ else
+ eor_flag = false;
+
+ if (!json) {
+ vty_out(vty, " %s:\n",
+ get_afi_safi_str(afi, safi, false));
+
+ vty_out(vty, " F bit: ");
+ }
+
+ if (peer->nsf[afi][safi] &&
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV)) {
+
+ if (json) {
+ json_object_boolean_true_add(json_afi_safi,
+ "fBit");
+ } else
+ vty_out(vty, "True\n");
+ } else {
+ if (json)
+ json_object_boolean_false_add(json_afi_safi,
+ "fBit");
+ else
+ vty_out(vty, "False\n");
+ }
+
+ if (!json)
+ vty_out(vty, " End-of-RIB sent: ");
+
+ if (CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_SEND)) {
+ if (json) {
+ json_object_boolean_true_add(
+ json_endofrib_status, "endOfRibSend");
+
+ PRINT_EOR_JSON(eor_flag);
+ } else {
+ vty_out(vty, "Yes\n");
+ vty_out(vty,
+ " End-of-RIB sent after update: ");
+
+ PRINT_EOR(eor_flag);
+ }
+ } else {
+ if (json) {
+ json_object_boolean_false_add(
+ json_endofrib_status, "endOfRibSend");
+ json_object_boolean_false_add(
+ json_endofrib_status,
+ "endOfRibSentAfterUpdate");
+ } else {
+ vty_out(vty, "No\n");
+ vty_out(vty,
+ " End-of-RIB sent after update: ");
+ vty_out(vty, "No\n");
+ }
+ }
+
+ if (!json)
+ vty_out(vty, " End-of-RIB received: ");
+
+ if (CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED)) {
+ if (json)
+ json_object_boolean_true_add(
+ json_endofrib_status, "endOfRibRecv");
+ else
+ vty_out(vty, "Yes\n");
+ } else {
+ if (json)
+ json_object_boolean_false_add(
+ json_endofrib_status, "endOfRibRecv");
+ else
+ vty_out(vty, "No\n");
+ }
+
+ if (json) {
+ json_object_int_add(json_timer, "stalePathTimer",
+ peer->bgp->stalepath_time);
+ json_object_int_add(json_timer, "llgrStaleTime",
+ peer->llgr[afi][safi].stale_time);
+
+ if (peer->connection->t_gr_stale != NULL) {
+ json_object_int_add(json_timer,
+ "stalePathTimerRemaining",
+ event_timer_remain_second(
+ peer->connection
+ ->t_gr_stale));
+ }
+
+ /* Display Configured Selection
+ * Deferral only when when
+ * Gr mode is enabled.
+ */
+ if (CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART)) {
+ json_object_int_add(json_timer,
+ "selectionDeferralTimer",
+ peer->bgp->stalepath_time);
+ }
+
+ if (peer->bgp->gr_info[afi][safi].t_select_deferral !=
+ NULL) {
+
+ json_object_int_add(
+ json_timer,
+ "selectionDeferralTimerRemaining",
+ event_timer_remain_second(
+ peer->bgp->gr_info[afi][safi]
+ .t_select_deferral));
+ }
+ } else {
+ vty_out(vty, " Timers:\n");
+ vty_out(vty,
+ " Configured Stale Path Time(sec): %u\n",
+ peer->bgp->stalepath_time);
+
+ if (peer->connection->t_gr_stale != NULL)
+ vty_out(vty,
+ " Stale Path Remaining(sec): %ld\n",
+ event_timer_remain_second(
+ peer->connection->t_gr_stale));
+ /* Display Configured Selection
+ * Deferral only when when
+ * Gr mode is enabled.
+ */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
+ vty_out(vty,
+ " Configured Selection Deferral Time(sec): %u\n",
+ peer->bgp->select_defer_time);
+
+ vty_out(vty, " LLGR Stale Path Time(sec): %u\n",
+ peer->llgr[afi][safi].stale_time);
+
+ if (peer->bgp->gr_info[afi][safi].t_select_deferral !=
+ NULL)
+ vty_out(vty,
+ " Selection Deferral Time Remaining(sec): %ld\n",
+ event_timer_remain_second(
+ peer->bgp->gr_info[afi][safi]
+ .t_select_deferral));
+ }
+ if (json) {
+ json_object_object_add(json_afi_safi, "endOfRibStatus",
+ json_endofrib_status);
+ json_object_object_add(json_afi_safi, "timers",
+ json_timer);
+ json_object_object_add(
+ json, get_afi_safi_str(afi, safi, true),
+ json_afi_safi);
+ }
+ }
+}
+
+static void bgp_show_neighbor_graceful_restart_time(struct vty *vty,
+ struct peer *p,
+ json_object *json)
+{
+ if (json) {
+ json_object *json_timer = NULL;
+
+ json_timer = json_object_new_object();
+
+ json_object_int_add(json_timer, "configuredRestartTimer",
+ p->bgp->restart_time);
+ json_object_int_add(json_timer, "configuredLlgrStaleTime",
+ p->bgp->llgr_stale_time);
+
+ json_object_int_add(json_timer, "receivedRestartTimer",
+ p->v_gr_restart);
+
+ if (p->connection->t_gr_restart != NULL)
+ json_object_int_add(json_timer, "restartTimerRemaining",
+ event_timer_remain_second(
+ p->connection->t_gr_restart));
+
+ json_object_object_add(json, "timers", json_timer);
+ } else {
+
+ vty_out(vty, " Timers:\n");
+ vty_out(vty, " Configured Restart Time(sec): %u\n",
+ p->bgp->restart_time);
+
+ vty_out(vty, " Received Restart Time(sec): %u\n",
+ p->v_gr_restart);
+ vty_out(vty, " Configured LLGR Stale Path Time(sec): %u\n",
+ p->bgp->llgr_stale_time);
+ if (p->connection->t_gr_restart != NULL)
+ vty_out(vty, " Restart Time Remaining(sec): %ld\n",
+ event_timer_remain_second(
+ p->connection->t_gr_restart));
+ if (p->connection->t_gr_restart != NULL) {
+ vty_out(vty, " Restart Time Remaining(sec): %ld\n",
+ event_timer_remain_second(
+ p->connection->t_gr_restart));
+ }
+ }
+}
+
+static void bgp_show_peer_gr_status(struct vty *vty, struct peer *p,
+ json_object *json)
+{
+ char dn_flag[2] = {0};
+ /* '*' + v6 address of neighbor */
+ char neighborAddr[INET6_ADDRSTRLEN + 1] = {0};
+
+ if (!p->conf_if && peer_dynamic_neighbor(p))
+ dn_flag[0] = '*';
+
+ if (p->conf_if) {
+ if (json)
+ json_object_string_addf(json, "neighborAddr", "%pSU",
+ &p->connection->su);
+ else
+ vty_out(vty, "BGP neighbor on %s: %pSU\n", p->conf_if,
+ &p->connection->su);
+ } else {
+ snprintf(neighborAddr, sizeof(neighborAddr), "%s%s", dn_flag,
+ p->host);
+
+ if (json)
+ json_object_string_add(json, "neighborAddr",
+ neighborAddr);
+ else
+ vty_out(vty, "BGP neighbor is %s\n", neighborAddr);
+ }
+
+ /* more gr info in new format */
+ BGP_SHOW_PEER_GR_CAPABILITY(vty, p, json);
+}
+
+static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
+ safi_t safi, bool use_json,
+ json_object *json_neigh)
+{
+ struct bgp_filter *filter;
+ struct peer_af *paf;
+ char orf_pfx_name[BUFSIZ];
+ int orf_pfx_count;
+ json_object *json_af = NULL;
+ json_object *json_prefA = NULL;
+ json_object *json_addr = NULL;
+ json_object *json_advmap = NULL;
+
+ if (use_json) {
+ json_addr = json_object_new_object();
+ json_af = json_object_new_object();
+ filter = &p->filter[afi][safi];
+
+ if (peer_group_active(p))
+ json_object_string_add(json_addr, "peerGroupMember",
+ p->group->name);
+
+ paf = peer_af_find(p, afi, safi);
+ if (paf && PAF_SUBGRP(paf)) {
+ json_object_int_add(json_addr, "updateGroupId",
+ PAF_UPDGRP(paf)->id);
+ json_object_int_add(json_addr, "subGroupId",
+ PAF_SUBGRP(paf)->id);
+ json_object_int_add(json_addr, "packetQueueLength",
+ bpacket_queue_virtual_length(paf));
+ }
+
+ if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV)) {
+ json_object_int_add(json_af, "orfType",
+ ORF_TYPE_PREFIX);
+ json_prefA = json_object_new_object();
+ bgp_show_peer_afi_orf_cap(vty, p, afi, safi,
+ PEER_CAP_ORF_PREFIX_SM_ADV,
+ PEER_CAP_ORF_PREFIX_RM_ADV,
+ PEER_CAP_ORF_PREFIX_SM_RCV,
+ PEER_CAP_ORF_PREFIX_RM_RCV,
+ use_json, json_prefA);
+ json_object_object_add(json_af, "orfPrefixList",
+ json_prefA);
+ }
+
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
+ json_object_object_add(json_addr, "afDependentCap",
+ json_af);
+ else
+ json_object_free(json_af);
+
+ snprintf(orf_pfx_name, sizeof(orf_pfx_name), "%s.%d.%d",
+ p->host, afi, safi);
+ orf_pfx_count = prefix_bgp_show_prefix_list(
+ NULL, afi, orf_pfx_name, use_json);
+
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_PREFIX_SEND)
+ || orf_pfx_count) {
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_PREFIX_SEND))
+ json_object_boolean_true_add(json_neigh,
+ "orfSent");
+ if (orf_pfx_count)
+ json_object_int_add(json_addr, "orfRecvCounter",
+ orf_pfx_count);
+ }
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_WAIT_REFRESH))
+ json_object_string_add(
+ json_addr, "orfFirstUpdate",
+ "deferredUntilORFOrRouteRefreshRecvd");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REFLECTOR_CLIENT))
+ json_object_boolean_true_add(json_addr,
+ "routeReflectorClient");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ json_object_boolean_true_add(json_addr,
+ "routeServerClient");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+ json_object_boolean_true_add(json_addr,
+ "inboundSoftConfigPermit");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
+ json_object_boolean_true_add(
+ json_addr,
+ "privateAsNumsAllReplacedInUpdatesToNbr");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ json_object_boolean_true_add(
+ json_addr,
+ "privateAsNumsReplacedInUpdatesToNbr");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
+ json_object_boolean_true_add(
+ json_addr,
+ "privateAsNumsAllRemovedInUpdatesToNbr");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS))
+ json_object_boolean_true_add(
+ json_addr,
+ "privateAsNumsRemovedInUpdatesToNbr");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)) {
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN))
+ json_object_boolean_true_add(json_addr,
+ "allowAsInOrigin");
+ else
+ json_object_int_add(json_addr, "allowAsInCount",
+ p->allowas_in[afi][safi]);
+ }
+
+ if (p->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
+ json_object_boolean_true_add(
+ json_addr,
+ bgp_addpath_names(p->addpath_type[afi][safi])
+ ->type_json_name);
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
+ json_object_string_add(json_addr,
+ "overrideASNsInOutboundUpdates",
+ "ifAspathEqualRemoteAs");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)
+ || CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_FORCE_NEXTHOP_SELF))
+ json_object_boolean_true_add(json_addr,
+ "routerAlwaysNextHop");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_AS_PATH_UNCHANGED))
+ json_object_boolean_true_add(
+ json_addr, "unchangedAsPathPropogatedToNbr");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_NEXTHOP_UNCHANGED))
+ json_object_boolean_true_add(
+ json_addr, "unchangedNextHopPropogatedToNbr");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+ json_object_boolean_true_add(
+ json_addr, "unchangedMedPropogatedToNbr");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
+ || CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY)) {
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_COMMUNITY)
+ && CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY))
+ json_object_string_add(json_addr,
+ "commAttriSentToNbr",
+ "extendedAndStandard");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY))
+ json_object_string_add(json_addr,
+ "commAttriSentToNbr",
+ "extended");
+ else
+ json_object_string_add(json_addr,
+ "commAttriSentToNbr",
+ "standard");
+ }
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_DEFAULT_ORIGINATE)) {
+ if (p->default_rmap[afi][safi].name)
+ json_object_string_add(
+ json_addr, "defaultRouteMap",
+ p->default_rmap[afi][safi].name);
+
+ if (paf && PAF_SUBGRP(paf)
+ && CHECK_FLAG(PAF_SUBGRP(paf)->sflags,
+ SUBGRP_STATUS_DEFAULT_ORIGINATE))
+ json_object_boolean_true_add(json_addr,
+ "defaultSent");
+ else
+ json_object_boolean_true_add(json_addr,
+ "defaultNotSent");
+ }
+
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+ if (is_evpn_enabled())
+ json_object_boolean_true_add(
+ json_addr, "advertiseAllVnis");
+ }
+
+ if (filter->plist[FILTER_IN].name
+ || filter->dlist[FILTER_IN].name
+ || filter->aslist[FILTER_IN].name
+ || filter->map[RMAP_IN].name)
+ json_object_boolean_true_add(json_addr,
+ "inboundPathPolicyConfig");
+ if (filter->plist[FILTER_OUT].name
+ || filter->dlist[FILTER_OUT].name
+ || filter->aslist[FILTER_OUT].name
+ || filter->map[RMAP_OUT].name || filter->usmap.name)
+ json_object_boolean_true_add(
+ json_addr, "outboundPathPolicyConfig");
+
+ /* prefix-list */
+ if (filter->plist[FILTER_IN].name)
+ json_object_string_add(json_addr,
+ "incomingUpdatePrefixFilterList",
+ filter->plist[FILTER_IN].name);
+ if (filter->plist[FILTER_OUT].name)
+ json_object_string_add(json_addr,
+ "outgoingUpdatePrefixFilterList",
+ filter->plist[FILTER_OUT].name);
+
+ /* distribute-list */
+ if (filter->dlist[FILTER_IN].name)
+ json_object_string_add(
+ json_addr, "incomingUpdateNetworkFilterList",
+ filter->dlist[FILTER_IN].name);
+ if (filter->dlist[FILTER_OUT].name)
+ json_object_string_add(
+ json_addr, "outgoingUpdateNetworkFilterList",
+ filter->dlist[FILTER_OUT].name);
+
+ /* filter-list. */
+ if (filter->aslist[FILTER_IN].name)
+ json_object_string_add(json_addr,
+ "incomingUpdateAsPathFilterList",
+ filter->aslist[FILTER_IN].name);
+ if (filter->aslist[FILTER_OUT].name)
+ json_object_string_add(json_addr,
+ "outgoingUpdateAsPathFilterList",
+ filter->aslist[FILTER_OUT].name);
+
+ /* route-map. */
+ if (filter->map[RMAP_IN].name)
+ json_object_string_add(
+ json_addr, "routeMapForIncomingAdvertisements",
+ filter->map[RMAP_IN].name);
+ if (filter->map[RMAP_OUT].name)
+ json_object_string_add(
+ json_addr, "routeMapForOutgoingAdvertisements",
+ filter->map[RMAP_OUT].name);
+
+ /* ebgp-requires-policy (inbound) */
+ if (CHECK_FLAG(p->bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && !bgp_inbound_policy_exists(p, filter))
+ json_object_string_add(
+ json_addr, "inboundEbgpRequiresPolicy",
+ "Inbound updates discarded due to missing policy");
+
+ /* ebgp-requires-policy (outbound) */
+ if (CHECK_FLAG(p->bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && (!bgp_outbound_policy_exists(p, filter)))
+ json_object_string_add(
+ json_addr, "outboundEbgpRequiresPolicy",
+ "Outbound updates discarded due to missing policy");
+
+ /* unsuppress-map */
+ if (filter->usmap.name)
+ json_object_string_add(json_addr,
+ "selectiveUnsuppressRouteMap",
+ filter->usmap.name);
+
+ /* advertise-map */
+ if (filter->advmap.aname) {
+ json_advmap = json_object_new_object();
+ json_object_string_add(json_advmap, "condition",
+ filter->advmap.condition
+ ? "EXIST"
+ : "NON_EXIST");
+ json_object_string_add(json_advmap, "conditionMap",
+ filter->advmap.cname);
+ json_object_string_add(json_advmap, "advertiseMap",
+ filter->advmap.aname);
+ json_object_string_add(
+ json_advmap, "advertiseStatus",
+ filter->advmap.update_type ==
+ UPDATE_TYPE_ADVERTISE
+ ? "Advertise"
+ : "Withdraw");
+ json_object_object_add(json_addr, "advertiseMap",
+ json_advmap);
+ }
+
+ /* Receive prefix count */
+ json_object_int_add(json_addr, "acceptedPrefixCounter",
+ p->pcount[afi][safi]);
+ if (paf && PAF_SUBGRP(paf))
+ json_object_int_add(json_addr, "sentPrefixCounter",
+ (PAF_SUBGRP(paf))->scount);
+
+ /* Maximum prefix */
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT))
+ json_object_int_add(json_addr, "prefixOutAllowedMax",
+ p->pmax_out[afi][safi]);
+
+ /* Maximum prefix */
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) {
+ json_object_int_add(json_addr, "prefixAllowedMax",
+ p->pmax[afi][safi]);
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_WARNING))
+ json_object_boolean_true_add(
+ json_addr, "prefixAllowedMaxWarning");
+ json_object_int_add(json_addr,
+ "prefixAllowedWarningThresh",
+ p->pmax_threshold[afi][safi]);
+ if (p->pmax_restart[afi][safi])
+ json_object_int_add(
+ json_addr,
+ "prefixAllowedRestartIntervalMsecs",
+ p->pmax_restart[afi][safi] * 60000);
+ }
+ json_object_object_add(json_neigh,
+ get_afi_safi_str(afi, safi, true),
+ json_addr);
+
+ } else {
+ filter = &p->filter[afi][safi];
+
+ vty_out(vty, " For address family: %s\n",
+ get_afi_safi_str(afi, safi, false));
+
+ if (peer_group_active(p))
+ vty_out(vty, " %s peer-group member\n",
+ p->group->name);
+
+ paf = peer_af_find(p, afi, safi);
+ if (paf && PAF_SUBGRP(paf)) {
+ vty_out(vty, " Update group %" PRIu64", subgroup %" PRIu64 "\n",
+ PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id);
+ vty_out(vty, " Packet Queue length %d\n",
+ bpacket_queue_virtual_length(paf));
+ } else {
+ vty_out(vty, " Not part of any update group\n");
+ }
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
+ vty_out(vty, " AF-dependant capabilities:\n");
+
+ if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_RCV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_ADV)
+ || CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV)) {
+ vty_out(vty,
+ " Outbound Route Filter (ORF) type (%d) Prefix-list:\n",
+ ORF_TYPE_PREFIX);
+ bgp_show_peer_afi_orf_cap(
+ vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV,
+ PEER_CAP_ORF_PREFIX_RM_ADV,
+ PEER_CAP_ORF_PREFIX_SM_RCV,
+ PEER_CAP_ORF_PREFIX_RM_RCV, use_json, NULL);
+ }
+
+ snprintf(orf_pfx_name, sizeof(orf_pfx_name), "%s.%d.%d",
+ p->host, afi, safi);
+ orf_pfx_count = prefix_bgp_show_prefix_list(
+ NULL, afi, orf_pfx_name, use_json);
+
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_PREFIX_SEND)
+ || orf_pfx_count) {
+ vty_out(vty, " Outbound Route Filter (ORF):");
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_PREFIX_SEND))
+ vty_out(vty, " sent;");
+ if (orf_pfx_count)
+ vty_out(vty, " received (%d entries)",
+ orf_pfx_count);
+ vty_out(vty, "\n");
+ }
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_ORF_WAIT_REFRESH))
+ vty_out(vty,
+ " First update is deferred until ORF or ROUTE-REFRESH is received\n");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REFLECTOR_CLIENT))
+ vty_out(vty, " Route-Reflector Client\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT))
+ vty_out(vty, " Route-Server Client\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+ vty_out(vty,
+ " Inbound soft reconfiguration allowed\n");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
+ vty_out(vty,
+ " Private AS numbers (all) replaced in updates to this neighbor\n");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
+ vty_out(vty,
+ " Private AS numbers replaced in updates to this neighbor\n");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
+ vty_out(vty,
+ " Private AS numbers (all) removed in updates to this neighbor\n");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS))
+ vty_out(vty,
+ " Private AS numbers removed in updates to this neighbor\n");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)) {
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN))
+ vty_out(vty,
+ " Local AS allowed as path origin\n");
+ else
+ vty_out(vty,
+ " Local AS allowed in path, %d occurrences\n",
+ p->allowas_in[afi][safi]);
+ }
+
+ if (p->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
+ vty_out(vty, " %s\n",
+ bgp_addpath_names(p->addpath_type[afi][safi])
+ ->human_description);
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
+ vty_out(vty,
+ " Override ASNs in outbound updates if aspath equals remote-as\n");
+
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)
+ || CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_FORCE_NEXTHOP_SELF))
+ vty_out(vty, " NEXT_HOP is always this router\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_AS_PATH_UNCHANGED))
+ vty_out(vty,
+ " AS_PATH is propagated unchanged to this neighbor\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_NEXTHOP_UNCHANGED))
+ vty_out(vty,
+ " NEXT_HOP is propagated unchanged to this neighbor\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+ vty_out(vty,
+ " MED is propagated unchanged to this neighbor\n");
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
+ || CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY)
+ || CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_LARGE_COMMUNITY)) {
+ vty_out(vty,
+ " Community attribute sent to this neighbor");
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_COMMUNITY)
+ && CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY)
+ && CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_LARGE_COMMUNITY))
+ vty_out(vty, "(all)\n");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_LARGE_COMMUNITY))
+ vty_out(vty, "(large)\n");
+ else if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY))
+ vty_out(vty, "(extended)\n");
+ else
+ vty_out(vty, "(standard)\n");
+ }
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_DEFAULT_ORIGINATE)) {
+ vty_out(vty, " Default information originate,");
+
+ if (p->default_rmap[afi][safi].name)
+ vty_out(vty, " default route-map %s%s,",
+ p->default_rmap[afi][safi].map ? "*"
+ : "",
+ p->default_rmap[afi][safi].name);
+ if (paf && PAF_SUBGRP(paf)
+ && CHECK_FLAG(PAF_SUBGRP(paf)->sflags,
+ SUBGRP_STATUS_DEFAULT_ORIGINATE))
+ vty_out(vty, " default sent\n");
+ else
+ vty_out(vty, " default not sent\n");
+ }
+
+ /* advertise-vni-all */
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+ if (is_evpn_enabled())
+ vty_out(vty, " advertise-all-vni\n");
+ }
+
+ if (filter->plist[FILTER_IN].name
+ || filter->dlist[FILTER_IN].name
+ || filter->aslist[FILTER_IN].name
+ || filter->map[RMAP_IN].name)
+ vty_out(vty, " Inbound path policy configured\n");
+ if (filter->plist[FILTER_OUT].name
+ || filter->dlist[FILTER_OUT].name
+ || filter->aslist[FILTER_OUT].name
+ || filter->map[RMAP_OUT].name || filter->usmap.name)
+ vty_out(vty, " Outbound path policy configured\n");
+
+ /* prefix-list */
+ if (filter->plist[FILTER_IN].name)
+ vty_out(vty,
+ " Incoming update prefix filter list is %s%s\n",
+ filter->plist[FILTER_IN].plist ? "*" : "",
+ filter->plist[FILTER_IN].name);
+ if (filter->plist[FILTER_OUT].name)
+ vty_out(vty,
+ " Outgoing update prefix filter list is %s%s\n",
+ filter->plist[FILTER_OUT].plist ? "*" : "",
+ filter->plist[FILTER_OUT].name);
+
+ /* distribute-list */
+ if (filter->dlist[FILTER_IN].name)
+ vty_out(vty,
+ " Incoming update network filter list is %s%s\n",
+ filter->dlist[FILTER_IN].alist ? "*" : "",
+ filter->dlist[FILTER_IN].name);
+ if (filter->dlist[FILTER_OUT].name)
+ vty_out(vty,
+ " Outgoing update network filter list is %s%s\n",
+ filter->dlist[FILTER_OUT].alist ? "*" : "",
+ filter->dlist[FILTER_OUT].name);
+
+ /* filter-list. */
+ if (filter->aslist[FILTER_IN].name)
+ vty_out(vty,
+ " Incoming update AS path filter list is %s%s\n",
+ filter->aslist[FILTER_IN].aslist ? "*" : "",
+ filter->aslist[FILTER_IN].name);
+ if (filter->aslist[FILTER_OUT].name)
+ vty_out(vty,
+ " Outgoing update AS path filter list is %s%s\n",
+ filter->aslist[FILTER_OUT].aslist ? "*" : "",
+ filter->aslist[FILTER_OUT].name);
+
+ /* route-map. */
+ if (filter->map[RMAP_IN].name)
+ vty_out(vty,
+ " Route map for incoming advertisements is %s%s\n",
+ filter->map[RMAP_IN].map ? "*" : "",
+ filter->map[RMAP_IN].name);
+ if (filter->map[RMAP_OUT].name)
+ vty_out(vty,
+ " Route map for outgoing advertisements is %s%s\n",
+ filter->map[RMAP_OUT].map ? "*" : "",
+ filter->map[RMAP_OUT].name);
+
+ /* ebgp-requires-policy (inbound) */
+ if (CHECK_FLAG(p->bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && !bgp_inbound_policy_exists(p, filter))
+ vty_out(vty,
+ " Inbound updates discarded due to missing policy\n");
+
+ /* ebgp-requires-policy (outbound) */
+ if (CHECK_FLAG(p->bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY)
+ && !bgp_outbound_policy_exists(p, filter))
+ vty_out(vty,
+ " Outbound updates discarded due to missing policy\n");
+
+ /* unsuppress-map */
+ if (filter->usmap.name)
+ vty_out(vty,
+ " Route map for selective unsuppress is %s%s\n",
+ filter->usmap.map ? "*" : "",
+ filter->usmap.name);
+
+ /* advertise-map */
+ if (filter->advmap.aname && filter->advmap.cname)
+ vty_out(vty,
+ " Condition %s, Condition-map %s%s, Advertise-map %s%s, status: %s\n",
+ filter->advmap.condition ? "EXIST"
+ : "NON_EXIST",
+ filter->advmap.cmap ? "*" : "",
+ filter->advmap.cname,
+ filter->advmap.amap ? "*" : "",
+ filter->advmap.aname,
+ filter->advmap.update_type ==
+ UPDATE_TYPE_ADVERTISE
+ ? "Advertise"
+ : "Withdraw");
+
+ /* Receive prefix count */
+ vty_out(vty, " %u accepted prefixes\n",
+ p->pcount[afi][safi]);
+
+ /* maximum-prefix-out */
+ if (CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_OUT))
+ vty_out(vty,
+ " Maximum allowed prefixes sent %u\n",
+ p->pmax_out[afi][safi]);
+
+ /* Maximum prefix */
+ if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) {
+ vty_out(vty,
+ " Maximum prefixes allowed %u%s\n",
+ p->pmax[afi][safi],
+ CHECK_FLAG(p->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_WARNING)
+ ? " (warning-only)"
+ : "");
+ vty_out(vty, " Threshold for warning message %d%%",
+ p->pmax_threshold[afi][safi]);
+ if (p->pmax_restart[afi][safi])
+ vty_out(vty, ", restart interval %d min",
+ p->pmax_restart[afi][safi]);
+ vty_out(vty, "\n");
+ }
+
+ vty_out(vty, "\n");
+ }
+}
+
+static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
+ json_object *json)
+{
+ struct bgp *bgp;
+ char timebuf[BGP_UPTIME_LEN];
+ char dn_flag[2];
+ afi_t afi;
+ safi_t safi;
+ uint16_t i;
+ uint8_t *msg;
+ json_object *json_neigh = NULL;
+ time_t epoch_tbuf;
+ uint32_t sync_tcp_mss;
+
+ bgp = p->bgp;
+
+ if (use_json)
+ json_neigh = json_object_new_object();
+
+ memset(dn_flag, '\0', sizeof(dn_flag));
+ if (!p->conf_if && peer_dynamic_neighbor(p))
+ dn_flag[0] = '*';
+
+ if (!use_json) {
+ if (p->conf_if) /* Configured interface name. */
+ vty_out(vty, "BGP neighbor on %s: %pSU, ", p->conf_if,
+ &p->connection->su);
+ else /* Configured IP address. */
+ vty_out(vty, "BGP neighbor is %s%s, ", dn_flag,
+ p->host);
+ }
+
+ if (use_json) {
+ if (p->conf_if && BGP_CONNECTION_SU_UNSPEC(p->connection))
+ json_object_string_add(json_neigh, "bgpNeighborAddr",
+ "none");
+ else if (p->conf_if && !BGP_CONNECTION_SU_UNSPEC(p->connection))
+ json_object_string_addf(json_neigh, "bgpNeighborAddr",
+ "%pSU", &p->connection->su);
+
+ asn_asn2json(json_neigh, "remoteAs", p->as, bgp->asnotation);
+
+ if (p->change_local_as)
+ asn_asn2json(json_neigh, "localAs", p->change_local_as,
+ bgp->asnotation);
+ else
+ asn_asn2json(json_neigh, "localAs", p->local_as,
+ bgp->asnotation);
+
+ if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
+ json_object_boolean_true_add(json_neigh,
+ "localAsNoPrepend");
+
+ if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS))
+ json_object_boolean_true_add(json_neigh,
+ "localAsReplaceAs");
+ } else {
+ if ((p->as_type == AS_SPECIFIED) ||
+ (p->as_type == AS_EXTERNAL) ||
+ (p->as_type == AS_INTERNAL)) {
+ vty_out(vty, "remote AS ");
+ vty_out(vty, ASN_FORMAT(bgp->asnotation), &p->as);
+ vty_out(vty, ", ");
+ } else
+ vty_out(vty, "remote AS Unspecified, ");
+ vty_out(vty, "local AS ");
+ vty_out(vty, ASN_FORMAT(bgp->asnotation),
+ p->change_local_as ? &p->change_local_as
+ : &p->local_as);
+ vty_out(vty, "%s%s, ",
+ CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
+ ? " no-prepend"
+ : "",
+ CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
+ ? " replace-as"
+ : "");
+ }
+ /* peer type internal or confed-internal */
+ if ((p->as == p->local_as) || (p->as_type == AS_INTERNAL)) {
+ if (use_json) {
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+ json_object_boolean_true_add(
+ json_neigh, "nbrConfedInternalLink");
+ else
+ json_object_boolean_true_add(json_neigh,
+ "nbrInternalLink");
+ } else {
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+ vty_out(vty, "confed-internal link\n");
+ else
+ vty_out(vty, "internal link\n");
+ }
+ /* peer type external or confed-external */
+ } else if (p->as || (p->as_type == AS_EXTERNAL)) {
+ if (use_json) {
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+ json_object_boolean_true_add(
+ json_neigh, "nbrConfedExternalLink");
+ else
+ json_object_boolean_true_add(json_neigh,
+ "nbrExternalLink");
+ } else {
+ if (bgp_confederation_peers_check(bgp, p->as))
+ vty_out(vty, "confed-external link\n");
+ else
+ vty_out(vty, "external link\n");
+ }
+ } else {
+ if (use_json)
+ json_object_boolean_true_add(json_neigh,
+ "nbrUnspecifiedLink");
+ else
+ vty_out(vty, "unspecified link\n");
+ }
+
+ /* Roles */
+ if (use_json) {
+ json_object_string_add(json_neigh, "localRole",
+ bgp_get_name_by_role(p->local_role));
+ json_object_string_add(json_neigh, "remoteRole",
+ bgp_get_name_by_role(p->remote_role));
+ } else {
+ vty_out(vty, " Local Role: %s\n",
+ bgp_get_name_by_role(p->local_role));
+ vty_out(vty, " Remote Role: %s\n",
+ bgp_get_name_by_role(p->remote_role));
+ }
+
+
+ /* Description. */
+ if (p->desc) {
+ if (use_json)
+ json_object_string_add(json_neigh, "nbrDesc", p->desc);
+ else
+ vty_out(vty, " Description: %s\n", p->desc);
+ }
+
+ if (p->hostname) {
+ if (use_json) {
+ json_object_string_add(json_neigh, "hostname",
+ p->hostname);
+
+ if (p->domainname)
+ json_object_string_add(json_neigh, "domainname",
+ p->domainname);
+ } else {
+ if (p->domainname && (p->domainname[0] != '\0'))
+ vty_out(vty, "Hostname: %s.%s\n", p->hostname,
+ p->domainname);
+ else
+ vty_out(vty, "Hostname: %s\n", p->hostname);
+ }
+ } else {
+ if (use_json)
+ json_object_string_add(json_neigh, "hostname",
+ "Unknown");
+ }
+
+ /* Peer-group */
+ if (p->group) {
+ if (use_json) {
+ json_object_string_add(json_neigh, "peerGroup",
+ p->group->name);
+
+ if (dn_flag[0]) {
+ struct prefix prefix, *range = NULL;
+
+ if (sockunion2hostprefix(&p->connection->su,
+ &prefix))
+ range = peer_group_lookup_dynamic_neighbor_range(
+ p->group, &prefix);
+
+ if (range) {
+ json_object_string_addf(
+ json_neigh,
+ "peerSubnetRangeGroup", "%pFX",
+ range);
+ }
+ }
+ } else {
+ vty_out(vty,
+ " Member of peer-group %s for session parameters\n",
+ p->group->name);
+
+ if (dn_flag[0]) {
+ struct prefix prefix, *range = NULL;
+
+ if (sockunion2hostprefix(&p->connection->su,
+ &prefix))
+ range = peer_group_lookup_dynamic_neighbor_range(
+ p->group, &prefix);
+
+ if (range) {
+ vty_out(vty,
+ " Belongs to the subnet range group: %pFX\n",
+ range);
+ }
+ }
+ }
+ }
+
+ if (use_json) {
+ /* Administrative shutdown. */
+ if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(p->bgp->flags, BGP_FLAG_SHUTDOWN))
+ json_object_boolean_true_add(json_neigh,
+ "adminShutDown");
+
+ /* BGP Version. */
+ json_object_int_add(json_neigh, "bgpVersion", 4);
+ json_object_string_addf(json_neigh, "remoteRouterId", "%pI4",
+ &p->remote_id);
+ json_object_string_addf(json_neigh, "localRouterId", "%pI4",
+ &bgp->router_id);
+
+ /* Confederation */
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
+ && bgp_confederation_peers_check(bgp, p->as))
+ json_object_boolean_true_add(json_neigh,
+ "nbrCommonAdmin");
+
+ /* Status. */
+ json_object_string_add(json_neigh, "bgpState",
+ lookup_msg(bgp_status_msg,
+ p->connection->status, NULL));
+
+ if (peer_established(p->connection)) {
+ time_t uptime;
+
+ uptime = monotime(NULL);
+ uptime -= p->uptime;
+ epoch_tbuf = time(NULL) - uptime;
+
+ json_object_int_add(json_neigh, "bgpTimerUpMsec",
+ uptime * 1000);
+ json_object_string_add(json_neigh, "bgpTimerUpString",
+ peer_uptime(p->uptime, timebuf,
+ BGP_UPTIME_LEN, 0,
+ NULL));
+ json_object_int_add(json_neigh,
+ "bgpTimerUpEstablishedEpoch",
+ epoch_tbuf);
+ } else if (p->connection->status == Active) {
+ if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE))
+ json_object_string_add(json_neigh, "bgpStateIs",
+ "passive");
+ else if (CHECK_FLAG(p->sflags, PEER_STATUS_NSF_WAIT))
+ json_object_string_add(json_neigh, "bgpStateIs",
+ "passiveNSF");
+ }
+
+ /* read timer */
+ time_t uptime;
+ struct tm tm;
+
+ uptime = monotime(NULL);
+ uptime -= p->readtime;
+ gmtime_r(&uptime, &tm);
+
+ json_object_int_add(json_neigh, "bgpTimerLastRead",
+ (tm.tm_sec * 1000) + (tm.tm_min * 60000)
+ + (tm.tm_hour * 3600000));
+
+ uptime = monotime(NULL);
+ uptime -= p->last_write;
+ gmtime_r(&uptime, &tm);
+
+ json_object_int_add(json_neigh, "bgpTimerLastWrite",
+ (tm.tm_sec * 1000) + (tm.tm_min * 60000)
+ + (tm.tm_hour * 3600000));
+
+ uptime = monotime(NULL);
+ uptime -= p->update_time;
+ gmtime_r(&uptime, &tm);
+
+ json_object_int_add(json_neigh, "bgpInUpdateElapsedTimeMsecs",
+ (tm.tm_sec * 1000) + (tm.tm_min * 60000)
+ + (tm.tm_hour * 3600000));
+
+ /* Configured timer values. */
+ json_object_int_add(json_neigh,
+ "bgpTimerConfiguredHoldTimeMsecs",
+ CHECK_FLAG(p->flags, PEER_FLAG_TIMER)
+ ? p->holdtime * 1000
+ : bgp->default_holdtime * 1000);
+ json_object_int_add(json_neigh,
+ "bgpTimerConfiguredKeepAliveIntervalMsecs",
+ CHECK_FLAG(p->flags, PEER_FLAG_TIMER)
+ ? p->keepalive * 1000
+ : bgp->default_keepalive * 1000);
+ json_object_int_add(json_neigh, "bgpTimerHoldTimeMsecs",
+ p->v_holdtime * 1000);
+ json_object_int_add(json_neigh,
+ "bgpTimerKeepAliveIntervalMsecs",
+ p->v_keepalive * 1000);
+ if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER_DELAYOPEN)) {
+ json_object_int_add(json_neigh,
+ "bgpTimerDelayOpenTimeMsecs",
+ p->v_delayopen * 1000);
+ }
+
+ /* Configured and Synced tcp-mss value for peer */
+ sync_tcp_mss = sockopt_tcp_mss_get(p->connection->fd);
+ json_object_int_add(json_neigh, "bgpTcpMssConfigured",
+ p->tcp_mss);
+ json_object_int_add(json_neigh, "bgpTcpMssSynced", sync_tcp_mss);
+
+ /* Extended Optional Parameters Length for BGP OPEN Message */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+ json_object_boolean_true_add(
+ json_neigh, "extendedOptionalParametersLength");
+ else
+ json_object_boolean_false_add(
+ json_neigh, "extendedOptionalParametersLength");
+
+ /* Conditional advertisements */
+ json_object_int_add(
+ json_neigh,
+ "bgpTimerConfiguredConditionalAdvertisementsSec",
+ bgp->condition_check_period);
+ if (event_is_scheduled(bgp->t_condition_check))
+ json_object_int_add(
+ json_neigh,
+ "bgpTimerUntilConditionalAdvertisementsSec",
+ event_timer_remain_second(
+ bgp->t_condition_check));
+ } else {
+ /* Administrative shutdown. */
+ if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(p->bgp->flags, BGP_FLAG_SHUTDOWN))
+ vty_out(vty, " Administratively shut down\n");
+
+ /* BGP Version. */
+ vty_out(vty, " BGP version 4");
+ vty_out(vty, ", remote router ID %pI4", &p->remote_id);
+ vty_out(vty, ", local router ID %pI4\n", &bgp->router_id);
+
+ /* Confederation */
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
+ && bgp_confederation_peers_check(bgp, p->as))
+ vty_out(vty,
+ " Neighbor under common administration\n");
+
+ /* Status. */
+ vty_out(vty, " BGP state = %s",
+ lookup_msg(bgp_status_msg, p->connection->status, NULL));
+
+ if (peer_established(p->connection))
+ vty_out(vty, ", up for %8s",
+ peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN,
+ 0, NULL));
+ else if (p->connection->status == Active) {
+ if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE))
+ vty_out(vty, " (passive)");
+ else if (CHECK_FLAG(p->sflags, PEER_STATUS_NSF_WAIT))
+ vty_out(vty, " (NSF passive)");
+ }
+ vty_out(vty, "\n");
+
+ /* read timer */
+ vty_out(vty, " Last read %s",
+ peer_uptime(p->readtime, timebuf, BGP_UPTIME_LEN, 0,
+ NULL));
+ vty_out(vty, ", Last write %s\n",
+ peer_uptime(p->last_write, timebuf, BGP_UPTIME_LEN, 0,
+ NULL));
+
+ /* Configured timer values. */
+ vty_out(vty,
+ " Hold time is %d seconds, keepalive interval is %d seconds\n",
+ p->v_holdtime, p->v_keepalive);
+ vty_out(vty, " Configured hold time is %d seconds",
+ CHECK_FLAG(p->flags, PEER_FLAG_TIMER)
+ ? p->holdtime
+ : bgp->default_holdtime);
+ vty_out(vty, ", keepalive interval is %d seconds\n",
+ CHECK_FLAG(p->flags, PEER_FLAG_TIMER)
+ ? p->keepalive
+ : bgp->default_keepalive);
+ if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER_DELAYOPEN))
+ vty_out(vty,
+ " Configured DelayOpenTime is %d seconds\n",
+ p->delayopen);
+
+ /* Configured and synced tcp-mss value for peer */
+ sync_tcp_mss = sockopt_tcp_mss_get(p->connection->fd);
+ vty_out(vty, " Configured tcp-mss is %d", p->tcp_mss);
+ vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss);
+
+ /* Extended Optional Parameters Length for BGP OPEN Message */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+ vty_out(vty,
+ " Extended Optional Parameters Length is enabled\n");
+
+ /* Conditional advertisements */
+ vty_out(vty,
+ " Configured conditional advertisements interval is %d seconds\n",
+ bgp->condition_check_period);
+ if (event_is_scheduled(bgp->t_condition_check))
+ vty_out(vty,
+ " Time until conditional advertisements begin is %lu seconds\n",
+ event_timer_remain_second(
+ bgp->t_condition_check));
+ }
+ /* Capability. */
+ if (peer_established(p->connection) &&
+ (p->cap || peer_afc_advertised(p) || peer_afc_received(p))) {
+ if (use_json) {
+ json_object *json_cap = NULL;
+
+ json_cap = json_object_new_object();
+
+ /* AS4 */
+ if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV)) {
+ if (CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV))
+ json_object_string_add(
+ json_cap, "4byteAs",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV))
+ json_object_string_add(json_cap,
+ "4byteAs",
+ "advertised");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV))
+ json_object_string_add(json_cap,
+ "4byteAs",
+ "received");
+ }
+
+ /* Extended Message Support */
+ if (CHECK_FLAG(p->cap, PEER_CAP_EXTENDED_MESSAGE_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_EXTENDED_MESSAGE_RCV))
+ json_object_string_add(json_cap,
+ "extendedMessage",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV))
+ json_object_string_add(json_cap,
+ "extendedMessage",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV))
+ json_object_string_add(json_cap,
+ "extendedMessage",
+ "received");
+
+ /* AddPath */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_ADV)) {
+ json_object *json_add = NULL;
+ const char *print_store;
+
+ json_add = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ json_object *json_sub = NULL;
+ json_sub = json_object_new_object();
+ print_store = get_afi_safi_str(
+ afi, safi, true);
+
+ if (CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV)) {
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV) &&
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV))
+ json_object_boolean_true_add(
+ json_sub,
+ "txAdvertisedAndReceived");
+ else if (
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV))
+ json_object_boolean_true_add(
+ json_sub,
+ "txAdvertised");
+ else if (
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV))
+ json_object_boolean_true_add(
+ json_sub,
+ "txReceived");
+ }
+
+ if (CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV)) {
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV) &&
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV))
+ json_object_boolean_true_add(
+ json_sub,
+ "rxAdvertisedAndReceived");
+ else if (
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV))
+ json_object_boolean_true_add(
+ json_sub,
+ "rxAdvertised");
+ else if (
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV))
+ json_object_boolean_true_add(
+ json_sub,
+ "rxReceived");
+ }
+
+ if (CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV))
+ json_object_object_add(
+ json_add, print_store,
+ json_sub);
+ else
+ json_object_free(json_sub);
+ }
+
+ json_object_object_add(json_cap, "addPath",
+ json_add);
+ }
+
+ /* Dynamic */
+ if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
+ if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV))
+ json_object_string_add(
+ json_cap, "dynamic",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_DYNAMIC_ADV))
+ json_object_string_add(json_cap,
+ "dynamic",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_DYNAMIC_RCV))
+ json_object_string_add(json_cap,
+ "dynamic",
+ "received");
+ }
+
+ /* Role */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ROLE_ADV)) {
+ if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_ROLE_RCV))
+ json_object_string_add(
+ json_cap, "role",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_ADV))
+ json_object_string_add(json_cap, "role",
+ "advertised");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_RCV))
+ json_object_string_add(json_cap, "role",
+ "received");
+ }
+
+ /* Extended nexthop */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV)) {
+ json_object *json_nxt = NULL;
+ const char *print_store;
+
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV))
+ json_object_string_add(
+ json_cap, "extendedNexthop",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV))
+ json_object_string_add(
+ json_cap, "extendedNexthop",
+ "advertised");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV))
+ json_object_string_add(
+ json_cap, "extendedNexthop",
+ "received");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV)) {
+ json_nxt = json_object_new_object();
+
+ for (safi = SAFI_UNICAST;
+ safi < SAFI_MAX; safi++) {
+ if (CHECK_FLAG(
+ p->af_cap[AFI_IP]
+ [safi],
+ PEER_CAP_ENHE_AF_RCV)) {
+ print_store =
+ get_afi_safi_str(
+ AFI_IP,
+ safi,
+ true);
+ json_object_string_add(
+ json_nxt,
+ print_store,
+ "recieved"); /* misspelled for compatibility */
+ }
+ }
+ json_object_object_add(
+ json_cap,
+ "extendedNexthopFamililesByPeer",
+ json_nxt);
+ }
+ }
+
+ /* Long-lived Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV)) {
+ json_object *json_llgr = NULL;
+ const char *afi_safi_str;
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "advertised");
+ else if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV))
+ json_object_string_add(
+ json_cap,
+ "longLivedGracefulRestart",
+ "received");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV)) {
+ json_llgr = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ENHE_AF_RCV)) {
+ afi_safi_str =
+ get_afi_safi_str(
+ afi,
+ safi,
+ true);
+ json_object_string_add(
+ json_llgr,
+ afi_safi_str,
+ "received");
+ }
+ }
+ json_object_object_add(
+ json_cap,
+ "longLivedGracefulRestartByPeer",
+ json_llgr);
+ }
+ }
+
+ /* Route Refresh */
+ if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_REFRESH_RCV)) {
+ if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_REFRESH_RCV))
+ json_object_string_add(json_cap,
+ "routeRefresh",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_REFRESH_ADV))
+ json_object_string_add(json_cap,
+ "routeRefresh",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_REFRESH_RCV))
+ json_object_string_add(json_cap,
+ "routeRefresh",
+ "received");
+ }
+
+ /* Enhanced Route Refresh */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_ADV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_RCV)) {
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_ADV) &&
+ CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_RCV))
+ json_object_string_add(
+ json_cap,
+ "enhancedRouteRefresh",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_ADV))
+ json_object_string_add(
+ json_cap,
+ "enhancedRouteRefresh",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_RCV))
+ json_object_string_add(
+ json_cap,
+ "enhancedRouteRefresh",
+ "received");
+ }
+
+ /* Multiprotocol Extensions */
+ json_object *json_multi = NULL;
+
+ json_multi = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (p->afc_adv[afi][safi] ||
+ p->afc_recv[afi][safi]) {
+ json_object *json_exten = NULL;
+ json_exten = json_object_new_object();
+
+ if (p->afc_adv[afi][safi] &&
+ p->afc_recv[afi][safi])
+ json_object_boolean_true_add(
+ json_exten,
+ "advertisedAndReceived");
+ else if (p->afc_adv[afi][safi])
+ json_object_boolean_true_add(
+ json_exten,
+ "advertised");
+ else if (p->afc_recv[afi][safi])
+ json_object_boolean_true_add(
+ json_exten, "received");
+
+ json_object_object_add(
+ json_multi,
+ get_afi_safi_str(afi, safi,
+ true),
+ json_exten);
+ }
+ }
+ json_object_object_add(json_cap,
+ "multiprotocolExtensions",
+ json_multi);
+
+ /* Hostname capabilities */
+ json_object *json_hname = NULL;
+
+ json_hname = json_object_new_object();
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
+ json_object_string_add(
+ json_hname, "advHostName",
+ bgp->peer_self->hostname
+ ? bgp->peer_self->hostname
+ : "n/a");
+ json_object_string_add(
+ json_hname, "advDomainName",
+ bgp->peer_self->domainname
+ ? bgp->peer_self->domainname
+ : "n/a");
+ }
+
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
+ json_object_string_add(
+ json_hname, "rcvHostName",
+ p->hostname ? p->hostname : "n/a");
+ json_object_string_add(
+ json_hname, "rcvDomainName",
+ p->domainname ? p->domainname : "n/a");
+ }
+
+ json_object_object_add(json_cap, "hostName",
+ json_hname);
+
+ /* Software Version capability */
+ json_object *json_soft_version = NULL;
+
+ json_soft_version = json_object_new_object();
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_ADV))
+ json_object_string_add(
+ json_soft_version,
+ "advertisedSoftwareVersion",
+ cmd_software_version_get());
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_RCV))
+ json_object_string_add(
+ json_soft_version,
+ "receivedSoftwareVersion",
+ p->soft_version ? p->soft_version
+ : "n/a");
+
+ json_object_object_add(json_cap, "softwareVersion",
+ json_soft_version);
+
+ /* Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV) &&
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV))
+ json_object_string_add(
+ json_cap, "gracefulRestart",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_RESTART_ADV))
+ json_object_string_add(
+ json_cap,
+ "gracefulRestartCapability",
+ "advertised");
+ else if (CHECK_FLAG(p->cap,
+ PEER_CAP_RESTART_RCV))
+ json_object_string_add(
+ json_cap,
+ "gracefulRestartCapability",
+ "received");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
+ int restart_af_count = 0;
+ json_object *json_restart = NULL;
+ json_restart = json_object_new_object();
+
+ json_object_int_add(
+ json_cap,
+ "gracefulRestartRemoteTimerMsecs",
+ p->v_gr_restart * 1000);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_RESTART_AF_RCV)) {
+ json_object *json_sub =
+ NULL;
+ json_sub =
+ json_object_new_object();
+
+ if (CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV))
+ json_object_boolean_true_add(
+ json_sub,
+ "preserved");
+ restart_af_count++;
+ json_object_object_add(
+ json_restart,
+ get_afi_safi_str(
+ afi,
+ safi,
+ true),
+ json_sub);
+ }
+ }
+ if (!restart_af_count) {
+ json_object_string_add(
+ json_cap,
+ "addressFamiliesByPeer",
+ "none");
+ json_object_free(json_restart);
+ } else
+ json_object_object_add(
+ json_cap,
+ "addressFamiliesByPeer",
+ json_restart);
+ }
+ }
+ json_object_object_add(
+ json_neigh, "neighborCapabilities", json_cap);
+ } else {
+ vty_out(vty, " Neighbor capabilities:\n");
+
+ /* AS4 */
+ if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV)) {
+ vty_out(vty, " 4 Byte AS:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_AS4_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Extended Message Support */
+ if (CHECK_FLAG(p->cap, PEER_CAP_EXTENDED_MESSAGE_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_EXTENDED_MESSAGE_ADV)) {
+ vty_out(vty, " Extended Message:");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* AddPath */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_ADV)) {
+ vty_out(vty, " AddPath:\n");
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV)) {
+ vty_out(vty, " %s: TX ",
+ get_afi_safi_str(
+ afi, safi,
+ false));
+
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV))
+ vty_out(vty,
+ "advertised");
+
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV))
+ vty_out(vty,
+ "%sreceived",
+ CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV)
+ ? " and "
+ : "");
+
+ vty_out(vty, "\n");
+ }
+
+ if (CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV) ||
+ CHECK_FLAG(
+ p->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV)) {
+ vty_out(vty, " %s: RX ",
+ get_afi_safi_str(
+ afi, safi,
+ false));
+
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV))
+ vty_out(vty,
+ "advertised");
+
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV))
+ vty_out(vty,
+ "%sreceived",
+ CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV)
+ ? " and "
+ : "");
+
+ vty_out(vty, "\n");
+ }
+ }
+ }
+
+ /* Dynamic */
+ if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
+ vty_out(vty, " Dynamic:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_DYNAMIC_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Role */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ROLE_ADV)) {
+ vty_out(vty, " Role:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_ROLE_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_ROLE_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Extended nexthop */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV)) {
+ vty_out(vty, " Extended nexthop:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_ENHE_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV)) {
+ vty_out(vty,
+ " Address families by peer:\n ");
+ for (safi = SAFI_UNICAST;
+ safi < SAFI_MAX; safi++)
+ if (CHECK_FLAG(
+ p->af_cap[AFI_IP]
+ [safi],
+ PEER_CAP_ENHE_AF_RCV))
+ vty_out(vty,
+ " %s\n",
+ get_afi_safi_str(
+ AFI_IP,
+ safi,
+ false));
+ }
+ }
+
+ /* Long-lived Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV)) {
+ vty_out(vty,
+ " Long-lived Graceful Restart:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_LLGR_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_LLGR_RCV)) {
+ vty_out(vty,
+ " Address families by peer:\n");
+ FOREACH_AFI_SAFI (afi, safi)
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_LLGR_AF_RCV))
+ vty_out(vty,
+ " %s\n",
+ get_afi_safi_str(
+ afi,
+ safi,
+ false));
+ }
+ }
+
+ /* Route Refresh */
+ if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_REFRESH_RCV)) {
+ vty_out(vty, " Route refresh:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_REFRESH_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Enhanced Route Refresh */
+ if (CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_ADV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_RCV)) {
+ vty_out(vty, " Enhanced Route Refresh:");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_ENHANCED_RR_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_REFRESH_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Multiprotocol Extensions */
+ FOREACH_AFI_SAFI (afi, safi)
+ if (p->afc_adv[afi][safi] ||
+ p->afc_recv[afi][safi]) {
+ vty_out(vty, " Address Family %s:",
+ get_afi_safi_str(afi, safi,
+ false));
+ if (p->afc_adv[afi][safi])
+ vty_out(vty, " advertised");
+ if (p->afc_recv[afi][safi])
+ vty_out(vty, " %sreceived",
+ p->afc_adv[afi][safi]
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
+ /* Hostname capability */
+ vty_out(vty, " Hostname Capability:");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
+ vty_out(vty,
+ " advertised (name: %s,domain name: %s)",
+ bgp->peer_self->hostname
+ ? bgp->peer_self->hostname
+ : "n/a",
+ bgp->peer_self->domainname
+ ? bgp->peer_self->domainname
+ : "n/a");
+ } else {
+ vty_out(vty, " not advertised");
+ }
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
+ vty_out(vty,
+ " received (name: %s,domain name: %s)",
+ p->hostname ? p->hostname : "n/a",
+ p->domainname ? p->domainname : "n/a");
+ } else {
+ vty_out(vty, " not received");
+ }
+
+ vty_out(vty, "\n");
+
+ /* Software Version capability */
+ vty_out(vty, " Version Capability:");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_ADV)) {
+ vty_out(vty,
+ " advertised software version (%s)",
+ cmd_software_version_get());
+ } else
+ vty_out(vty, " not advertised");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_RCV)) {
+ vty_out(vty, " received software version (%s)",
+ p->soft_version ? p->soft_version
+ : "n/a");
+ } else
+ vty_out(vty, " not received");
+
+ vty_out(vty, "\n");
+
+ /* Graceful Restart */
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
+ vty_out(vty,
+ " Graceful Restart Capability:");
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(p->cap,
+ PEER_CAP_RESTART_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+
+ if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
+ int restart_af_count = 0;
+
+ vty_out(vty,
+ " Remote Restart timer is %d seconds\n",
+ p->v_gr_restart);
+ vty_out(vty,
+ " Address families by peer:\n ");
+
+ FOREACH_AFI_SAFI (afi, safi)
+ if (CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_RESTART_AF_RCV)) {
+ vty_out(vty, "%s%s(%s)",
+ restart_af_count
+ ? ", "
+ : "",
+ get_afi_safi_str(
+ afi,
+ safi,
+ false),
+ CHECK_FLAG(
+ p->af_cap
+ [afi]
+ [safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV)
+ ? "preserved"
+ : "not preserved");
+ restart_af_count++;
+ }
+ if (!restart_af_count)
+ vty_out(vty, "none");
+ vty_out(vty, "\n");
+ }
+ } /* Graceful Restart */
+ }
+ }
+
+ /* graceful restart information */
+ json_object *json_grace = NULL;
+ json_object *json_grace_send = NULL;
+ json_object *json_grace_recv = NULL;
+ int eor_send_af_count = 0;
+ int eor_receive_af_count = 0;
+
+ if (use_json) {
+ json_grace = json_object_new_object();
+ json_grace_send = json_object_new_object();
+ json_grace_recv = json_object_new_object();
+
+ if ((peer_established(p->connection)) &&
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_EOR_SEND)) {
+ json_object_boolean_true_add(
+ json_grace_send,
+ get_afi_safi_str(afi, safi,
+ true));
+ eor_send_af_count++;
+ }
+ }
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED)) {
+ json_object_boolean_true_add(
+ json_grace_recv,
+ get_afi_safi_str(afi, safi,
+ true));
+ eor_receive_af_count++;
+ }
+ }
+ }
+ json_object_object_add(json_grace, "endOfRibSend",
+ json_grace_send);
+ json_object_object_add(json_grace, "endOfRibRecv",
+ json_grace_recv);
+
+
+ if (p->connection->t_gr_restart)
+ json_object_int_add(json_grace,
+ "gracefulRestartTimerMsecs",
+ event_timer_remain_second(
+ p->connection->t_gr_restart) *
+ 1000);
+
+ if (p->connection->t_gr_stale)
+ json_object_int_add(json_grace,
+ "gracefulStalepathTimerMsecs",
+ event_timer_remain_second(
+ p->connection->t_gr_stale) *
+ 1000);
+ /* more gr info in new format */
+ BGP_SHOW_PEER_GR_CAPABILITY(vty, p, json_grace);
+ json_object_object_add(json_neigh, "gracefulRestartInfo",
+ json_grace);
+ } else {
+ vty_out(vty, " Graceful restart information:\n");
+ if ((peer_established(p->connection)) &&
+ CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) {
+ vty_out(vty, " End-of-RIB send: ");
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_EOR_SEND)) {
+ vty_out(vty, "%s%s",
+ eor_send_af_count ? ", " : "",
+ get_afi_safi_str(afi, safi,
+ false));
+ eor_send_af_count++;
+ }
+ }
+ vty_out(vty, "\n");
+ vty_out(vty, " End-of-RIB received: ");
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(p->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED)) {
+ vty_out(vty, "%s%s",
+ eor_receive_af_count ? ", "
+ : "",
+ get_afi_safi_str(afi, safi,
+ false));
+ eor_receive_af_count++;
+ }
+ }
+ vty_out(vty, "\n");
+ }
+
+ if (p->connection->t_gr_restart)
+ vty_out(vty,
+ " The remaining time of restart timer is %ld\n",
+ event_timer_remain_second(
+ p->connection->t_gr_restart));
+
+ if (p->connection->t_gr_stale)
+ vty_out(vty,
+ " The remaining time of stalepath timer is %ld\n",
+ event_timer_remain_second(
+ p->connection->t_gr_stale));
+
+ /* more gr info in new format */
+ BGP_SHOW_PEER_GR_CAPABILITY(vty, p, NULL);
+ }
+
+ if (use_json) {
+ json_object *json_stat = NULL;
+ json_stat = json_object_new_object();
+ /* Packet counts. */
+
+ atomic_size_t outq_count, inq_count;
+ outq_count = atomic_load_explicit(&p->connection->obuf->count,
+ memory_order_relaxed);
+ inq_count = atomic_load_explicit(&p->connection->ibuf->count,
+ memory_order_relaxed);
+
+ json_object_int_add(json_stat, "depthInq",
+ (unsigned long)inq_count);
+ json_object_int_add(json_stat, "depthOutq",
+ (unsigned long)outq_count);
+ json_object_int_add(json_stat, "opensSent",
+ atomic_load_explicit(&p->open_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "opensRecv",
+ atomic_load_explicit(&p->open_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "notificationsSent",
+ atomic_load_explicit(&p->notify_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "notificationsRecv",
+ atomic_load_explicit(&p->notify_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "updatesSent",
+ atomic_load_explicit(&p->update_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "updatesRecv",
+ atomic_load_explicit(&p->update_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "keepalivesSent",
+ atomic_load_explicit(&p->keepalive_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "keepalivesRecv",
+ atomic_load_explicit(&p->keepalive_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "routeRefreshSent",
+ atomic_load_explicit(&p->refresh_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "routeRefreshRecv",
+ atomic_load_explicit(&p->refresh_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "capabilitySent",
+ atomic_load_explicit(&p->dynamic_cap_out,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "capabilityRecv",
+ atomic_load_explicit(&p->dynamic_cap_in,
+ memory_order_relaxed));
+ json_object_int_add(json_stat, "totalSent", PEER_TOTAL_TX(p));
+ json_object_int_add(json_stat, "totalRecv", PEER_TOTAL_RX(p));
+ json_object_object_add(json_neigh, "messageStats", json_stat);
+ } else {
+ atomic_size_t outq_count, inq_count, open_out, open_in,
+ notify_out, notify_in, update_out, update_in,
+ keepalive_out, keepalive_in, refresh_out, refresh_in,
+ dynamic_cap_out, dynamic_cap_in;
+ outq_count = atomic_load_explicit(&p->connection->obuf->count,
+ memory_order_relaxed);
+ inq_count = atomic_load_explicit(&p->connection->ibuf->count,
+ memory_order_relaxed);
+ open_out = atomic_load_explicit(&p->open_out,
+ memory_order_relaxed);
+ open_in =
+ atomic_load_explicit(&p->open_in, memory_order_relaxed);
+ notify_out = atomic_load_explicit(&p->notify_out,
+ memory_order_relaxed);
+ notify_in = atomic_load_explicit(&p->notify_in,
+ memory_order_relaxed);
+ update_out = atomic_load_explicit(&p->update_out,
+ memory_order_relaxed);
+ update_in = atomic_load_explicit(&p->update_in,
+ memory_order_relaxed);
+ keepalive_out = atomic_load_explicit(&p->keepalive_out,
+ memory_order_relaxed);
+ keepalive_in = atomic_load_explicit(&p->keepalive_in,
+ memory_order_relaxed);
+ refresh_out = atomic_load_explicit(&p->refresh_out,
+ memory_order_relaxed);
+ refresh_in = atomic_load_explicit(&p->refresh_in,
+ memory_order_relaxed);
+ dynamic_cap_out = atomic_load_explicit(&p->dynamic_cap_out,
+ memory_order_relaxed);
+ dynamic_cap_in = atomic_load_explicit(&p->dynamic_cap_in,
+ memory_order_relaxed);
+
+ /* Packet counts. */
+ vty_out(vty, " Message statistics:\n");
+ vty_out(vty, " Inq depth is %zu\n", inq_count);
+ vty_out(vty, " Outq depth is %zu\n", outq_count);
+ vty_out(vty, " Sent Rcvd\n");
+ vty_out(vty, " Opens: %10zu %10zu\n", open_out,
+ open_in);
+ vty_out(vty, " Notifications: %10zu %10zu\n", notify_out,
+ notify_in);
+ vty_out(vty, " Updates: %10zu %10zu\n", update_out,
+ update_in);
+ vty_out(vty, " Keepalives: %10zu %10zu\n", keepalive_out,
+ keepalive_in);
+ vty_out(vty, " Route Refresh: %10zu %10zu\n", refresh_out,
+ refresh_in);
+ vty_out(vty, " Capability: %10zu %10zu\n",
+ dynamic_cap_out, dynamic_cap_in);
+ vty_out(vty, " Total: %10u %10u\n",
+ (uint32_t)PEER_TOTAL_TX(p), (uint32_t)PEER_TOTAL_RX(p));
+ }
+
+ if (use_json) {
+ /* advertisement-interval */
+ json_object_int_add(json_neigh,
+ "minBtwnAdvertisementRunsTimerMsecs",
+ p->v_routeadv * 1000);
+
+ /* Update-source. */
+ if (p->update_if || p->update_source) {
+ if (p->update_if)
+ json_object_string_add(json_neigh,
+ "updateSource",
+ p->update_if);
+ else if (p->update_source)
+ json_object_string_addf(json_neigh,
+ "updateSource", "%pSU",
+ p->update_source);
+ }
+ } else {
+ /* advertisement-interval */
+ vty_out(vty,
+ " Minimum time between advertisement runs is %d seconds\n",
+ p->v_routeadv);
+
+ /* Update-source. */
+ if (p->update_if || p->update_source) {
+ vty_out(vty, " Update source is ");
+ if (p->update_if)
+ vty_out(vty, "%s", p->update_if);
+ else if (p->update_source)
+ vty_out(vty, "%pSU", p->update_source);
+ vty_out(vty, "\n");
+ }
+
+ vty_out(vty, "\n");
+ }
+
+ /* Address Family Information */
+ json_object *json_hold = NULL;
+
+ if (use_json)
+ json_hold = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi)
+ if (p->afc[afi][safi])
+ bgp_show_peer_afi(vty, p, afi, safi, use_json,
+ json_hold);
+
+ if (use_json) {
+ json_object_object_add(json_neigh, "addressFamilyInfo",
+ json_hold);
+ json_object_int_add(json_neigh, "connectionsEstablished",
+ p->established);
+ json_object_int_add(json_neigh, "connectionsDropped",
+ p->dropped);
+ } else
+ vty_out(vty, " Connections established %d; dropped %d\n",
+ p->established, p->dropped);
+
+ if (!p->last_reset) {
+ if (use_json)
+ json_object_string_add(json_neigh, "lastReset",
+ "never");
+ else
+ vty_out(vty, " Last reset never\n");
+ } else {
+ if (use_json) {
+ time_t uptime;
+ struct tm tm;
+
+ uptime = monotime(NULL);
+ uptime -= p->resettime;
+ gmtime_r(&uptime, &tm);
+
+ json_object_int_add(json_neigh, "lastResetTimerMsecs",
+ (tm.tm_sec * 1000)
+ + (tm.tm_min * 60000)
+ + (tm.tm_hour * 3600000));
+ bgp_show_peer_reset(NULL, p, json_neigh, true);
+ } else {
+ vty_out(vty, " Last reset %s, ",
+ peer_uptime(p->resettime, timebuf,
+ BGP_UPTIME_LEN, 0, NULL));
+
+ bgp_show_peer_reset(vty, p, NULL, false);
+ if (p->last_reset_cause) {
+ msg = p->last_reset_cause->data;
+ vty_out(vty,
+ " Message received that caused BGP to send a NOTIFICATION:\n ");
+ for (i = 1; i <= p->last_reset_cause->size;
+ i++) {
+ vty_out(vty, "%02X", *msg++);
+
+ if (i != p->last_reset_cause->size) {
+ if (i % 16 == 0) {
+ vty_out(vty, "\n ");
+ } else if (i % 4 == 0) {
+ vty_out(vty, " ");
+ }
+ }
+ }
+ vty_out(vty, "\n");
+ }
+ }
+ }
+
+ if (CHECK_FLAG(p->sflags, PEER_STATUS_PREFIX_OVERFLOW)) {
+ if (use_json)
+ json_object_boolean_true_add(json_neigh,
+ "prefixesConfigExceedMax");
+ else
+ vty_out(vty,
+ " Peer had exceeded the max. no. of prefixes configured.\n");
+
+ if (p->connection->t_pmax_restart) {
+ if (use_json) {
+ json_object_boolean_true_add(
+ json_neigh, "reducePrefixNumFrom");
+ json_object_int_add(json_neigh,
+ "restartInTimerMsec",
+ event_timer_remain_second(
+ p->connection
+ ->t_pmax_restart) *
+ 1000);
+ } else
+ vty_out(vty,
+ " Reduce the no. of prefix from %s, will restart in %ld seconds\n",
+ p->host,
+ event_timer_remain_second(
+ p->connection->t_pmax_restart));
+ } else {
+ if (use_json)
+ json_object_boolean_true_add(
+ json_neigh,
+ "reducePrefixNumAndClearIpBgp");
+ else
+ vty_out(vty,
+ " Reduce the no. of prefix and clear ip bgp %s to restore peering\n",
+ p->host);
+ }
+ }
+
+ /* EBGP Multihop and GTSM */
+ if (p->sort != BGP_PEER_IBGP) {
+ if (use_json) {
+ if (p->gtsm_hops > BGP_GTSM_HOPS_DISABLED)
+ json_object_int_add(json_neigh,
+ "externalBgpNbrMaxHopsAway",
+ p->gtsm_hops);
+ else
+ json_object_int_add(json_neigh,
+ "externalBgpNbrMaxHopsAway",
+ p->ttl);
+ } else {
+ if (p->gtsm_hops > BGP_GTSM_HOPS_DISABLED)
+ vty_out(vty,
+ " External BGP neighbor may be up to %d hops away.\n",
+ p->gtsm_hops);
+ else
+ vty_out(vty,
+ " External BGP neighbor may be up to %d hops away.\n",
+ p->ttl);
+ }
+ } else {
+ if (use_json) {
+ if (p->gtsm_hops > BGP_GTSM_HOPS_DISABLED)
+ json_object_int_add(json_neigh,
+ "internalBgpNbrMaxHopsAway",
+ p->gtsm_hops);
+ else
+ json_object_int_add(json_neigh,
+ "internalBgpNbrMaxHopsAway",
+ p->ttl);
+ } else {
+ if (p->gtsm_hops > BGP_GTSM_HOPS_DISABLED)
+ vty_out(vty,
+ " Internal BGP neighbor may be up to %d hops away.\n",
+ p->gtsm_hops);
+ else
+ vty_out(vty,
+ " Internal BGP neighbor may be up to %d hops away.\n",
+ p->ttl);
+ }
+ }
+
+ /* Local address. */
+ if (p->su_local) {
+ if (use_json) {
+ json_object_string_addf(json_neigh, "hostLocal", "%pSU",
+ p->su_local);
+ json_object_int_add(json_neigh, "portLocal",
+ ntohs(p->su_local->sin.sin_port));
+ } else
+ vty_out(vty, "Local host: %pSU, Local port: %d\n",
+ p->su_local, ntohs(p->su_local->sin.sin_port));
+ } else {
+ if (use_json) {
+ json_object_string_add(json_neigh, "hostLocal",
+ "Unknown");
+ json_object_int_add(json_neigh, "portLocal", -1);
+ }
+ }
+
+ /* Remote address. */
+ if (p->su_remote) {
+ if (use_json) {
+ json_object_string_addf(json_neigh, "hostForeign",
+ "%pSU", p->su_remote);
+ json_object_int_add(json_neigh, "portForeign",
+ ntohs(p->su_remote->sin.sin_port));
+ } else
+ vty_out(vty, "Foreign host: %pSU, Foreign port: %d\n",
+ p->su_remote,
+ ntohs(p->su_remote->sin.sin_port));
+ } else {
+ if (use_json) {
+ json_object_string_add(json_neigh, "hostForeign",
+ "Unknown");
+ json_object_int_add(json_neigh, "portForeign", -1);
+ }
+ }
+
+ /* Nexthop display. */
+ if (p->su_local) {
+ if (use_json) {
+ json_object_string_addf(json_neigh, "nexthop", "%pI4",
+ &p->nexthop.v4);
+ json_object_string_addf(json_neigh, "nexthopGlobal",
+ "%pI6", &p->nexthop.v6_global);
+ json_object_string_addf(json_neigh, "nexthopLocal",
+ "%pI6", &p->nexthop.v6_local);
+ if (p->shared_network)
+ json_object_string_add(json_neigh,
+ "bgpConnection",
+ "sharedNetwork");
+ else
+ json_object_string_add(json_neigh,
+ "bgpConnection",
+ "nonSharedNetwork");
+ } else {
+ vty_out(vty, "Nexthop: %pI4\n", &p->nexthop.v4);
+ vty_out(vty, "Nexthop global: %pI6\n",
+ &p->nexthop.v6_global);
+ vty_out(vty, "Nexthop local: %pI6\n",
+ &p->nexthop.v6_local);
+ vty_out(vty, "BGP connection: %s\n",
+ p->shared_network ? "shared network"
+ : "non shared network");
+ }
+ } else {
+ if (use_json) {
+ json_object_string_add(json_neigh, "nexthop",
+ "Unknown");
+ json_object_string_add(json_neigh, "nexthopGlobal",
+ "Unknown");
+ json_object_string_add(json_neigh, "nexthopLocal",
+ "Unknown");
+ json_object_string_add(json_neigh, "bgpConnection",
+ "Unknown");
+ }
+ }
+
+ /* Timer information. */
+ if (use_json) {
+ json_object_int_add(json_neigh, "connectRetryTimer",
+ p->v_connect);
+ if (peer_established(p->connection)) {
+ json_object_int_add(json_neigh, "estimatedRttInMsecs",
+ p->rtt);
+ if (CHECK_FLAG(p->flags, PEER_FLAG_RTT_SHUTDOWN)) {
+ json_object_int_add(json_neigh,
+ "shutdownRttInMsecs",
+ p->rtt_expected);
+ json_object_int_add(json_neigh,
+ "shutdownRttAfterCount",
+ p->rtt_keepalive_rcv);
+ }
+ }
+ if (p->connection->t_start)
+ json_object_int_add(json_neigh,
+ "nextStartTimerDueInMsecs",
+ event_timer_remain_second(
+ p->connection->t_start) *
+ 1000);
+ if (p->connection->t_connect)
+ json_object_int_add(json_neigh,
+ "nextConnectTimerDueInMsecs",
+ event_timer_remain_second(
+ p->connection->t_connect) *
+ 1000);
+ if (p->connection->t_routeadv) {
+ json_object_int_add(json_neigh, "mraiInterval",
+ p->v_routeadv);
+ json_object_int_add(json_neigh, "mraiTimerExpireInMsecs",
+ event_timer_remain_second(
+ p->connection->t_routeadv) *
+ 1000);
+ }
+ if (p->password)
+ json_object_int_add(json_neigh, "authenticationEnabled",
+ 1);
+
+ if (p->connection->t_read)
+ json_object_string_add(json_neigh, "readThread", "on");
+ else
+ json_object_string_add(json_neigh, "readThread", "off");
+
+ if (CHECK_FLAG(p->connection->thread_flags,
+ PEER_THREAD_WRITES_ON))
+ json_object_string_add(json_neigh, "writeThread", "on");
+ else
+ json_object_string_add(json_neigh, "writeThread",
+ "off");
+ } else {
+ vty_out(vty, "BGP Connect Retry Timer in Seconds: %d\n",
+ p->v_connect);
+ if (peer_established(p->connection)) {
+ vty_out(vty, "Estimated round trip time: %d ms\n",
+ p->rtt);
+ if (CHECK_FLAG(p->flags, PEER_FLAG_RTT_SHUTDOWN))
+ vty_out(vty,
+ "Shutdown when RTT > %dms, count > %u\n",
+ p->rtt_expected, p->rtt_keepalive_rcv);
+ }
+ if (p->connection->t_start)
+ vty_out(vty, "Next start timer due in %ld seconds\n",
+ event_timer_remain_second(
+ p->connection->t_start));
+ if (p->connection->t_connect)
+ vty_out(vty, "Next connect timer due in %ld seconds\n",
+ event_timer_remain_second(
+ p->connection->t_connect));
+ if (p->connection->t_routeadv)
+ vty_out(vty,
+ "MRAI (interval %u) timer expires in %ld seconds\n",
+ p->v_routeadv,
+ event_timer_remain_second(
+ p->connection->t_routeadv));
+ if (p->password)
+ vty_out(vty, "Peer Authentication Enabled\n");
+
+ vty_out(vty, "Read thread: %s Write thread: %s FD used: %d\n",
+ p->connection->t_read ? "on" : "off",
+ CHECK_FLAG(p->connection->thread_flags,
+ PEER_THREAD_WRITES_ON)
+ ? "on"
+ : "off",
+ p->connection->fd);
+ }
+
+ if (p->notify.code == BGP_NOTIFY_OPEN_ERR
+ && p->notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL)
+ bgp_capability_vty_out(vty, p, use_json, json_neigh);
+
+ if (!use_json)
+ vty_out(vty, "\n");
+
+ /* BFD information. */
+ if (p->bfd_config)
+ bgp_bfd_show_info(vty, p, json_neigh);
+
+ if (use_json) {
+ if (p->conf_if) /* Configured interface name. */
+ json_object_object_add(json, p->conf_if, json_neigh);
+ else /* Configured IP address. */
+ json_object_object_add(json, p->host, json_neigh);
+ }
+}
+
+static int bgp_show_neighbor_graceful_restart(struct vty *vty, struct bgp *bgp,
+ enum show_type type,
+ union sockunion *su,
+ const char *conf_if, afi_t afi,
+ json_object *json)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer;
+ bool found = false;
+ safi_t safi = SAFI_UNICAST;
+ json_object *json_neighbor = NULL;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ if ((peer->afc[afi][safi]) == 0)
+ continue;
+
+ if (json)
+ json_neighbor = json_object_new_object();
+
+ if (type == show_all) {
+ bgp_show_peer_gr_status(vty, peer, json_neighbor);
+
+ if (json)
+ json_object_object_add(json, peer->host,
+ json_neighbor);
+
+ } else if (type == show_peer) {
+ if (conf_if) {
+ if ((peer->conf_if
+ && !strcmp(peer->conf_if, conf_if))
+ || (peer->hostname
+ && !strcmp(peer->hostname, conf_if))) {
+ found = true;
+ bgp_show_peer_gr_status(vty, peer,
+ json_neighbor);
+ }
+ } else {
+ if (sockunion_same(&peer->connection->su, su)) {
+ found = true;
+ bgp_show_peer_gr_status(vty, peer,
+ json_neighbor);
+ }
+ }
+ if (json) {
+ if (found)
+ json_object_object_add(json, peer->host,
+ json_neighbor);
+ else
+ json_object_free(json_neighbor);
+ }
+ }
+
+ if (found)
+ break;
+ }
+
+ if (type == show_peer && !found) {
+ if (json)
+ json_object_boolean_true_add(json, "bgpNoSuchNeighbor");
+ else
+ vty_out(vty, "%% No such neighbor\n");
+ }
+
+ if (!json)
+ vty_out(vty, "\n");
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
+ enum show_type type, union sockunion *su,
+ const char *conf_if, bool use_json,
+ json_object *json)
+{
+ struct listnode *node, *nnode;
+ struct peer *peer;
+ int find = 0;
+ bool nbr_output = false;
+ afi_t afi = AFI_MAX;
+ safi_t safi = SAFI_MAX;
+
+ if (type == show_ipv4_peer || type == show_ipv4_all) {
+ afi = AFI_IP;
+ } else if (type == show_ipv6_peer || type == show_ipv6_all) {
+ afi = AFI_IP6;
+ }
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ switch (type) {
+ case show_all:
+ bgp_show_peer(vty, peer, use_json, json);
+ nbr_output = true;
+ break;
+ case show_peer:
+ if (conf_if) {
+ if ((peer->conf_if
+ && !strcmp(peer->conf_if, conf_if))
+ || (peer->hostname
+ && !strcmp(peer->hostname, conf_if))) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ }
+ } else {
+ if (sockunion_same(&peer->connection->su, su)) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ }
+ }
+ break;
+ case show_ipv4_peer:
+ case show_ipv6_peer:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ if (conf_if) {
+ if ((peer->conf_if
+ && !strcmp(peer->conf_if, conf_if))
+ || (peer->hostname
+ && !strcmp(peer->hostname, conf_if))) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ } else {
+ if (sockunion_same(&peer->connection
+ ->su,
+ su)) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case show_ipv4_all:
+ case show_ipv6_all:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ bgp_show_peer(vty, peer, use_json, json);
+ nbr_output = true;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if ((type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) && !find) {
+ if (use_json)
+ json_object_boolean_true_add(json, "bgpNoSuchNeighbor");
+ else
+ vty_out(vty, "%% No such neighbor in this view/vrf\n");
+ }
+
+ if (type != show_peer && type != show_ipv4_peer &&
+ type != show_ipv6_peer && !nbr_output && !use_json)
+ vty_out(vty, "%% No BGP neighbors found\n");
+
+ if (use_json) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ } else {
+ vty_out(vty, "\n");
+ }
+
+ return CMD_SUCCESS;
+}
+
+static void bgp_show_neighbor_graceful_restart_vty(struct vty *vty,
+ enum show_type type,
+ const char *ip_str,
+ afi_t afi, json_object *json)
+{
+
+ int ret;
+ struct bgp *bgp;
+ union sockunion su;
+
+ bgp = bgp_get_default();
+
+ if (!bgp)
+ return;
+
+ if (!json)
+ bgp_show_global_graceful_restart_mode_vty(vty, bgp);
+
+ if (ip_str) {
+ ret = str2sockunion(ip_str, &su);
+ if (ret < 0)
+ bgp_show_neighbor_graceful_restart(vty, bgp, type, NULL,
+ ip_str, afi, json);
+ else
+ bgp_show_neighbor_graceful_restart(vty, bgp, type, &su,
+ NULL, afi, json);
+ } else
+ bgp_show_neighbor_graceful_restart(vty, bgp, type, NULL, NULL,
+ afi, json);
+}
+
+static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
+ enum show_type type,
+ const char *ip_str,
+ bool use_json)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ union sockunion su;
+ json_object *json = NULL;
+ int ret, is_first = 1;
+ bool nbr_output = false;
+
+ if (use_json)
+ vty_out(vty, "{\n");
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ nbr_output = true;
+ if (use_json) {
+ if (!(json = json_object_new_object())) {
+ flog_err(
+ EC_BGP_JSON_MEM_ERROR,
+ "Unable to allocate memory for JSON object");
+ vty_out(vty,
+ "{\"error\": {\"message:\": \"Unable to allocate memory for JSON object\"}}}\n");
+ return;
+ }
+
+ json_object_int_add(json, "vrfId",
+ (bgp->vrf_id == VRF_UNKNOWN)
+ ? -1
+ : (int64_t)bgp->vrf_id);
+ json_object_string_add(
+ json, "vrfName",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+
+ if (!is_first)
+ vty_out(vty, ",\n");
+ else
+ is_first = 0;
+
+ vty_out(vty, "\"%s\":",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+ } else {
+ vty_out(vty, "\nInstance %s:\n",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+ }
+
+ if (type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) {
+ ret = str2sockunion(ip_str, &su);
+ if (ret < 0)
+ bgp_show_neighbor(vty, bgp, type, NULL, ip_str,
+ use_json, json);
+ else
+ bgp_show_neighbor(vty, bgp, type, &su, NULL,
+ use_json, json);
+ } else {
+ bgp_show_neighbor(vty, bgp, type, NULL, NULL,
+ use_json, json);
+ }
+ json_object_free(json);
+ json = NULL;
+ }
+
+ if (use_json)
+ vty_out(vty, "}\n");
+ else if (!nbr_output)
+ vty_out(vty, "%% BGP instance not found\n");
+}
+
+static int bgp_show_neighbor_vty(struct vty *vty, const char *name,
+ enum show_type type, const char *ip_str,
+ bool use_json)
+{
+ int ret;
+ struct bgp *bgp;
+ union sockunion su;
+ json_object *json = NULL;
+
+ if (name) {
+ if (strmatch(name, "all")) {
+ bgp_show_all_instances_neighbors_vty(vty, type, ip_str,
+ use_json);
+ return CMD_SUCCESS;
+ } else {
+ bgp = bgp_lookup_by_name(name);
+ if (!bgp) {
+ if (use_json) {
+ json = json_object_new_object();
+ vty_json(vty, json);
+ } else
+ vty_out(vty,
+ "%% BGP instance not found\n");
+
+ return CMD_WARNING;
+ }
+ }
+ } else {
+ bgp = bgp_get_default();
+ }
+
+ if (bgp) {
+ json = json_object_new_object();
+ if (ip_str) {
+ ret = str2sockunion(ip_str, &su);
+ if (ret < 0)
+ bgp_show_neighbor(vty, bgp, type, NULL, ip_str,
+ use_json, json);
+ else
+ bgp_show_neighbor(vty, bgp, type, &su, NULL,
+ use_json, json);
+ } else {
+ bgp_show_neighbor(vty, bgp, type, NULL, NULL, use_json,
+ json);
+ }
+ json_object_free(json);
+ } else {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% BGP instance not found\n");
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+
+/* "show [ip] bgp neighbors graceful-restart" commands. */
+DEFUN (show_ip_bgp_neighbors_graceful_restart,
+ show_ip_bgp_neighbors_graceful_restart_cmd,
+ "show bgp [<ipv4|ipv6>] neighbors [<A.B.C.D|X:X::X:X|WORD>] graceful-restart [json]",
+ SHOW_STR
+ BGP_STR
+ IP_STR
+ IPV6_STR
+ NEIGHBOR_STR
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on BGP configured interface\n"
+ GR_SHOW
+ JSON_STR)
+{
+ char *sh_arg = NULL;
+ enum show_type sh_type;
+ int idx = 0;
+ afi_t afi = AFI_MAX;
+ bool uj = use_json(argc, argv);
+
+ if (!argv_find_and_parse_afi(argv, argc, &idx, &afi))
+ afi = AFI_MAX;
+
+ idx++;
+
+ if (argv_find(argv, argc, "A.B.C.D", &idx)
+ || argv_find(argv, argc, "X:X::X:X", &idx)
+ || argv_find(argv, argc, "WORD", &idx)) {
+ sh_type = show_peer;
+ sh_arg = argv[idx]->arg;
+ } else
+ sh_type = show_all;
+
+ if (!argv_find(argv, argc, "graceful-restart", &idx))
+ return CMD_SUCCESS;
+
+
+ return bgp_show_neighbor_graceful_restart_afi_all(vty, sh_type, sh_arg,
+ afi, uj);
+}
+
+/* "show [ip] bgp neighbors" commands. */
+DEFUN (show_ip_bgp_neighbors,
+ show_ip_bgp_neighbors_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6>] neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AF_STR
+ BGP_AF_STR
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on BGP configured interface\n"
+ JSON_STR)
+{
+ char *vrf = NULL;
+ char *sh_arg = NULL;
+ enum show_type sh_type;
+ afi_t afi = AFI_MAX;
+
+ bool uj = use_json(argc, argv);
+
+ int idx = 0;
+
+ /* [<vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ } else if (argv_find(argv, argc, "view", &idx))
+ /* [<view> VIEWVRFNAME] */
+ vrf = argv[idx + 1]->arg;
+
+ idx++;
+
+ if (argv_find(argv, argc, "ipv4", &idx)) {
+ sh_type = show_ipv4_all;
+ afi = AFI_IP;
+ } else if (argv_find(argv, argc, "ipv6", &idx)) {
+ sh_type = show_ipv6_all;
+ afi = AFI_IP6;
+ } else {
+ sh_type = show_all;
+ }
+
+ if (argv_find(argv, argc, "A.B.C.D", &idx)
+ || argv_find(argv, argc, "X:X::X:X", &idx)
+ || argv_find(argv, argc, "WORD", &idx)) {
+ sh_type = show_peer;
+ sh_arg = argv[idx]->arg;
+ }
+
+ if (sh_type == show_peer && afi == AFI_IP) {
+ sh_type = show_ipv4_peer;
+ } else if (sh_type == show_peer && afi == AFI_IP6) {
+ sh_type = show_ipv6_peer;
+ }
+
+ return bgp_show_neighbor_vty(vty, vrf, sh_type, sh_arg, uj);
+}
+
+/* Show BGP's AS paths internal data. There are both `show [ip] bgp
+ paths' and `show ip mbgp paths'. Those functions results are the
+ same.*/
+DEFUN (show_ip_bgp_paths,
+ show_ip_bgp_paths_cmd,
+ "show [ip] bgp ["BGP_SAFI_CMD_STR"] paths",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_SAFI_HELP_STR
+ "Path information\n")
+{
+ vty_out(vty, "Address Refcnt Path\n");
+ aspath_print_all_vty(vty);
+ return CMD_SUCCESS;
+}
+
+#include "hash.h"
+
+static void community_show_all_iterator(struct hash_bucket *bucket,
+ struct vty *vty)
+{
+ struct community *com;
+
+ com = (struct community *)bucket->data;
+ vty_out(vty, "[%p] (%ld) %s\n", (void *)com, com->refcnt,
+ community_str(com, false, false));
+}
+
+/* Show BGP's community internal data. */
+DEFUN (show_ip_bgp_community_info,
+ show_ip_bgp_community_info_cmd,
+ "show [ip] bgp community-info",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "List all bgp community information\n")
+{
+ vty_out(vty, "Address Refcnt Community\n");
+
+ hash_iterate(community_hash(),
+ (void (*)(struct hash_bucket *,
+ void *))community_show_all_iterator,
+ vty);
+
+ return CMD_SUCCESS;
+}
+
+static void lcommunity_show_all_iterator(struct hash_bucket *bucket,
+ struct vty *vty)
+{
+ struct lcommunity *lcom;
+
+ lcom = (struct lcommunity *)bucket->data;
+ vty_out(vty, "[%p] (%ld) %s\n", (void *)lcom, lcom->refcnt,
+ lcommunity_str(lcom, false, false));
+}
+
+/* Show BGP's community internal data. */
+DEFUN (show_ip_bgp_lcommunity_info,
+ show_ip_bgp_lcommunity_info_cmd,
+ "show ip bgp large-community-info",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "List all bgp large-community information\n")
+{
+ vty_out(vty, "Address Refcnt Large-community\n");
+
+ hash_iterate(lcommunity_hash(),
+ (void (*)(struct hash_bucket *,
+ void *))lcommunity_show_all_iterator,
+ vty);
+
+ return CMD_SUCCESS;
+}
+/* Graceful Restart */
+
+static void bgp_show_global_graceful_restart_mode_vty(struct vty *vty,
+ struct bgp *bgp)
+{
+
+
+ vty_out(vty, "\n%s", SHOW_GR_HEADER);
+
+ enum global_mode bgp_global_gr_mode = bgp_global_gr_mode_get(bgp);
+
+ switch (bgp_global_gr_mode) {
+
+ case GLOBAL_HELPER:
+ vty_out(vty, "Global BGP GR Mode : Helper\n");
+ break;
+
+ case GLOBAL_GR:
+ vty_out(vty, "Global BGP GR Mode : Restart\n");
+ break;
+
+ case GLOBAL_DISABLE:
+ vty_out(vty, "Global BGP GR Mode : Disable\n");
+ break;
+
+ case GLOBAL_INVALID:
+ vty_out(vty,
+ "Global BGP GR Mode Invalid\n");
+ break;
+ }
+ vty_out(vty, "\n");
+}
+
+static int bgp_show_neighbor_graceful_restart_afi_all(struct vty *vty,
+ enum show_type type,
+ const char *ip_str,
+ afi_t afi, bool use_json)
+{
+ json_object *json = NULL;
+
+ if (use_json)
+ json = json_object_new_object();
+
+ if ((afi == AFI_MAX) && (ip_str == NULL)) {
+ afi = AFI_IP;
+
+ while ((afi != AFI_L2VPN) && (afi < AFI_MAX)) {
+
+ bgp_show_neighbor_graceful_restart_vty(
+ vty, type, ip_str, afi, json);
+ afi++;
+ }
+ } else if (afi != AFI_MAX) {
+ bgp_show_neighbor_graceful_restart_vty(vty, type, ip_str, afi,
+ json);
+ } else {
+ if (json)
+ json_object_free(json);
+ return CMD_ERR_INCOMPLETE;
+ }
+
+ if (json)
+ vty_json(vty, json);
+
+ return CMD_SUCCESS;
+}
+/* Graceful Restart */
+
+DEFUN (show_ip_bgp_attr_info,
+ show_ip_bgp_attr_info_cmd,
+ "show [ip] bgp attribute-info",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "List all bgp attribute information\n")
+{
+ attr_show_all(vty);
+ return CMD_SUCCESS;
+}
+
+static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
+ afi_t afi, safi_t safi,
+ bool use_json, json_object *json)
+{
+ struct bgp *bgp;
+ struct listnode *node;
+ char *vname;
+ char *ecom_str;
+ enum vpn_policy_direction dir;
+
+ if (json) {
+ json_object *json_import_vrfs = NULL;
+ json_object *json_export_vrfs = NULL;
+
+ bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
+ if (!bgp) {
+ vty_json(vty, json);
+
+ return CMD_WARNING;
+ }
+
+ /* Provide context for the block */
+ json_object_string_add(json, "vrf", name ? name : "default");
+ json_object_string_add(json, "afiSafi",
+ get_afi_safi_str(afi, safi, true));
+
+ if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ json_object_string_add(json, "importFromVrfs", "none");
+ json_object_string_add(json, "importRts", "none");
+ } else {
+ json_import_vrfs = json_object_new_array();
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].import_vrf,
+ node, vname))
+ json_object_array_add(json_import_vrfs,
+ json_object_new_string(vname));
+
+ json_object_object_add(json, "importFromVrfs",
+ json_import_vrfs);
+ dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ if (bgp->vpn_policy[afi].rtlist[dir]) {
+ ecom_str = ecommunity_ecom2str(
+ bgp->vpn_policy[afi].rtlist[dir],
+ ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+ json_object_string_add(json, "importRts",
+ ecom_str);
+ XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+ } else
+ json_object_string_add(json, "importRts",
+ "none");
+ }
+
+ if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
+ json_object_string_add(json, "exportToVrfs", "none");
+ json_object_string_add(json, "routeDistinguisher",
+ "none");
+ json_object_string_add(json, "exportRts", "none");
+ } else {
+ json_export_vrfs = json_object_new_array();
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].export_vrf,
+ node, vname))
+ json_object_array_add(json_export_vrfs,
+ json_object_new_string(vname));
+ json_object_object_add(json, "exportToVrfs",
+ json_export_vrfs);
+ json_object_string_addf(
+ json, "routeDistinguisher", "%s",
+ bgp->vpn_policy[afi].tovpn_rd_pretty);
+ dir = BGP_VPN_POLICY_DIR_TOVPN;
+ if (bgp->vpn_policy[afi].rtlist[dir]) {
+ ecom_str = ecommunity_ecom2str(
+ bgp->vpn_policy[afi].rtlist[dir],
+ ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+ json_object_string_add(json, "exportRts",
+ ecom_str);
+ XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+ } else
+ json_object_string_add(json, "exportRts",
+ "none");
+ }
+
+ if (use_json) {
+ vty_json(vty, json);
+ }
+ } else {
+ bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
+ if (!bgp) {
+ vty_out(vty, "%% No such BGP instance exist\n");
+ return CMD_WARNING;
+ }
+
+ if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT))
+ vty_out(vty,
+ "This VRF is not importing %s routes from any other VRF\n",
+ get_afi_safi_str(afi, safi, false));
+ else {
+ vty_out(vty,
+ "This VRF is importing %s routes from the following VRFs:\n",
+ get_afi_safi_str(afi, safi, false));
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].import_vrf,
+ node, vname))
+ vty_out(vty, " %s\n", vname);
+
+ dir = BGP_VPN_POLICY_DIR_FROMVPN;
+ ecom_str = NULL;
+ if (bgp->vpn_policy[afi].rtlist[dir]) {
+ ecom_str = ecommunity_ecom2str(
+ bgp->vpn_policy[afi].rtlist[dir],
+ ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+ vty_out(vty, "Import RT(s): %s\n", ecom_str);
+
+ XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+ } else
+ vty_out(vty, "Import RT(s):\n");
+ }
+
+ if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT))
+ vty_out(vty,
+ "This VRF is not exporting %s routes to any other VRF\n",
+ get_afi_safi_str(afi, safi, false));
+ else {
+ vty_out(vty,
+ "This VRF is exporting %s routes to the following VRFs:\n",
+ get_afi_safi_str(afi, safi, false));
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].export_vrf,
+ node, vname))
+ vty_out(vty, " %s\n", vname);
+
+ vty_out(vty, "RD: ");
+ vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
+ &bgp->vpn_policy[afi].tovpn_rd);
+ vty_out(vty, "\n");
+
+ dir = BGP_VPN_POLICY_DIR_TOVPN;
+ if (bgp->vpn_policy[afi].rtlist[dir]) {
+ ecom_str = ecommunity_ecom2str(
+ bgp->vpn_policy[afi].rtlist[dir],
+ ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+ vty_out(vty, "Export RT: %s\n", ecom_str);
+ XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+ } else
+ vty_out(vty, "Import RT(s):\n");
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
+ safi_t safi, bool use_json)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ char *vrf_name = NULL;
+ json_object *json = NULL;
+ json_object *json_vrf = NULL;
+ json_object *json_vrfs = NULL;
+
+ if (use_json) {
+ json = json_object_new_object();
+ json_vrfs = json_object_new_object();
+ }
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
+ vrf_name = bgp->name;
+
+ if (use_json) {
+ json_vrf = json_object_new_object();
+ } else {
+ vty_out(vty, "\nInstance %s:\n",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME : bgp->name);
+ }
+ bgp_show_route_leak_vty(vty, vrf_name, afi, safi, 0, json_vrf);
+ if (use_json) {
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ json_object_object_add(json_vrfs,
+ VRF_DEFAULT_NAME, json_vrf);
+ else
+ json_object_object_add(json_vrfs, vrf_name,
+ json_vrf);
+ }
+ }
+
+ if (use_json) {
+ json_object_object_add(json, "vrfs", json_vrfs);
+ vty_json(vty, json);
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* "show [ip] bgp route-leak" command. */
+DEFUN (show_ip_bgp_route_leak,
+ show_ip_bgp_route_leak_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_SAFI_HELP_STR
+ "Route leaking information\n"
+ JSON_STR)
+{
+ char *vrf = NULL;
+ afi_t afi = AFI_MAX;
+ safi_t safi = SAFI_MAX;
+
+ bool uj = use_json(argc, argv);
+ int idx = 0;
+ json_object *json = NULL;
+
+ /* show [ip] bgp */
+ if (argv_find(argv, argc, "ip", &idx)) {
+ afi = AFI_IP;
+ safi = SAFI_UNICAST;
+ }
+ /* [vrf VIEWVRFNAME] */
+ if (argv_find(argv, argc, "view", &idx)) {
+ vty_out(vty,
+ "%% This command is not applicable to BGP views\n");
+ return CMD_WARNING;
+ }
+
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ }
+ /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
+ if (argv_find_and_parse_afi(argv, argc, &idx, &afi))
+ argv_find_and_parse_safi(argv, argc, &idx, &safi);
+
+ if (!((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)) {
+ vty_out(vty,
+ "%% This command is applicable only for unicast ipv4|ipv6\n");
+ return CMD_WARNING;
+ }
+
+ if (vrf && strmatch(vrf, "all"))
+ return bgp_show_all_instance_route_leak_vty(vty, afi, safi, uj);
+
+ if (uj)
+ json = json_object_new_object();
+
+ return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj, json);
+}
+
+static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
+ safi_t safi, bool uj)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (!uj)
+ vty_out(vty, "\nInstance %s:\n",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME
+ : bgp->name);
+
+ update_group_show(bgp, afi, safi, vty, 0, uj);
+ }
+}
+
+static int bgp_show_update_groups(struct vty *vty, const char *name, int afi,
+ int safi, uint64_t subgrp_id, bool uj)
+{
+ struct bgp *bgp;
+
+ if (name) {
+ if (strmatch(name, "all")) {
+ bgp_show_all_instances_updgrps_vty(vty, afi, safi, uj);
+ return CMD_SUCCESS;
+ } else {
+ bgp = bgp_lookup_by_name(name);
+ }
+ } else {
+ bgp = bgp_get_default();
+ }
+
+ if (bgp)
+ update_group_show(bgp, afi, safi, vty, subgrp_id, uj);
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_updgrps,
+ show_ip_bgp_updgrps_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] update-groups [SUBGROUP-ID] [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Detailed info about dynamic update groups\n"
+ "Specific subgroup to display detailed info for\n"
+ JSON_STR)
+{
+ char *vrf = NULL;
+ afi_t afi = AFI_IP6;
+ safi_t safi = SAFI_UNICAST;
+ uint64_t subgrp_id = 0;
+
+ int idx = 0;
+
+ bool uj = use_json(argc, argv);
+
+ /* show [ip] bgp */
+ if (argv_find(argv, argc, "ip", &idx))
+ afi = AFI_IP;
+ /* [<vrf> VIEWVRFNAME] */
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[idx + 1]->arg;
+ if (vrf && strmatch(vrf, VRF_DEFAULT_NAME))
+ vrf = NULL;
+ } else if (argv_find(argv, argc, "view", &idx))
+ /* [<view> VIEWVRFNAME] */
+ vrf = argv[idx + 1]->arg;
+ /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
+ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
+ argv_find_and_parse_safi(argv, argc, &idx, &safi);
+ }
+
+ /* get subgroup id, if provided */
+ idx = argc - 1;
+ if (argv[idx]->type == VARIABLE_TKN)
+ subgrp_id = strtoull(argv[idx]->arg, NULL, 10);
+
+ return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id, uj));
+}
+
+DEFUN (show_bgp_instance_all_ipv6_updgrps,
+ show_bgp_instance_all_ipv6_updgrps_cmd,
+ "show [ip] bgp <view|vrf> all update-groups [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_ALL_HELP_STR
+ "Detailed info about dynamic update groups\n"
+ JSON_STR)
+{
+ bool uj = use_json(argc, argv);
+
+ bgp_show_all_instances_updgrps_vty(vty, AFI_IP6, SAFI_UNICAST, uj);
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_l2vpn_evpn_updgrps,
+ show_bgp_l2vpn_evpn_updgrps_cmd,
+ "show [ip] bgp l2vpn evpn update-groups",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "l2vpn address family\n"
+ "evpn sub-address family\n"
+ "Detailed info about dynamic update groups\n")
+{
+ char *vrf = NULL;
+ uint64_t subgrp_id = 0;
+
+ bgp_show_update_groups(vty, vrf, AFI_L2VPN, SAFI_EVPN, subgrp_id, 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_updgrps_stats,
+ show_bgp_updgrps_stats_cmd,
+ "show [ip] bgp update-groups statistics",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "Detailed info about dynamic update groups\n"
+ "Statistics\n")
+{
+ struct bgp *bgp;
+
+ bgp = bgp_get_default();
+ if (bgp)
+ update_group_show_stats(bgp, vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_instance_updgrps_stats,
+ show_bgp_instance_updgrps_stats_cmd,
+ "show [ip] bgp <view|vrf> VIEWVRFNAME update-groups statistics",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ "Detailed info about dynamic update groups\n"
+ "Statistics\n")
+{
+ int idx_word = 3;
+ struct bgp *bgp;
+
+ bgp = bgp_lookup_by_name(argv[idx_word]->arg);
+ if (bgp)
+ update_group_show_stats(bgp, vty);
+
+ return CMD_SUCCESS;
+}
+
+static void show_bgp_updgrps_adj_info_aux(struct vty *vty, const char *name,
+ afi_t afi, safi_t safi,
+ const char *what, uint64_t subgrp_id)
+{
+ struct bgp *bgp;
+
+ if (name)
+ bgp = bgp_lookup_by_name(name);
+ else
+ bgp = bgp_get_default();
+
+ if (bgp) {
+ if (!strcmp(what, "advertise-queue"))
+ update_group_show_adj_queue(bgp, afi, safi, vty,
+ subgrp_id);
+ else if (!strcmp(what, "advertised-routes"))
+ update_group_show_advertised(bgp, afi, safi, vty,
+ subgrp_id);
+ else if (!strcmp(what, "packet-queue"))
+ update_group_show_packet_queue(bgp, afi, safi, vty,
+ subgrp_id);
+ }
+}
+
+DEFPY(show_ip_bgp_instance_updgrps_adj_s,
+ show_ip_bgp_instance_updgrps_adj_s_cmd,
+ "show [ip]$ip bgp [<view|vrf> VIEWVRFNAME$vrf] [<ipv4|ipv6>$afi <unicast|multicast|vpn>$safi] update-groups [SUBGROUP-ID]$sgid <advertise-queue|advertised-routes|packet-queue>$rtq",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
+ BGP_SAFI_HELP_STR
+ "Detailed info about dynamic update groups\n"
+ "Specific subgroup to display info for\n"
+ "Advertisement queue\n"
+ "Announced routes\n"
+ "Packet queue\n")
+{
+ uint64_t subgrp_id = 0;
+ afi_t afiz;
+ safi_t safiz;
+ if (sgid)
+ subgrp_id = strtoull(sgid, NULL, 10);
+
+ if (!ip && !afi)
+ afiz = AFI_IP6;
+ if (!ip && afi)
+ afiz = bgp_vty_afi_from_str(afi);
+ if (ip && !afi)
+ afiz = AFI_IP;
+ if (ip && afi) {
+ afiz = bgp_vty_afi_from_str(afi);
+ if (afiz != AFI_IP)
+ vty_out(vty,
+ "%% Cannot specify both 'ip' and 'ipv6'\n");
+ return CMD_WARNING;
+ }
+
+ safiz = safi ? bgp_vty_safi_from_str(safi) : SAFI_UNICAST;
+
+ show_bgp_updgrps_adj_info_aux(vty, vrf, afiz, safiz, rtq, subgrp_id);
+ return CMD_SUCCESS;
+}
+
+static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
+ json_object *json)
+{
+ struct listnode *node, *nnode;
+ struct prefix *range;
+ struct peer *conf;
+ struct peer *peer;
+ afi_t afi;
+ safi_t safi;
+ const char *peer_status;
+ int lr_count;
+ int dynamic;
+ bool af_cfgd;
+ json_object *json_peer_group = NULL;
+ json_object *json_peer_group_afc = NULL;
+ json_object *json_peer_group_members = NULL;
+ json_object *json_peer_group_dynamic = NULL;
+ json_object *json_peer_group_dynamic_af = NULL;
+ json_object *json_peer_group_ranges = NULL;
+
+ conf = group->conf;
+
+ if (json) {
+ json_peer_group = json_object_new_object();
+ json_peer_group_afc = json_object_new_array();
+ }
+
+ if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
+ if (json)
+ asn_asn2json(json_peer_group, "remoteAs", conf->as,
+ bgp_get_asnotation(conf->bgp));
+ else {
+ vty_out(vty, "\nBGP peer-group %s, remote AS ",
+ group->name);
+ vty_out(vty, ASN_FORMAT(bgp_get_asnotation(conf->bgp)),
+ &conf->as);
+ vty_out(vty, "\n");
+ }
+ } else if (conf->as_type == AS_INTERNAL) {
+ if (json)
+ asn_asn2json(json, "remoteAs", group->bgp->as,
+ group->bgp->asnotation);
+ else
+ vty_out(vty, "\nBGP peer-group %s, remote AS %s\n",
+ group->name, group->bgp->as_pretty);
+ } else {
+ if (!json)
+ vty_out(vty, "\nBGP peer-group %s\n", group->name);
+ }
+
+ if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) {
+ if (json)
+ json_object_string_add(json_peer_group, "type",
+ "internal");
+ else
+ vty_out(vty, " Peer-group type is internal\n");
+ } else {
+ if (json)
+ json_object_string_add(json_peer_group, "type",
+ "external");
+ else
+ vty_out(vty, " Peer-group type is external\n");
+ }
+
+ /* Display AFs configured. */
+ if (!json)
+ vty_out(vty, " Configured address-families:");
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (conf->afc[afi][safi]) {
+ af_cfgd = true;
+ if (json)
+ json_object_array_add(
+ json_peer_group_afc,
+ json_object_new_string(get_afi_safi_str(
+ afi, safi, false)));
+ else
+ vty_out(vty, " %s;",
+ get_afi_safi_str(afi, safi, false));
+ }
+ }
+
+ if (json) {
+ json_object_object_add(json_peer_group,
+ "addressFamiliesConfigured",
+ json_peer_group_afc);
+ } else {
+ if (!af_cfgd)
+ vty_out(vty, " none\n");
+ else
+ vty_out(vty, "\n");
+ }
+
+ /* Display listen ranges (for dynamic neighbors), if any */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ lr_count = listcount(group->listen_range[afi]);
+ if (lr_count) {
+ if (json) {
+ if (!json_peer_group_dynamic)
+ json_peer_group_dynamic =
+ json_object_new_object();
+
+ json_peer_group_dynamic_af =
+ json_object_new_object();
+ json_peer_group_ranges =
+ json_object_new_array();
+ json_object_int_add(json_peer_group_dynamic_af,
+ "count", lr_count);
+ } else {
+ vty_out(vty, " %d %s listen range(s)\n",
+ lr_count, afi2str(afi));
+ }
+
+ for (ALL_LIST_ELEMENTS(group->listen_range[afi], node,
+ nnode, range)) {
+ if (json) {
+ char buf[BUFSIZ];
+
+ snprintfrr(buf, sizeof(buf), "%pFX",
+ range);
+
+ json_object_array_add(
+ json_peer_group_ranges,
+ json_object_new_string(buf));
+ } else {
+ vty_out(vty, " %pFX\n", range);
+ }
+ }
+
+ if (json) {
+ json_object_object_add(
+ json_peer_group_dynamic_af, "ranges",
+ json_peer_group_ranges);
+
+ json_object_object_add(
+ json_peer_group_dynamic, afi2str(afi),
+ json_peer_group_dynamic_af);
+ }
+ }
+ }
+
+ if (json_peer_group_dynamic)
+ json_object_object_add(json_peer_group, "dynamicRanges",
+ json_peer_group_dynamic);
+
+ /* Display group members and their status */
+ if (listcount(group->peer)) {
+ if (json)
+ json_peer_group_members = json_object_new_object();
+ else
+ vty_out(vty, " Peer-group members:\n");
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
+ || CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN))
+ peer_status = "Idle (Admin)";
+ else if (CHECK_FLAG(peer->sflags,
+ PEER_STATUS_PREFIX_OVERFLOW))
+ peer_status = "Idle (PfxCt)";
+ else
+ peer_status =
+ lookup_msg(bgp_status_msg,
+ peer->connection->status,
+ NULL);
+
+ dynamic = peer_dynamic_neighbor(peer);
+
+ if (json) {
+ json_object *json_peer_group_member =
+ json_object_new_object();
+
+ json_object_string_add(json_peer_group_member,
+ "status", peer_status);
+
+ if (dynamic)
+ json_object_boolean_true_add(
+ json_peer_group_member,
+ "dynamic");
+
+ json_object_object_add(json_peer_group_members,
+ peer->host,
+ json_peer_group_member);
+ } else {
+ vty_out(vty, " %s %s %s \n", peer->host,
+ dynamic ? "(dynamic)" : "",
+ peer_status);
+ }
+ }
+ if (json)
+ json_object_object_add(json_peer_group, "members",
+ json_peer_group_members);
+ }
+
+ if (json)
+ json_object_object_add(json, group->name, json_peer_group);
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
+ const char *group_name, bool uj)
+{
+ struct bgp *bgp;
+ struct listnode *node, *nnode;
+ struct peer_group *group;
+ bool found = false;
+ json_object *json = NULL;
+
+ if (uj)
+ json = json_object_new_object();
+
+ bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
+ if (!bgp) {
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty, "%% BGP instance not found\n");
+
+ return CMD_WARNING;
+ }
+
+ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
+ if (group_name) {
+ if (strmatch(group->name, group_name)) {
+ bgp_show_one_peer_group(vty, group, json);
+ found = true;
+ break;
+ }
+ } else {
+ bgp_show_one_peer_group(vty, group, json);
+ }
+ }
+
+ if (group_name && !found && !uj)
+ vty_out(vty, "%% No such peer-group\n");
+
+ if (uj)
+ vty_json(vty, json);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_ip_bgp_peer_groups, show_ip_bgp_peer_groups_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME] [json]",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
+ "Detailed information on BGP peer groups\n"
+ "Peer group name\n" JSON_STR)
+{
+ char *vrf, *pg;
+ int idx = 0;
+ bool uj = use_json(argc, argv);
+
+ vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg
+ : NULL;
+ pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL;
+
+ return bgp_show_peer_group_vty(vty, vrf, pg, uj);
+}
+
+
+/* Redistribute VTY commands. */
+
+DEFUN (bgp_redistribute_ipv4,
+ bgp_redistribute_ipv4_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD,
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int type;
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_redist_add(bgp, AFI_IP, type, 0);
+ return bgp_redistribute_set(bgp, AFI_IP, type, 0, false);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4, bgp_redistribute_ipv4_hidden_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD,
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD)
+
+DEFUN (bgp_redistribute_ipv4_rmap,
+ bgp_redistribute_ipv4_rmap_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_word = 3;
+ int type;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map = route_map_lookup_warn_noexist(
+ vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ red = bgp_redist_add(bgp, AFI_IP, type, 0);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_rmap, bgp_redistribute_ipv4_rmap_hidden_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (bgp_redistribute_ipv4_metric,
+ bgp_redistribute_ipv4_metric_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_number = 3;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, type, 0);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+ return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_metric, bgp_redistribute_ipv4_metric_hidden_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+
+DEFUN (bgp_redistribute_ipv4_rmap_metric,
+ bgp_redistribute_ipv4_rmap_metric_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " route-map RMAP_NAME metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_word = 3;
+ int idx_number = 5;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, type, 0);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+ return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_rmap_metric,
+ bgp_redistribute_ipv4_rmap_metric_hidden_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD
+ " route-map RMAP_NAME metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+
+DEFUN (bgp_redistribute_ipv4_metric_rmap,
+ bgp_redistribute_ipv4_metric_rmap_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_number = 3;
+ int idx_word = 5;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, type, 0);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+ changed |=
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_metric_rmap,
+ bgp_redistribute_ipv4_metric_rmap_hidden_cmd,
+ "redistribute " FRR_IP_REDIST_STR_BGPD
+ " metric (0-4294967295) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (bgp_redistribute_ipv4_ospf,
+ bgp_redistribute_ipv4_ospf_cmd,
+ "redistribute <ospf|table> (1-65535)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 1;
+ int idx_number = 2;
+ unsigned short instance;
+ unsigned short protocol;
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ bgp_redist_add(bgp, AFI_IP, protocol, instance);
+ return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, false);
+}
+
+ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd,
+ "redistribute <ospf|table> (1-65535)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n")
+
+DEFUN (bgp_redistribute_ipv4_ospf_rmap,
+ bgp_redistribute_ipv4_ospf_rmap_cmd,
+ "redistribute <ospf|table> (1-65535) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 1;
+ int idx_number = 2;
+ int idx_word = 4;
+ struct bgp_redist *red;
+ unsigned short instance;
+ int protocol;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+ red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
+}
+
+ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
+ bgp_redistribute_ipv4_ospf_rmap_hidden_cmd,
+ "redistribute <ospf|table> (1-65535) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (bgp_redistribute_ipv4_ospf_metric,
+ bgp_redistribute_ipv4_ospf_metric_cmd,
+ "redistribute <ospf|table> (1-65535) metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 1;
+ int idx_number = 2;
+ int idx_number_2 = 4;
+ uint32_t metric;
+ struct bgp_redist *red;
+ unsigned short instance;
+ int protocol;
+ bool changed;
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+ metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+ metric);
+ return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
+}
+
+ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
+ bgp_redistribute_ipv4_ospf_metric_hidden_cmd,
+ "redistribute <ospf|table> (1-65535) metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+
+DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
+ bgp_redistribute_ipv4_ospf_rmap_metric_cmd,
+ "redistribute <ospf|table> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 1;
+ int idx_number = 2;
+ int idx_word = 4;
+ int idx_number_2 = 6;
+ uint32_t metric;
+ struct bgp_redist *red;
+ unsigned short instance;
+ int protocol;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+ metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+ metric);
+ return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_ospf_rmap_metric,
+ bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd,
+ "redistribute <ospf|table> (1-65535) route-map RMAP_NAME metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+
+DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
+ bgp_redistribute_ipv4_ospf_metric_rmap_cmd,
+ "redistribute <ospf|table> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 1;
+ int idx_number = 2;
+ int idx_number_2 = 4;
+ int idx_word = 6;
+ uint32_t metric;
+ struct bgp_redist *red;
+ unsigned short instance;
+ int protocol;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+ metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+ metric);
+ changed |=
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
+}
+
+ALIAS_HIDDEN(
+ bgp_redistribute_ipv4_ospf_metric_rmap,
+ bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd,
+ "redistribute <ospf|table> (1-65535) metric (0-4294967295) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (no_bgp_redistribute_ipv4_ospf,
+ no_bgp_redistribute_ipv4_ospf_cmd,
+ "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_ospf_table = 2;
+ int idx_number = 3;
+ unsigned short instance;
+ int protocol;
+
+ if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
+ protocol = ZEBRA_ROUTE_OSPF;
+ else {
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use '%s'\n",
+ argv[idx_ospf_table]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ protocol = ZEBRA_ROUTE_TABLE;
+ }
+
+ instance = strtoul(argv[idx_number]->arg, NULL, 10);
+ bgp_redistribute_unset(bgp, AFI_IP, protocol, instance);
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(
+ no_bgp_redistribute_ipv4_ospf, no_bgp_redistribute_ipv4_ospf_hidden_cmd,
+ "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ "Open Shortest Path First (OSPFv2)\n"
+ "Non-main Kernel Routing Table\n"
+ "Instance ID/Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (no_bgp_redistribute_ipv4,
+ no_bgp_redistribute_ipv4_cmd,
+ "no redistribute " FRR_IP_REDIST_STR_BGPD " [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 2;
+ int type;
+
+ type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ bgp_redistribute_unset(bgp, AFI_IP, type, 0);
+ return CMD_SUCCESS;
+}
+
+ALIAS_HIDDEN(
+ no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_hidden_cmd,
+ "no redistribute " FRR_IP_REDIST_STR_BGPD
+ " [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+
+DEFUN (bgp_redistribute_ipv6,
+ bgp_redistribute_ipv6_cmd,
+ "redistribute " FRR_IP6_REDIST_STR_BGPD,
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_redist_add(bgp, AFI_IP6, type, 0);
+ return bgp_redistribute_set(bgp, AFI_IP6, type, 0, false);
+}
+
+DEFUN (bgp_redistribute_ipv6_rmap,
+ bgp_redistribute_ipv6_rmap_cmd,
+ "redistribute " FRR_IP6_REDIST_STR_BGPD " route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_word = 3;
+ int type;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ red = bgp_redist_add(bgp, AFI_IP6, type, 0);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
+}
+
+DEFUN (bgp_redistribute_ipv6_metric,
+ bgp_redistribute_ipv6_metric_cmd,
+ "redistribute " FRR_IP6_REDIST_STR_BGPD " metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_number = 3;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP6, type, 0);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
+ return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
+}
+
+DEFUN (bgp_redistribute_ipv6_rmap_metric,
+ bgp_redistribute_ipv6_rmap_metric_cmd,
+ "redistribute " FRR_IP6_REDIST_STR_BGPD " route-map RMAP_NAME metric (0-4294967295)",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD
+ "Route map reference\n"
+ "Pointer to route-map entries\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_word = 3;
+ int idx_number = 5;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP6, type, 0);
+ changed =
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type,
+ metric);
+ return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
+}
+
+DEFUN (bgp_redistribute_ipv6_metric_rmap,
+ bgp_redistribute_ipv6_metric_rmap_cmd,
+ "redistribute " FRR_IP6_REDIST_STR_BGPD " metric (0-4294967295) route-map RMAP_NAME",
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 1;
+ int idx_number = 3;
+ int idx_word = 5;
+ int type;
+ uint32_t metric;
+ struct bgp_redist *red;
+ bool changed;
+ struct route_map *route_map =
+ route_map_lookup_warn_noexist(vty, argv[idx_word]->arg);
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ metric = strtoul(argv[idx_number]->arg, NULL, 10);
+
+ red = bgp_redist_add(bgp, AFI_IP6, type, 0);
+ changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST,
+ metric);
+ changed |=
+ bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map);
+ return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
+}
+
+DEFUN (no_bgp_redistribute_ipv6,
+ no_bgp_redistribute_ipv6_cmd,
+ "no redistribute " FRR_IP6_REDIST_STR_BGPD " [{metric (0-4294967295)|route-map RMAP_NAME}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ FRR_IP6_REDIST_HELP_STR_BGPD
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ int idx_protocol = 2;
+ int type;
+
+ type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
+ if (type < 0) {
+ vty_out(vty, "%% Invalid route type\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
+ return CMD_SUCCESS;
+}
+
+/* Neighbor update tcp-mss. */
+static int peer_tcp_mss_vty(struct vty *vty, const char *peer_str,
+ const char *tcp_mss_str)
+{
+ struct peer *peer;
+ uint32_t tcp_mss_val = 0;
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (tcp_mss_str) {
+ tcp_mss_val = strtoul(tcp_mss_str, NULL, 10);
+ peer_tcp_mss_set(peer, tcp_mss_val);
+ } else {
+ peer_tcp_mss_unset(peer);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(neighbor_tcp_mss, neighbor_tcp_mss_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss (1-65535)",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "TCP max segment size\n"
+ "TCP MSS value\n")
+{
+ int peer_index = 1;
+ int mss_index = 3;
+
+ vty_out(vty,
+ " Warning: Reset BGP session for tcp-mss value to take effect\n");
+ return peer_tcp_mss_vty(vty, argv[peer_index]->arg,
+ argv[mss_index]->arg);
+}
+
+DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss [(1-65535)]",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "TCP max segment size\n"
+ "TCP MSS value\n")
+{
+ int peer_index = 2;
+
+ vty_out(vty,
+ " Warning: Reset BGP session for tcp-mss value to take effect\n");
+ return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL);
+}
+
+DEFPY(bgp_retain_route_target, bgp_retain_route_target_cmd,
+ "[no$no] bgp retain route-target all",
+ NO_STR BGP_STR
+ "Retain BGP updates\n"
+ "Retain BGP updates based on route-target values\n"
+ "Retain all BGP updates\n")
+{
+ bool check;
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+ check = CHECK_FLAG(bgp->af_flags[bgp_node_afi(vty)][bgp_node_safi(vty)],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
+ if (check != !no) {
+ if (!no)
+ SET_FLAG(bgp->af_flags[bgp_node_afi(vty)]
+ [bgp_node_safi(vty)],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
+ else
+ UNSET_FLAG(bgp->af_flags[bgp_node_afi(vty)]
+ [bgp_node_safi(vty)],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
+ /* trigger a flush to re-sync with ADJ-RIB-in */
+ bgp_clear(vty, bgp, bgp_node_afi(vty), bgp_node_safi(vty),
+ clear_all, BGP_CLEAR_SOFT_IN, NULL);
+ }
+ return CMD_SUCCESS;
+}
+
+static void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp,
+ afi_t afi, safi_t safi)
+{
+ int i;
+
+ /* Unicast redistribution only. */
+ if (safi != SAFI_UNICAST)
+ return;
+
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+ /* Redistribute BGP does not make sense. */
+ if (i != ZEBRA_ROUTE_BGP) {
+ struct list *red_list;
+ struct listnode *node;
+ struct bgp_redist *red;
+
+ red_list = bgp->redist[afi][i];
+ if (!red_list)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
+ /* "redistribute" configuration. */
+ vty_out(vty, " redistribute %s",
+ zebra_route_string(i));
+ if (red->instance)
+ vty_out(vty, " %d", red->instance);
+ if (red->redist_metric_flag)
+ vty_out(vty, " metric %u",
+ red->redist_metric);
+ if (red->rmap.name)
+ vty_out(vty, " route-map %s",
+ red->rmap.name);
+ vty_out(vty, "\n");
+ }
+ }
+ }
+}
+
+/* peer-group helpers for config-write */
+
+bool peergroup_flag_check(struct peer *peer, uint64_t flag)
+{
+ if (!peer_group_active(peer)) {
+ if (CHECK_FLAG(peer->flags_invert, flag))
+ return !CHECK_FLAG(peer->flags, flag);
+ else
+ return !!CHECK_FLAG(peer->flags, flag);
+ }
+
+ return !!CHECK_FLAG(peer->flags_override, flag);
+}
+
+static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag)
+{
+ if (!peer_group_active(peer)) {
+ if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
+ return !peer_af_flag_check(peer, afi, safi, flag);
+ else
+ return peer_af_flag_check(peer, afi, safi, flag);
+ }
+
+ return !!CHECK_FLAG(peer->af_flags_override[afi][safi], flag);
+}
+
+static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint8_t type, int direct)
+{
+ struct bgp_filter *filter;
+
+ if (peer_group_active(peer))
+ return !!CHECK_FLAG(peer->filter_override[afi][safi][direct],
+ type);
+
+ filter = &peer->filter[afi][safi];
+ switch (type) {
+ case PEER_FT_DISTRIBUTE_LIST:
+ return !!(filter->dlist[direct].name);
+ case PEER_FT_FILTER_LIST:
+ return !!(filter->aslist[direct].name);
+ case PEER_FT_PREFIX_LIST:
+ return !!(filter->plist[direct].name);
+ case PEER_FT_ROUTE_MAP:
+ return !!(filter->map[direct].name);
+ case PEER_FT_UNSUPPRESS_MAP:
+ return !!(filter->usmap.name);
+ case PEER_FT_ADVERTISE_MAP:
+ return !!(filter->advmap.aname
+ && ((filter->advmap.condition == direct)
+ && filter->advmap.cname));
+ default:
+ return false;
+ }
+}
+
+/* Return true if the addpath type is set for peer and different from
+ * peer-group.
+ */
+static bool peergroup_af_addpath_check(struct peer *peer, afi_t afi,
+ safi_t safi)
+{
+ enum bgp_addpath_strat type, g_type;
+
+ type = peer->addpath_type[afi][safi];
+
+ if (type != BGP_ADDPATH_NONE) {
+ if (peer_group_active(peer)) {
+ g_type = peer->group->conf->addpath_type[afi][safi];
+
+ if (type != g_type)
+ return true;
+ else
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/* This is part of the address-family block (unicast only) */
+static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
+ afi_t afi)
+{
+ int indent = 2;
+ uint32_t tovpn_sid_index = 0;
+
+ if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) {
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT))
+ vty_out(vty, "%*simport vrf route-map %s\n", indent, "",
+ bgp->vpn_policy[afi]
+ .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]);
+ else
+ vty_out(vty, "%*sroute-map vpn import %s\n", indent, "",
+ bgp->vpn_policy[afi]
+ .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]);
+ }
+ if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)
+ || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT))
+ return;
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+
+ vty_out(vty, "%*slabel vpn export %s\n", indent, "", "auto");
+
+ } else {
+ if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
+ vty_out(vty, "%*slabel vpn export %u\n", indent, "",
+ bgp->vpn_policy[afi].tovpn_label);
+ }
+ }
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP))
+ vty_out(vty,
+ "%*slabel vpn export allocation-mode per-nexthop\n",
+ indent, "");
+
+ tovpn_sid_index = bgp->vpn_policy[afi].tovpn_sid_index;
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_SID_AUTO)) {
+ vty_out(vty, "%*ssid vpn export %s\n", indent, "", "auto");
+ } else if (tovpn_sid_index != 0) {
+ vty_out(vty, "%*ssid vpn export %d\n", indent, "",
+ tovpn_sid_index);
+ }
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET))
+ vty_out(vty, "%*srd vpn export %s\n", indent, "",
+ bgp->vpn_policy[afi].tovpn_rd_pretty);
+
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
+
+ char buf[PREFIX_STRLEN];
+ if (inet_ntop(bgp->vpn_policy[afi].tovpn_nexthop.family,
+ &bgp->vpn_policy[afi].tovpn_nexthop.u.prefix, buf,
+ sizeof(buf))) {
+
+ vty_out(vty, "%*snexthop vpn export %s\n",
+ indent, "", buf);
+ }
+ }
+ if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]
+ && bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]
+ && ecommunity_cmp(
+ bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
+ bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN])) {
+
+ char *b = ecommunity_ecom2str(
+ bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN],
+ ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
+ vty_out(vty, "%*srt vpn both %s\n", indent, "", b);
+ XFREE(MTYPE_ECOMMUNITY_STR, b);
+ } else {
+ if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
+ char *b = ecommunity_ecom2str(
+ bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
+ ECOMMUNITY_FORMAT_ROUTE_MAP,
+ ECOMMUNITY_ROUTE_TARGET);
+ vty_out(vty, "%*srt vpn import %s\n", indent, "", b);
+ XFREE(MTYPE_ECOMMUNITY_STR, b);
+ }
+ if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
+ char *b = ecommunity_ecom2str(
+ bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
+ ECOMMUNITY_FORMAT_ROUTE_MAP,
+ ECOMMUNITY_ROUTE_TARGET);
+ vty_out(vty, "%*srt vpn export %s\n", indent, "", b);
+ XFREE(MTYPE_ECOMMUNITY_STR, b);
+ }
+ }
+
+ if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN])
+ vty_out(vty, "%*sroute-map vpn export %s\n", indent, "",
+ bgp->vpn_policy[afi]
+ .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]);
+
+ if (bgp->vpn_policy[afi].import_redirect_rtlist) {
+ char *b = ecommunity_ecom2str(
+ bgp->vpn_policy[afi]
+ .import_redirect_rtlist,
+ ECOMMUNITY_FORMAT_ROUTE_MAP,
+ ECOMMUNITY_ROUTE_TARGET);
+
+ if (bgp->vpn_policy[afi].import_redirect_rtlist->unit_size
+ != ECOMMUNITY_SIZE)
+ vty_out(vty, "%*srt6 redirect import %s\n",
+ indent, "", b);
+ else
+ vty_out(vty, "%*srt redirect import %s\n",
+ indent, "", b);
+ XFREE(MTYPE_ECOMMUNITY_STR, b);
+ }
+}
+
+static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
+ afi_t afi, safi_t safi)
+{
+ struct bgp_filter *filter;
+ char *addr;
+
+ addr = peer->host;
+ filter = &peer->filter[afi][safi];
+
+ /* distribute-list. */
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s distribute-list %s in\n", addr,
+ filter->dlist[FILTER_IN].name);
+
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
+ FILTER_OUT))
+ vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
+ filter->dlist[FILTER_OUT].name);
+
+ /* prefix-list. */
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
+ filter->plist[FILTER_IN].name);
+
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
+ FILTER_OUT))
+ vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
+ filter->plist[FILTER_OUT].name);
+
+ /* route-map. */
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP, RMAP_IN))
+ vty_out(vty, " neighbor %s route-map %s in\n", addr,
+ filter->map[RMAP_IN].name);
+
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP,
+ RMAP_OUT))
+ vty_out(vty, " neighbor %s route-map %s out\n", addr,
+ filter->map[RMAP_OUT].name);
+
+ /* unsuppress-map */
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_UNSUPPRESS_MAP, 0))
+ vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
+ filter->usmap.name);
+
+ /* advertise-map : always applied in OUT direction*/
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
+ CONDITION_NON_EXIST))
+ vty_out(vty,
+ " neighbor %s advertise-map %s non-exist-map %s\n",
+ addr, filter->advmap.aname, filter->advmap.cname);
+
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ADVERTISE_MAP,
+ CONDITION_EXIST))
+ vty_out(vty, " neighbor %s advertise-map %s exist-map %s\n",
+ addr, filter->advmap.aname, filter->advmap.cname);
+
+ /* filter-list. */
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s filter-list %s in\n", addr,
+ filter->aslist[FILTER_IN].name);
+
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
+ FILTER_OUT))
+ vty_out(vty, " neighbor %s filter-list %s out\n", addr,
+ filter->aslist[FILTER_OUT].name);
+}
+
+/* BGP peer configuration display function. */
+static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
+ struct peer *peer)
+{
+ struct peer *g_peer = NULL;
+ char *addr;
+ int if_pg_printed = false;
+ int if_ras_printed = false;
+
+ /* Skip dynamic neighbors. */
+ if (peer_dynamic_neighbor(peer))
+ return;
+
+ if (peer->conf_if)
+ addr = peer->conf_if;
+ else
+ addr = peer->host;
+
+ /************************************
+ ****** Global to the neighbor ******
+ ************************************/
+ if (peer->conf_if) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
+ vty_out(vty, " neighbor %s interface v6only", addr);
+ else
+ vty_out(vty, " neighbor %s interface", addr);
+
+ if (peer_group_active(peer)) {
+ vty_out(vty, " peer-group %s", peer->group->name);
+ if_pg_printed = true;
+ } else if (peer->as_type == AS_SPECIFIED) {
+ vty_out(vty, " remote-as %s", peer->as_pretty);
+ if_ras_printed = true;
+ } else if (peer->as_type == AS_INTERNAL) {
+ vty_out(vty, " remote-as internal");
+ if_ras_printed = true;
+ } else if (peer->as_type == AS_EXTERNAL) {
+ vty_out(vty, " remote-as external");
+ if_ras_printed = true;
+ }
+
+ vty_out(vty, "\n");
+ }
+
+ /* remote-as and peer-group */
+ /* peer is a member of a peer-group */
+ if (peer_group_active(peer)) {
+ g_peer = peer->group->conf;
+
+ if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {
+ if (peer->as_type == AS_SPECIFIED) {
+ vty_out(vty, " neighbor %s remote-as %s\n",
+ addr, peer->as_pretty);
+ } else if (peer->as_type == AS_INTERNAL) {
+ vty_out(vty,
+ " neighbor %s remote-as internal\n",
+ addr);
+ } else if (peer->as_type == AS_EXTERNAL) {
+ vty_out(vty,
+ " neighbor %s remote-as external\n",
+ addr);
+ }
+ }
+
+ /* For swpX peers we displayed the peer-group
+ * via 'neighbor swpX interface peer-group PGNAME' */
+ if (!if_pg_printed)
+ vty_out(vty, " neighbor %s peer-group %s\n", addr,
+ peer->group->name);
+ }
+
+ /* peer is NOT a member of a peer-group */
+ else {
+ /* peer is a peer-group, declare the peer-group */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ vty_out(vty, " neighbor %s peer-group\n", addr);
+ }
+
+ if (!if_ras_printed) {
+ if (peer->as_type == AS_SPECIFIED) {
+ vty_out(vty, " neighbor %s remote-as %s\n",
+ addr, peer->as_pretty);
+ } else if (peer->as_type == AS_INTERNAL) {
+ vty_out(vty,
+ " neighbor %s remote-as internal\n",
+ addr);
+ } else if (peer->as_type == AS_EXTERNAL) {
+ vty_out(vty,
+ " neighbor %s remote-as external\n",
+ addr);
+ }
+ }
+ }
+
+ /* local-as */
+ if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS)) {
+ vty_out(vty, " neighbor %s local-as %s", addr,
+ peer->change_local_as_pretty);
+ if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND))
+ vty_out(vty, " no-prepend");
+ if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS))
+ vty_out(vty, " replace-as");
+ vty_out(vty, "\n");
+ }
+
+ /* description */
+ if (peer->desc) {
+ vty_out(vty, " neighbor %s description %s\n", addr, peer->desc);
+ }
+
+ /* shutdown */
+ if (peergroup_flag_check(peer, PEER_FLAG_SHUTDOWN)) {
+ if (peer->tx_shutdown_message)
+ vty_out(vty, " neighbor %s shutdown message %s\n", addr,
+ peer->tx_shutdown_message);
+ else
+ vty_out(vty, " neighbor %s shutdown\n", addr);
+ }
+
+ if (peergroup_flag_check(peer, PEER_FLAG_RTT_SHUTDOWN))
+ vty_out(vty, " neighbor %s shutdown rtt %u count %u\n", addr,
+ peer->rtt_expected, peer->rtt_keepalive_conf);
+
+ /* bfd */
+ if (peer->bfd_config)
+ bgp_bfd_peer_config_write(vty, peer, addr);
+
+ /* password */
+ if (peergroup_flag_check(peer, PEER_FLAG_PASSWORD))
+ vty_out(vty, " neighbor %s password %s\n", addr,
+ peer->password);
+
+ /* neighbor solo */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
+ if (!peer_group_active(peer)) {
+ vty_out(vty, " neighbor %s solo\n", addr);
+ }
+ }
+
+ /* BGP port */
+ if (peer->port != BGP_PORT_DEFAULT) {
+ vty_out(vty, " neighbor %s port %d\n", addr, peer->port);
+ }
+
+ /* Local interface name */
+ if (peer->ifname) {
+ vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
+ }
+
+ /* TCP max segment size */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
+ vty_out(vty, " neighbor %s tcp-mss %d\n", addr, peer->tcp_mss);
+
+ /* passive */
+ if (peergroup_flag_check(peer, PEER_FLAG_PASSIVE))
+ vty_out(vty, " neighbor %s passive\n", addr);
+
+ /* ebgp-multihop */
+ if (peer->sort != BGP_PEER_IBGP && peer->ttl != BGP_DEFAULT_TTL
+ && !(peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED
+ && peer->ttl == MAXTTL)) {
+ if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
+ if (peer->ttl != MAXTTL)
+ vty_out(vty, " neighbor %s ebgp-multihop %d\n",
+ addr, peer->ttl);
+ else
+ vty_out(vty, " neighbor %s ebgp-multihop\n",
+ addr);
+ }
+ }
+
+ /* aigp */
+ if (peergroup_flag_check(peer, PEER_FLAG_AIGP))
+ vty_out(vty, " neighbor %s aigp\n", addr);
+
+ /* graceful-shutdown */
+ if (peergroup_flag_check(peer, PEER_FLAG_GRACEFUL_SHUTDOWN))
+ vty_out(vty, " neighbor %s graceful-shutdown\n", addr);
+
+ /* role */
+ if (peergroup_flag_check(peer, PEER_FLAG_ROLE) &&
+ peer->local_role != ROLE_UNDEFINED)
+ vty_out(vty, " neighbor %s local-role %s%s\n", addr,
+ bgp_get_name_by_role(peer->local_role),
+ CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)
+ ? " strict-mode"
+ : "");
+
+ /* ttl-security hops */
+ if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED) {
+ if (!peer_group_active(peer)
+ || g_peer->gtsm_hops != peer->gtsm_hops) {
+ vty_out(vty, " neighbor %s ttl-security hops %d\n",
+ addr, peer->gtsm_hops);
+ }
+ }
+
+ /* disable-connected-check */
+ if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_CONNECTED_CHECK))
+ vty_out(vty, " neighbor %s disable-connected-check\n", addr);
+
+ /* link-bw-encoding-ieee */
+ if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE))
+ vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
+ addr);
+
+ /* extended-optional-parameters */
+ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
+ vty_out(vty, " neighbor %s extended-optional-parameters\n",
+ addr);
+
+ /* enforce-first-as */
+ if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
+ vty_out(vty, " neighbor %s enforce-first-as\n", addr);
+
+ /* update-source */
+ if (peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
+ if (peer->update_source)
+ vty_out(vty, " neighbor %s update-source %pSU\n", addr,
+ peer->update_source);
+ else if (peer->update_if)
+ vty_out(vty, " neighbor %s update-source %s\n", addr,
+ peer->update_if);
+ }
+
+ /* advertisement-interval */
+ if (peergroup_flag_check(peer, PEER_FLAG_ROUTEADV))
+ vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
+ peer->routeadv);
+
+ /* timers */
+ if (peergroup_flag_check(peer, PEER_FLAG_TIMER))
+ vty_out(vty, " neighbor %s timers %u %u\n", addr,
+ peer->keepalive, peer->holdtime);
+
+ /* timers connect */
+ if (peergroup_flag_check(peer, PEER_FLAG_TIMER_CONNECT))
+ vty_out(vty, " neighbor %s timers connect %u\n", addr,
+ peer->connect);
+ /* need special-case handling for changed default values due to
+ * config profile / version (because there is no "timers bgp connect"
+ * command, we need to save this per-peer :/)
+ */
+ else if (!peer_group_active(peer) && !peer->connect &&
+ peer->bgp->default_connect_retry != SAVE_BGP_CONNECT_RETRY)
+ vty_out(vty, " neighbor %s timers connect %u\n", addr,
+ peer->bgp->default_connect_retry);
+
+ /* timers delayopen */
+ if (peergroup_flag_check(peer, PEER_FLAG_TIMER_DELAYOPEN))
+ vty_out(vty, " neighbor %s timers delayopen %u\n", addr,
+ peer->delayopen);
+ /* Save config even though flag is not set if default values have been
+ * changed
+ */
+ else if (!peer_group_active(peer) && !peer->delayopen
+ && peer->bgp->default_delayopen != BGP_DEFAULT_DELAYOPEN)
+ vty_out(vty, " neighbor %s timers delayopen %u\n", addr,
+ peer->bgp->default_delayopen);
+
+ /* capability dynamic */
+ if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
+ vty_out(vty, " neighbor %s capability dynamic\n", addr);
+
+ /* capability extended-nexthop */
+ if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
+ if (CHECK_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE) &&
+ !peer->conf_if)
+ vty_out(vty,
+ " no neighbor %s capability extended-nexthop\n",
+ addr);
+ else if (!peer->conf_if)
+ vty_out(vty,
+ " neighbor %s capability extended-nexthop\n",
+ addr);
+ }
+
+ /* capability software-version */
+ if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION))
+ vty_out(vty, " neighbor %s capability software-version\n",
+ addr);
+
+ /* dont-capability-negotiation */
+ if (peergroup_flag_check(peer, PEER_FLAG_DONT_CAPABILITY))
+ vty_out(vty, " neighbor %s dont-capability-negotiate\n", addr);
+
+ /* override-capability */
+ if (peergroup_flag_check(peer, PEER_FLAG_OVERRIDE_CAPABILITY))
+ vty_out(vty, " neighbor %s override-capability\n", addr);
+
+ /* strict-capability-match */
+ if (peergroup_flag_check(peer, PEER_FLAG_STRICT_CAP_MATCH))
+ vty_out(vty, " neighbor %s strict-capability-match\n", addr);
+
+ /* Sender side AS path loop detection. */
+ if (peer->as_path_loop_detection)
+ vty_out(vty, " neighbor %s sender-as-path-loop-detection\n",
+ addr);
+
+ /* path-attribute discard */
+ char discard_attrs_str[BUFSIZ] = {0};
+ bool discard_attrs = bgp_path_attribute_discard(
+ peer, discard_attrs_str, sizeof(discard_attrs_str));
+
+ if (discard_attrs)
+ vty_out(vty, " neighbor %s path-attribute discard %s\n", addr,
+ discard_attrs_str);
+
+ /* path-attribute treat-as-withdraw */
+ char withdraw_attrs_str[BUFSIZ] = {0};
+ bool withdraw_attrs = bgp_path_attribute_treat_as_withdraw(
+ peer, withdraw_attrs_str, sizeof(withdraw_attrs_str));
+
+ if (withdraw_attrs)
+ vty_out(vty,
+ " neighbor %s path-attribute treat-as-withdraw %s\n",
+ addr, withdraw_attrs_str);
+
+ if (!CHECK_FLAG(peer->peer_gr_new_status_flag,
+ PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT)) {
+
+ if (CHECK_FLAG(peer->peer_gr_new_status_flag,
+ PEER_GRACEFUL_RESTART_NEW_STATE_HELPER)) {
+ vty_out(vty,
+ " neighbor %s graceful-restart-helper\n", addr);
+ } else if (CHECK_FLAG(
+ peer->peer_gr_new_status_flag,
+ PEER_GRACEFUL_RESTART_NEW_STATE_RESTART)) {
+ vty_out(vty,
+ " neighbor %s graceful-restart\n", addr);
+ } else if (
+ (!(CHECK_FLAG(peer->peer_gr_new_status_flag,
+ PEER_GRACEFUL_RESTART_NEW_STATE_HELPER))
+ && !(CHECK_FLAG(
+ peer->peer_gr_new_status_flag,
+ PEER_GRACEFUL_RESTART_NEW_STATE_RESTART)))) {
+ vty_out(vty, " neighbor %s graceful-restart-disable\n",
+ addr);
+ }
+ }
+}
+
+/* BGP peer configuration display function. */
+static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
+ struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct peer *g_peer = NULL;
+ char *addr;
+ bool flag_scomm, flag_secomm, flag_slcomm;
+
+ /* Skip dynamic neighbors. */
+ if (peer_dynamic_neighbor(peer))
+ return;
+
+ if (peer->conf_if)
+ addr = peer->conf_if;
+ else
+ addr = peer->host;
+
+ /************************************
+ ****** Per AF to the neighbor ******
+ ************************************/
+ if (peer_group_active(peer)) {
+ g_peer = peer->group->conf;
+
+ /* If the peer-group is active but peer is not, print a 'no
+ * activate' */
+ if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
+ vty_out(vty, " no neighbor %s activate\n", addr);
+ }
+
+ /* If the peer-group is not active but peer is, print an
+ 'activate' */
+ else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
+ vty_out(vty, " neighbor %s activate\n", addr);
+ }
+ } else {
+ if (peer->afc[afi][safi]) {
+ if (safi == SAFI_ENCAP)
+ vty_out(vty, " neighbor %s activate\n", addr);
+ else if (!bgp->default_af[afi][safi])
+ vty_out(vty, " neighbor %s activate\n", addr);
+ } else {
+ if (bgp->default_af[afi][safi])
+ vty_out(vty, " no neighbor %s activate\n",
+ addr);
+ }
+ }
+
+ /* addpath TX knobs */
+ if (peergroup_af_addpath_check(peer, afi, safi)) {
+ switch (peer->addpath_type[afi][safi]) {
+ case BGP_ADDPATH_ALL:
+ vty_out(vty, " neighbor %s addpath-tx-all-paths\n",
+ addr);
+ break;
+ case BGP_ADDPATH_BEST_PER_AS:
+ vty_out(vty,
+ " neighbor %s addpath-tx-bestpath-per-AS\n",
+ addr);
+ break;
+ case BGP_ADDPATH_BEST_SELECTED:
+ if (peer->addpath_best_selected[afi][safi])
+ vty_out(vty,
+ " neighbor %s addpath-tx-best-selected %u\n",
+ addr,
+ peer->addpath_best_selected[afi][safi]);
+ break;
+ case BGP_ADDPATH_MAX:
+ case BGP_ADDPATH_NONE:
+ break;
+ }
+ }
+
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DISABLE_ADDPATH_RX))
+ vty_out(vty, " neighbor %s disable-addpath-rx\n", addr);
+
+ /* ORF capability. */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
+ || peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM)) {
+ vty_out(vty, " neighbor %s capability orf prefix-list", addr);
+
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM)
+ && peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ORF_PREFIX_RM))
+ vty_out(vty, " both");
+ else if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ORF_PREFIX_SM))
+ vty_out(vty, " send");
+ else
+ vty_out(vty, " receive");
+ vty_out(vty, "\n");
+ }
+
+ /* Route reflector client. */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_REFLECTOR_CLIENT)) {
+ vty_out(vty, " neighbor %s route-reflector-client\n", addr);
+ }
+
+ /* next-hop-self force */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_FORCE_NEXTHOP_SELF)) {
+ vty_out(vty, " neighbor %s next-hop-self force\n", addr);
+ }
+
+ /* next-hop-self */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
+ vty_out(vty, " neighbor %s next-hop-self\n", addr);
+ }
+
+ /* remove-private-AS */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
+ vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
+ addr);
+ }
+
+ else if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
+ vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
+ addr);
+ }
+
+ else if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
+ vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
+ }
+
+ else if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_REMOVE_PRIVATE_AS)) {
+ vty_out(vty, " neighbor %s remove-private-AS\n", addr);
+ }
+
+ /* as-override */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
+ vty_out(vty, " neighbor %s as-override\n", addr);
+ }
+
+ /* send-community print. */
+ flag_scomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY);
+ flag_secomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ flag_slcomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ if (flag_scomm && flag_secomm && flag_slcomm) {
+ vty_out(vty, " no neighbor %s send-community all\n", addr);
+ } else {
+ if (flag_scomm)
+ vty_out(vty, " no neighbor %s send-community\n", addr);
+ if (flag_secomm)
+ vty_out(vty,
+ " no neighbor %s send-community extended\n",
+ addr);
+
+ if (flag_slcomm)
+ vty_out(vty, " no neighbor %s send-community large\n",
+ addr);
+ }
+
+ /* Default information */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_DEFAULT_ORIGINATE)) {
+ vty_out(vty, " neighbor %s default-originate", addr);
+
+ if (peer->default_rmap[afi][safi].name)
+ vty_out(vty, " route-map %s",
+ peer->default_rmap[afi][safi].name);
+
+ vty_out(vty, "\n");
+ }
+
+ /* Soft reconfiguration inbound. */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
+ vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
+ addr);
+ }
+
+ /* maximum-prefix. */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX)) {
+ vty_out(vty, " neighbor %s maximum-prefix %u", addr,
+ peer->pmax[afi][safi]);
+
+ if (peer->pmax_threshold[afi][safi]
+ != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
+ vty_out(vty, " %u", peer->pmax_threshold[afi][safi]);
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_MAX_PREFIX_WARNING))
+ vty_out(vty, " warning-only");
+ if (peer->pmax_restart[afi][safi])
+ vty_out(vty, " restart %u",
+ peer->pmax_restart[afi][safi]);
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_MAX_PREFIX_FORCE))
+ vty_out(vty, " force");
+
+ vty_out(vty, "\n");
+ }
+
+ /* maximum-prefix-out */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT))
+ vty_out(vty, " neighbor %s maximum-prefix-out %u\n",
+ addr, peer->pmax_out[afi][safi]);
+
+ /* Route server client. */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_RSERVER_CLIENT)) {
+ vty_out(vty, " neighbor %s route-server-client\n", addr);
+ }
+
+ /* Nexthop-local unchanged. */
+ if (peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
+ vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
+ }
+
+ /* allowas-in <1-10> */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
+ vty_out(vty, " neighbor %s allowas-in origin\n", addr);
+ } else if (peer->allowas_in[afi][safi] == 3) {
+ vty_out(vty, " neighbor %s allowas-in\n", addr);
+ } else {
+ vty_out(vty, " neighbor %s allowas-in %d\n", addr,
+ peer->allowas_in[afi][safi]);
+ }
+ }
+
+ /* accept-own */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ACCEPT_OWN))
+ vty_out(vty, " neighbor %s accept-own\n", addr);
+
+ /* soo */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOO)) {
+ char *soo_str = ecommunity_ecom2str(
+ peer->soo[afi][safi], ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+
+ vty_out(vty, " neighbor %s soo %s\n", addr, soo_str);
+ XFREE(MTYPE_ECOMMUNITY_STR, soo_str);
+ }
+
+ /* weight */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
+ vty_out(vty, " neighbor %s weight %lu\n", addr,
+ peer->weight[afi][safi]);
+
+ /* Filter. */
+ bgp_config_write_filter(vty, peer, afi, safi);
+
+ /* atribute-unchanged. */
+ if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
+ || (safi != SAFI_EVPN
+ && peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED))
+ || peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
+
+ if (!peer_group_active(peer)
+ || peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED)
+ || peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)
+ || peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_MED_UNCHANGED)) {
+
+ vty_out(vty,
+ " neighbor %s attribute-unchanged%s%s%s\n",
+ addr,
+ peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_AS_PATH_UNCHANGED)
+ ? " as-path"
+ : "",
+ peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)
+ ? " next-hop"
+ : "",
+ peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_MED_UNCHANGED)
+ ? " med"
+ : "");
+ }
+ }
+}
+
+static void bgp_vpn_config_write(struct vty *vty, struct bgp *bgp, afi_t afi,
+ safi_t safi)
+{
+ if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
+ vty_out(vty, " no bgp retain route-target all\n");
+}
+
+/* Address family based peer configuration display. */
+static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
+ safi_t safi)
+{
+ struct peer *peer;
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+
+
+ vty_frame(vty, " !\n address-family ");
+ if (afi == AFI_IP) {
+ if (safi == SAFI_UNICAST)
+ vty_frame(vty, "ipv4 unicast");
+ else if (safi == SAFI_LABELED_UNICAST)
+ vty_frame(vty, "ipv4 labeled-unicast");
+ else if (safi == SAFI_MULTICAST)
+ vty_frame(vty, "ipv4 multicast");
+ else if (safi == SAFI_MPLS_VPN)
+ vty_frame(vty, "ipv4 vpn");
+ else if (safi == SAFI_ENCAP)
+ vty_frame(vty, "ipv4 encap");
+ else if (safi == SAFI_FLOWSPEC)
+ vty_frame(vty, "ipv4 flowspec");
+ } else if (afi == AFI_IP6) {
+ if (safi == SAFI_UNICAST)
+ vty_frame(vty, "ipv6 unicast");
+ else if (safi == SAFI_LABELED_UNICAST)
+ vty_frame(vty, "ipv6 labeled-unicast");
+ else if (safi == SAFI_MULTICAST)
+ vty_frame(vty, "ipv6 multicast");
+ else if (safi == SAFI_MPLS_VPN)
+ vty_frame(vty, "ipv6 vpn");
+ else if (safi == SAFI_ENCAP)
+ vty_frame(vty, "ipv6 encap");
+ else if (safi == SAFI_FLOWSPEC)
+ vty_frame(vty, "ipv6 flowspec");
+ } else if (afi == AFI_L2VPN) {
+ if (safi == SAFI_EVPN)
+ vty_frame(vty, "l2vpn evpn");
+ }
+ vty_frame(vty, "\n");
+
+ bgp_config_write_distance(vty, bgp, afi, safi);
+
+ bgp_config_write_network(vty, bgp, afi, safi);
+
+ bgp_config_write_redistribute(vty, bgp, afi, safi);
+
+ /* BGP flag dampening. */
+ if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
+ bgp_config_write_damp(vty, afi, safi);
+
+ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
+ bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ /* Do not display doppelganger peers */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
+ }
+
+ bgp_config_write_maxpaths(vty, bgp, afi, safi);
+ bgp_config_write_table_map(vty, bgp, afi, safi);
+
+ if (safi == SAFI_EVPN)
+ bgp_config_write_evpn_info(vty, bgp, afi, safi);
+
+ if (safi == SAFI_FLOWSPEC)
+ bgp_fs_config_write_pbr(vty, bgp, afi, safi);
+
+ if (safi == SAFI_MPLS_VPN)
+ bgp_vpn_config_write(vty, bgp, afi, safi);
+
+ if (safi == SAFI_UNICAST) {
+ bgp_vpn_policy_config_write_afi(vty, bgp, afi);
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
+
+ vty_out(vty, " export vpn\n");
+ }
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
+
+ vty_out(vty, " import vpn\n");
+ }
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].import_vrf, node,
+ name))
+ vty_out(vty, " import vrf %s\n", name);
+ }
+ }
+
+ vty_endframe(vty, " exit-address-family\n");
+}
+
+int bgp_config_write(struct vty *vty)
+{
+ struct bgp *bgp;
+ struct peer_group *group;
+ struct peer *peer;
+ struct listnode *node, *nnode;
+ struct listnode *mnode, *mnnode;
+ afi_t afi;
+ safi_t safi;
+ uint32_t tovpn_sid_index = 0;
+
+ if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
+ vty_out(vty, "bgp route-map delay-timer %u\n",
+ bm->rmap_update_timer);
+
+ if (bm->v_update_delay != BGP_UPDATE_DELAY_DEF) {
+ vty_out(vty, "bgp update-delay %d", bm->v_update_delay);
+ if (bm->v_update_delay != bm->v_establish_wait)
+ vty_out(vty, " %d", bm->v_establish_wait);
+ vty_out(vty, "\n");
+ }
+
+ if (bm->wait_for_fib)
+ vty_out(vty, "bgp suppress-fib-pending\n");
+
+ if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+ vty_out(vty, "bgp graceful-shutdown\n");
+
+ /* No-RIB (Zebra) option flag configuration */
+ if (bgp_option_check(BGP_OPT_NO_FIB))
+ vty_out(vty, "bgp no-rib\n");
+
+ if (CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA))
+ vty_out(vty, "bgp send-extra-data zebra\n");
+
+ /* BGP session DSCP value */
+ if (bm->tcp_dscp != IPTOS_PREC_INTERNETCONTROL)
+ vty_out(vty, "bgp session-dscp %u\n", bm->tcp_dscp >> 2);
+
+ /* BGP InQ limit */
+ if (bm->inq_limit != BM_DEFAULT_Q_LIMIT)
+ vty_out(vty, "bgp input-queue-limit %u\n", bm->inq_limit);
+
+ if (bm->outq_limit != BM_DEFAULT_Q_LIMIT)
+ vty_out(vty, "bgp output-queue-limit %u\n", bm->outq_limit);
+
+ /* BGP configuration. */
+ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
+
+ /* skip all auto created vrf as they dont have user config */
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
+ /* Router bgp ASN */
+ vty_out(vty, "router bgp %s", bgp->as_pretty);
+
+ if (bgp->name)
+ vty_out(vty, " %s %s",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+ ? "view" : "vrf", bgp->name);
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION))
+ vty_out(vty, " as-notation %s",
+ asn_mode2str(bgp->asnotation));
+
+ vty_out(vty, "\n");
+
+ /* BGP fast-external-failover. */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
+ vty_out(vty, " no bgp fast-external-failover\n");
+
+ /* BGP router ID. */
+ if (bgp->router_id_static.s_addr != INADDR_ANY)
+ vty_out(vty, " bgp router-id %pI4\n",
+ &bgp->router_id_static);
+
+ /* Suppress fib pending */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING))
+ vty_out(vty, " bgp suppress-fib-pending\n");
+
+ /* BGP log-neighbor-changes. */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
+ != SAVE_BGP_LOG_NEIGHBOR_CHANGES)
+ vty_out(vty, " %sbgp log-neighbor-changes\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_LOG_NEIGHBOR_CHANGES)
+ ? ""
+ : "no ");
+
+ /* BGP configuration. */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED))
+ vty_out(vty, " bgp always-compare-med\n");
+
+ /* RFC8212 default eBGP policy. */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY)
+ != SAVE_BGP_EBGP_REQUIRES_POLICY)
+ vty_out(vty, " %sbgp ebgp-requires-policy\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_EBGP_REQUIRES_POLICY)
+ ? ""
+ : "no ");
+
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
+ !!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL))
+ vty_out(vty, " bgp labeled-unicast explicit-null\n");
+ else if (!!CHECK_FLAG(bgp->flags,
+ BGP_FLAG_LU_IPV4_EXPLICIT_NULL))
+ vty_out(vty,
+ " bgp labeled-unicast ipv4-explicit-null\n");
+ else if (!!CHECK_FLAG(bgp->flags,
+ BGP_FLAG_LU_IPV6_EXPLICIT_NULL))
+ vty_out(vty,
+ " bgp labeled-unicast ipv6-explicit-null\n");
+
+ /* draft-ietf-idr-deprecate-as-set-confed-set */
+ if (bgp->reject_as_sets)
+ vty_out(vty, " bgp reject-as-sets\n");
+
+ /* Suppress duplicate updates if the route actually not changed
+ */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)
+ != SAVE_BGP_SUPPRESS_DUPLICATES)
+ vty_out(vty, " %sbgp suppress-duplicates\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_SUPPRESS_DUPLICATES)
+ ? ""
+ : "no ");
+
+ /* Send Hard Reset CEASE Notification for 'Administrative Reset'
+ */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_HARD_ADMIN_RESET) !=
+ SAVE_BGP_HARD_ADMIN_RESET)
+ vty_out(vty, " %sbgp hard-administrative-reset\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_HARD_ADMIN_RESET)
+ ? ""
+ : "no ");
+
+ /* BGP default <afi>-<safi> */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (afi == AFI_IP && safi == SAFI_UNICAST) {
+ if (!bgp->default_af[afi][safi])
+ vty_out(vty, " no bgp default %s\n",
+ get_bgp_default_af_flag(afi,
+ safi));
+ } else if (bgp->default_af[afi][safi])
+ vty_out(vty, " bgp default %s\n",
+ get_bgp_default_af_flag(afi, safi));
+ }
+
+ /* BGP default local-preference. */
+ if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
+ vty_out(vty, " bgp default local-preference %u\n",
+ bgp->default_local_pref);
+
+ /* BGP default show-hostname */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
+ != SAVE_BGP_SHOW_HOSTNAME)
+ vty_out(vty, " %sbgp default show-hostname\n",
+ CHECK_FLAG(bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
+ ? ""
+ : "no ");
+
+ /* BGP default show-nexthop-hostname */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME)
+ != SAVE_BGP_SHOW_HOSTNAME)
+ vty_out(vty, " %sbgp default show-nexthop-hostname\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_SHOW_NEXTHOP_HOSTNAME)
+ ? ""
+ : "no ");
+
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY) !=
+ SAVE_BGP_SOFT_VERSION_CAPABILITY)
+ vty_out(vty,
+ " %sbgp default software-version-capability\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_SOFT_VERSION_CAPABILITY)
+ ? ""
+ : "no ");
+
+ /* BGP default subgroup-pkt-queue-max. */
+ if (bgp->default_subgroup_pkt_queue_max
+ != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
+ vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
+ bgp->default_subgroup_pkt_queue_max);
+
+ /* BGP client-to-client reflection. */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_CLIENT_TO_CLIENT))
+ vty_out(vty, " no bgp client-to-client reflection\n");
+
+ /* BGP cluster ID. */
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
+ vty_out(vty, " bgp cluster-id %pI4\n",
+ &bgp->cluster_id);
+
+ /* Disable ebgp connected nexthop check */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+ vty_out(vty,
+ " bgp disable-ebgp-connected-route-check\n");
+
+ /* Confederation identifier*/
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+ vty_out(vty, " bgp confederation identifier %s\n",
+ bgp->confed_id_pretty);
+
+ /* Confederation peer */
+ if (bgp->confed_peers_cnt > 0) {
+ int i;
+
+ vty_out(vty, " bgp confederation peers");
+
+ for (i = 0; i < bgp->confed_peers_cnt; i++)
+ vty_out(vty, " %s",
+ bgp->confed_peers[i].as_pretty);
+
+ vty_out(vty, "\n");
+ }
+
+ /* BGP deterministic-med. */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
+ != SAVE_BGP_DETERMINISTIC_MED)
+ vty_out(vty, " %sbgp deterministic-med\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DETERMINISTIC_MED)
+ ? ""
+ : "no ");
+
+ /* BGP update-delay. */
+ bgp_config_write_update_delay(vty, bgp);
+
+ if (bgp->v_maxmed_onstartup
+ != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) {
+ vty_out(vty, " bgp max-med on-startup %u",
+ bgp->v_maxmed_onstartup);
+ if (bgp->maxmed_onstartup_value
+ != BGP_MAXMED_VALUE_DEFAULT)
+ vty_out(vty, " %u",
+ bgp->maxmed_onstartup_value);
+ vty_out(vty, "\n");
+ }
+ if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) {
+ vty_out(vty, " bgp max-med administrative");
+ if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
+ vty_out(vty, " %u", bgp->maxmed_admin_value);
+ vty_out(vty, "\n");
+ }
+
+ /* write quanta */
+ bgp_config_write_wpkt_quanta(vty, bgp);
+ /* read quanta */
+ bgp_config_write_rpkt_quanta(vty, bgp);
+
+ /* coalesce time */
+ bgp_config_write_coalesce_time(vty, bgp);
+
+ /* BGP per-instance graceful-shutdown */
+ /* BGP-wide settings and per-instance settings are mutually
+ * exclusive.
+ */
+ if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ vty_out(vty, " bgp graceful-shutdown\n");
+
+ /* Long-lived Graceful Restart */
+ if (bgp->llgr_stale_time != BGP_DEFAULT_LLGR_STALE_TIME)
+ vty_out(vty,
+ " bgp long-lived-graceful-restart stale-time %u\n",
+ bgp->llgr_stale_time);
+
+ /* BGP graceful-restart. */
+ if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
+ vty_out(vty,
+ " bgp graceful-restart stalepath-time %u\n",
+ bgp->stalepath_time);
+
+ if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
+ vty_out(vty, " bgp graceful-restart restart-time %u\n",
+ bgp->restart_time);
+
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION) !=
+ SAVE_BGP_GRACEFUL_NOTIFICATION)
+ vty_out(vty, " %sbgp graceful-restart notification\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_GRACEFUL_NOTIFICATION)
+ ? ""
+ : "no ");
+
+ if (bgp->select_defer_time != BGP_DEFAULT_SELECT_DEFERRAL_TIME)
+ vty_out(vty,
+ " bgp graceful-restart select-defer-time %u\n",
+ bgp->select_defer_time);
+
+ if (bgp_global_gr_mode_get(bgp) == GLOBAL_GR)
+ vty_out(vty, " bgp graceful-restart\n");
+
+ if (bgp_global_gr_mode_get(bgp) == GLOBAL_DISABLE)
+ vty_out(vty, " bgp graceful-restart-disable\n");
+
+ /* BGP graceful-restart Preserve State F bit. */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD))
+ vty_out(vty,
+ " bgp graceful-restart preserve-fw-state\n");
+
+ /* BGP TCP keepalive */
+ bgp_config_tcp_keepalive(vty, bgp);
+
+ /* Stale timer for RIB */
+ if (bgp->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
+ vty_out(vty,
+ " bgp graceful-restart rib-stale-time %u\n",
+ bgp->rib_stale_time);
+
+ /* BGP bestpath method. */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE))
+ vty_out(vty, " bgp bestpath as-path ignore\n");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED))
+ vty_out(vty, " bgp bestpath as-path confed\n");
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
+ vty_out(vty,
+ " bgp bestpath as-path multipath-relax as-set\n");
+ } else {
+ vty_out(vty,
+ " bgp bestpath as-path multipath-relax\n");
+ }
+ }
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
+ vty_out(vty,
+ " bgp route-reflector allow-outbound-policy\n");
+ }
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID))
+ vty_out(vty, " bgp bestpath compare-routerid\n");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP))
+ vty_out(vty, " bgp bestpath aigp\n");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED)
+ || CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST)) {
+ vty_out(vty, " bgp bestpath med");
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED))
+ vty_out(vty, " confed");
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_MED_MISSING_AS_WORST))
+ vty_out(vty, " missing-as-worst");
+ vty_out(vty, "\n");
+ }
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
+ vty_out(vty,
+ " bgp bestpath peer-type multipath-relax\n");
+
+ /* Link bandwidth handling. */
+ if (bgp->lb_handling == BGP_LINK_BW_IGNORE_BW)
+ vty_out(vty, " bgp bestpath bandwidth ignore\n");
+ else if (bgp->lb_handling == BGP_LINK_BW_SKIP_MISSING)
+ vty_out(vty, " bgp bestpath bandwidth skip-missing\n");
+ else if (bgp->lb_handling == BGP_LINK_BW_DEFWT_4_MISSING)
+ vty_out(vty, " bgp bestpath bandwidth default-weight-for-missing\n");
+
+ /* BGP network import check. */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
+ != SAVE_BGP_IMPORT_CHECK)
+ vty_out(vty, " %sbgp network import-check\n",
+ CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
+ ? ""
+ : "no ");
+
+ /* BGP timers configuration. */
+ if (bgp->default_keepalive != SAVE_BGP_KEEPALIVE
+ || bgp->default_holdtime != SAVE_BGP_HOLDTIME)
+ vty_out(vty, " timers bgp %u %u\n",
+ bgp->default_keepalive, bgp->default_holdtime);
+
+ /* BGP minimum holdtime configuration. */
+ if (bgp->default_min_holdtime != SAVE_BGP_HOLDTIME
+ && bgp->default_min_holdtime != 0)
+ vty_out(vty, " bgp minimum-holdtime %u\n",
+ bgp->default_min_holdtime);
+
+ /* Conditional advertisement timer configuration */
+ if (bgp->condition_check_period
+ != DEFAULT_CONDITIONAL_ROUTES_POLL_TIME)
+ vty_out(vty,
+ " bgp conditional-advertisement timer %u\n",
+ bgp->condition_check_period);
+
+ /* default-originate timer configuration */
+ if (bgp->rmap_def_originate_eval_timer !=
+ RMAP_DEFAULT_ORIGINATE_EVAL_TIMER)
+ vty_out(vty, " bgp default-originate timer %u\n",
+ bgp->rmap_def_originate_eval_timer);
+
+ /* peer-group */
+ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
+ bgp_config_write_peer_global(vty, bgp, group->conf);
+ }
+
+ /* Normal neighbor configuration. */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ bgp_config_write_peer_global(vty, bgp, peer);
+ }
+
+ /* listen range and limit for dynamic BGP neighbors */
+ bgp_config_write_listen(vty, bgp);
+
+ /*
+ * BGP default autoshutdown neighbors
+ *
+ * This must be placed after any peer and peer-group
+ * configuration, to avoid setting all peers to shutdown after
+ * a daemon restart, which is undesired behavior. (see #2286)
+ */
+ if (bgp->autoshutdown)
+ vty_out(vty, " bgp default shutdown\n");
+
+ /* BGP instance administrative shutdown */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
+ vty_out(vty, " bgp shutdown\n");
+
+ if (bgp->allow_martian)
+ vty_out(vty, " bgp allow-martian-nexthop\n");
+
+ if (bgp->fast_convergence)
+ vty_out(vty, " bgp fast-convergence\n");
+
+ if (bgp->srv6_enabled) {
+ vty_frame(vty, " !\n segment-routing srv6\n");
+ if (strlen(bgp->srv6_locator_name))
+ vty_out(vty, " locator %s\n",
+ bgp->srv6_locator_name);
+ vty_endframe(vty, " exit\n");
+ }
+
+ tovpn_sid_index = bgp->tovpn_sid_index;
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_TOVPN_SID_AUTO)) {
+ vty_out(vty, " sid vpn per-vrf export auto\n");
+ } else if (tovpn_sid_index != 0) {
+ vty_out(vty, " sid vpn per-vrf export %d\n",
+ tovpn_sid_index);
+ }
+
+ /* IPv4 unicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
+
+ /* IPv4 multicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
+
+ /* IPv4 labeled-unicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
+
+ /* IPv4 VPN configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
+
+ /* ENCAPv4 configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
+
+ /* FLOWSPEC v4 configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_FLOWSPEC);
+
+ /* IPv6 unicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
+
+ /* IPv6 multicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
+
+ /* IPv6 labeled-unicast configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6,
+ SAFI_LABELED_UNICAST);
+
+ /* IPv6 VPN configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
+
+ /* ENCAPv6 configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
+
+ /* FLOWSPEC v6 configuration. */
+ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_FLOWSPEC);
+
+ /* EVPN configuration. */
+ bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
+
+ hook_call(bgp_inst_config_write, bgp, vty);
+
+#ifdef ENABLE_BGP_VNC
+ bgp_rfapi_cfg_write(vty, bgp);
+#endif
+
+ vty_out(vty, "exit\n");
+ vty_out(vty, "!\n");
+ }
+ return 0;
+}
+
+
+/* BGP node structure. */
+static struct cmd_node bgp_node = {
+ .name = "bgp",
+ .node = BGP_NODE,
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(config-router)# ",
+ .config_write = bgp_config_write,
+};
+
+static struct cmd_node bgp_ipv4_unicast_node = {
+ .name = "bgp ipv4 unicast",
+ .node = BGP_IPV4_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_ipv4_multicast_node = {
+ .name = "bgp ipv4 multicast",
+ .node = BGP_IPV4M_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_ipv4_labeled_unicast_node = {
+ .name = "bgp ipv4 labeled unicast",
+ .node = BGP_IPV4L_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_ipv6_unicast_node = {
+ .name = "bgp ipv6 unicast",
+ .node = BGP_IPV6_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_ipv6_multicast_node = {
+ .name = "bgp ipv6 multicast",
+ .node = BGP_IPV6M_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_ipv6_labeled_unicast_node = {
+ .name = "bgp ipv6 labeled unicast",
+ .node = BGP_IPV6L_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_vpnv4_node = {
+ .name = "bgp vpnv4",
+ .node = BGP_VPNV4_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_vpnv6_node = {
+ .name = "bgp vpnv6",
+ .node = BGP_VPNV6_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af-vpnv6)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_evpn_node = {
+ .name = "bgp evpn",
+ .node = BGP_EVPN_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-evpn)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_evpn_vni_node = {
+ .name = "bgp evpn vni",
+ .node = BGP_EVPN_VNI_NODE,
+ .parent_node = BGP_EVPN_NODE,
+ .prompt = "%s(config-router-af-vni)# ",
+};
+
+static struct cmd_node bgp_flowspecv4_node = {
+ .name = "bgp ipv4 flowspec",
+ .node = BGP_FLOWSPECV4_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_flowspecv6_node = {
+ .name = "bgp ipv6 flowspec",
+ .node = BGP_FLOWSPECV6_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-af-vpnv6)# ",
+ .no_xpath = true,
+};
+
+static struct cmd_node bgp_srv6_node = {
+ .name = "bgp srv6",
+ .node = BGP_SRV6_NODE,
+ .parent_node = BGP_NODE,
+ .prompt = "%s(config-router-srv6)# ",
+};
+
+static void community_list_vty(void);
+
+static void bgp_ac_peergroup(vector comps, struct cmd_token *token)
+{
+ struct bgp *bgp;
+ struct peer_group *group;
+ struct listnode *lnbgp, *lnpeer;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
+ for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group))
+ vector_set(comps,
+ XSTRDUP(MTYPE_COMPLETION, group->name));
+ }
+}
+
+static void bgp_ac_peer(vector comps, struct cmd_token *token)
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ struct listnode *lnbgp, *lnpeer;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, lnpeer, peer)) {
+ /* only provide suggestions on the appropriate input
+ * token type,
+ * they'll otherwise show up multiple times */
+ enum cmd_token_type match_type;
+ char *name = peer->host;
+
+ if (peer->conf_if) {
+ match_type = VARIABLE_TKN;
+ name = peer->conf_if;
+ } else if (strchr(peer->host, ':'))
+ match_type = IPV6_TKN;
+ else
+ match_type = IPV4_TKN;
+
+ if (token->type != match_type)
+ continue;
+
+ vector_set(comps, XSTRDUP(MTYPE_COMPLETION, name));
+ }
+ }
+}
+
+static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
+{
+ bgp_ac_peer(comps, token);
+
+ if (token->type == VARIABLE_TKN)
+ bgp_ac_peergroup(comps, token);
+}
+
+static const struct cmd_variable_handler bgp_var_neighbor[] = {
+ {.varname = "neighbor", .completions = bgp_ac_neighbor},
+ {.varname = "neighbors", .completions = bgp_ac_neighbor},
+ {.varname = "peer", .completions = bgp_ac_neighbor},
+ {.completions = NULL}};
+
+static const struct cmd_variable_handler bgp_var_peergroup[] = {
+ {.tokenname = "PGNAME", .completions = bgp_ac_peergroup},
+ {.completions = NULL} };
+
+DEFINE_HOOK(bgp_config_end, (struct bgp *bgp), (bgp));
+
+static struct event *t_bgp_cfg;
+
+bool bgp_config_inprocess(void)
+{
+ return event_is_scheduled(t_bgp_cfg);
+}
+
+/* Max wait time for config to load before post-config processing */
+#define BGP_PRE_CONFIG_MAX_WAIT_SECONDS 600
+
+static void bgp_config_finish(struct event *t)
+{
+ struct listnode *node;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp))
+ hook_call(bgp_config_end, bgp);
+}
+
+static void bgp_config_end_timeout(struct event *t)
+{
+ zlog_err("BGP configuration end timer expired after %d seconds.",
+ BGP_PRE_CONFIG_MAX_WAIT_SECONDS);
+ bgp_config_finish(t);
+}
+
+static void bgp_config_start(void)
+{
+ EVENT_OFF(t_bgp_cfg);
+ event_add_timer(bm->master, bgp_config_end_timeout, NULL,
+ BGP_PRE_CONFIG_MAX_WAIT_SECONDS, &t_bgp_cfg);
+}
+
+/* When we receive a hook the configuration is read,
+ * we start a timer to make sure we postpone sending
+ * EoR before route-maps are processed.
+ * This is especially valid if using `bgp route-map delay-timer`.
+ */
+static void bgp_config_end(void)
+{
+#define BGP_POST_CONFIG_DELAY_SECONDS 1
+ uint32_t bgp_post_config_delay =
+ event_is_scheduled(bm->t_rmap_update)
+ ? event_timer_remain_second(bm->t_rmap_update)
+ : BGP_POST_CONFIG_DELAY_SECONDS;
+
+ /* If BGP config processing thread isn't running, then
+ * we can return and rely it's properly handled.
+ */
+ if (!bgp_config_inprocess())
+ return;
+
+ EVENT_OFF(t_bgp_cfg);
+
+ /* Start a new timer to make sure we don't send EoR
+ * before route-maps are processed.
+ */
+ event_add_timer(bm->master, bgp_config_finish, NULL,
+ bgp_post_config_delay, &t_bgp_cfg);
+}
+
+static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
+{
+ int write = 0;
+ struct interface *ifp;
+ struct bgp_interface *iifp;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ iifp = ifp->info;
+ if (!iifp)
+ continue;
+
+ if_vty_config_start(vty, ifp);
+
+ if (CHECK_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING)) {
+ vty_out(vty, " mpls bgp forwarding\n");
+ write++;
+ }
+ if (CHECK_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_L3VPN_SWITCHING)) {
+ vty_out(vty,
+ " mpls bgp l3vpn-multi-domain-switching\n");
+ write++;
+ }
+
+ if_vty_config_end(vty);
+ }
+
+ return write;
+}
+
+/* Configuration write function for bgpd. */
+static int config_write_interface(struct vty *vty)
+{
+ int write = 0;
+ struct vrf *vrf = NULL;
+
+ /* Display all VRF aware OSPF interface configuration */
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ write += config_write_interface_one(vty, vrf);
+ }
+
+ return write;
+}
+
+DEFPY(mpls_bgp_forwarding, mpls_bgp_forwarding_cmd,
+ "[no$no] mpls bgp forwarding",
+ NO_STR MPLS_STR BGP_STR
+ "Enable MPLS forwarding for eBGP directly connected peers\n")
+{
+ bool check;
+ struct bgp_interface *iifp;
+
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ iifp = ifp->info;
+ if (!iifp) {
+ vty_out(vty, "Interface %s not available\n", ifp->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ check = CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ if (check != !no) {
+ if (no)
+ UNSET_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ else
+ SET_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ /* trigger a nht update on eBGP sessions */
+ if (if_is_operative(ifp))
+ bgp_nht_ifp_up(ifp);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY(mpls_bgp_l3vpn_multi_domain_switching,
+ mpls_bgp_l3vpn_multi_domain_switching_cmd,
+ "[no$no] mpls bgp l3vpn-multi-domain-switching",
+ NO_STR MPLS_STR BGP_STR
+ "Bind a local MPLS label to incoming L3VPN updates\n")
+{
+ bool check;
+ struct bgp_interface *iifp;
+
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ iifp = ifp->info;
+ if (!iifp) {
+ vty_out(vty, "Interface %s not available\n", ifp->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ check = CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_L3VPN_SWITCHING);
+ if (check == !no)
+ return CMD_SUCCESS;
+ if (no)
+ UNSET_FLAG(iifp->flags, BGP_INTERFACE_MPLS_L3VPN_SWITCHING);
+ else
+ SET_FLAG(iifp->flags, BGP_INTERFACE_MPLS_L3VPN_SWITCHING);
+ /* trigger a nht update on eBGP sessions */
+ if (if_is_operative(ifp))
+ bgp_nht_ifp_up(ifp);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_inq_limit,
+ bgp_inq_limit_cmd,
+ "bgp input-queue-limit (1-4294967295)$limit",
+ BGP_STR
+ "Set the BGP Input Queue limit for all peers when message parsing\n"
+ "Input-Queue limit\n")
+{
+ bm->inq_limit = limit;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_inq_limit,
+ no_bgp_inq_limit_cmd,
+ "no bgp input-queue-limit [(1-4294967295)$limit]",
+ NO_STR
+ BGP_STR
+ "Set the BGP Input Queue limit for all peers when message parsing\n"
+ "Input-Queue limit\n")
+{
+ bm->inq_limit = BM_DEFAULT_Q_LIMIT;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_outq_limit,
+ bgp_outq_limit_cmd,
+ "bgp output-queue-limit (1-4294967295)$limit",
+ BGP_STR
+ "Set the BGP Output Queue limit for all peers when message parsing\n"
+ "Output-Queue limit\n")
+{
+ bm->outq_limit = limit;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_outq_limit,
+ no_bgp_outq_limit_cmd,
+ "no bgp output-queue-limit [(1-4294967295)$limit]",
+ NO_STR
+ BGP_STR
+ "Set the BGP Output Queue limit for all peers when message parsing\n"
+ "Output-Queue limit\n")
+{
+ bm->outq_limit = BM_DEFAULT_Q_LIMIT;
+
+ return CMD_SUCCESS;
+}
+
+
+/* Initialization of BGP interface. */
+static void bgp_vty_if_init(void)
+{
+ /* Install interface node. */
+ if_cmd_init(config_write_interface);
+
+ /* "mpls bgp forwarding" commands. */
+ install_element(INTERFACE_NODE, &mpls_bgp_forwarding_cmd);
+ install_element(INTERFACE_NODE,
+ &mpls_bgp_l3vpn_multi_domain_switching_cmd);
+}
+
+void bgp_vty_init(void)
+{
+ cmd_variable_handler_register(bgp_var_neighbor);
+ cmd_variable_handler_register(bgp_var_peergroup);
+
+ cmd_init_config_callbacks(bgp_config_start, bgp_config_end);
+
+ /* Install bgp top node. */
+ install_node(&bgp_node);
+ install_node(&bgp_ipv4_unicast_node);
+ install_node(&bgp_ipv4_multicast_node);
+ install_node(&bgp_ipv4_labeled_unicast_node);
+ install_node(&bgp_ipv6_unicast_node);
+ install_node(&bgp_ipv6_multicast_node);
+ install_node(&bgp_ipv6_labeled_unicast_node);
+ install_node(&bgp_vpnv4_node);
+ install_node(&bgp_vpnv6_node);
+ install_node(&bgp_evpn_node);
+ install_node(&bgp_evpn_vni_node);
+ install_node(&bgp_flowspecv4_node);
+ install_node(&bgp_flowspecv6_node);
+ install_node(&bgp_srv6_node);
+
+ /* Install default VTY commands to new nodes. */
+ install_default(BGP_NODE);
+ install_default(BGP_IPV4_NODE);
+ install_default(BGP_IPV4M_NODE);
+ install_default(BGP_IPV4L_NODE);
+ install_default(BGP_IPV6_NODE);
+ install_default(BGP_IPV6M_NODE);
+ install_default(BGP_IPV6L_NODE);
+ install_default(BGP_VPNV4_NODE);
+ install_default(BGP_VPNV6_NODE);
+ install_default(BGP_FLOWSPECV4_NODE);
+ install_default(BGP_FLOWSPECV6_NODE);
+ install_default(BGP_EVPN_NODE);
+ install_default(BGP_EVPN_VNI_NODE);
+ install_default(BGP_SRV6_NODE);
+
+ /* "global bgp inq-limit command */
+ install_element(CONFIG_NODE, &bgp_inq_limit_cmd);
+ install_element(CONFIG_NODE, &no_bgp_inq_limit_cmd);
+ install_element(CONFIG_NODE, &bgp_outq_limit_cmd);
+ install_element(CONFIG_NODE, &no_bgp_outq_limit_cmd);
+
+ /* "bgp local-mac" hidden commands. */
+ install_element(CONFIG_NODE, &bgp_local_mac_cmd);
+ install_element(CONFIG_NODE, &no_bgp_local_mac_cmd);
+
+ /* "bgp suppress-fib-pending" global */
+ install_element(CONFIG_NODE, &bgp_global_suppress_fib_pending_cmd);
+
+ /* bgp route-map delay-timer commands. */
+ install_element(CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd);
+ install_element(CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd);
+
+ install_element(BGP_NODE, &bgp_allow_martian_cmd);
+
+ /* bgp fast-convergence command */
+ install_element(BGP_NODE, &bgp_fast_convergence_cmd);
+ install_element(BGP_NODE, &no_bgp_fast_convergence_cmd);
+
+ /* global bgp update-delay command */
+ install_element(CONFIG_NODE, &bgp_global_update_delay_cmd);
+ install_element(CONFIG_NODE, &no_bgp_global_update_delay_cmd);
+
+ /* global bgp graceful-shutdown command */
+ install_element(CONFIG_NODE, &bgp_graceful_shutdown_cmd);
+ install_element(CONFIG_NODE, &no_bgp_graceful_shutdown_cmd);
+
+ /* Dummy commands (Currently not supported) */
+ install_element(BGP_NODE, &no_synchronization_cmd);
+ install_element(BGP_NODE, &no_auto_summary_cmd);
+
+ /* "router bgp" commands. */
+ install_element(CONFIG_NODE, &router_bgp_cmd);
+
+ /* "no router bgp" commands. */
+ install_element(CONFIG_NODE, &no_router_bgp_cmd);
+
+ /* "bgp session-dscp command */
+ install_element(CONFIG_NODE, &bgp_session_dscp_cmd);
+ install_element(CONFIG_NODE, &no_bgp_session_dscp_cmd);
+
+ /* "bgp router-id" commands. */
+ install_element(BGP_NODE, &bgp_router_id_cmd);
+ install_element(BGP_NODE, &no_bgp_router_id_cmd);
+
+ /* "bgp suppress-fib-pending" command */
+ install_element(BGP_NODE, &bgp_suppress_fib_pending_cmd);
+
+ /* "bgp cluster-id" commands. */
+ install_element(BGP_NODE, &bgp_cluster_id_cmd);
+ install_element(BGP_NODE, &no_bgp_cluster_id_cmd);
+
+ /* "bgp no-rib" commands. */
+ install_element(CONFIG_NODE, &bgp_norib_cmd);
+ install_element(CONFIG_NODE, &no_bgp_norib_cmd);
+
+ install_element(CONFIG_NODE, &no_bgp_send_extra_data_cmd);
+
+ /* "bgp confederation" commands. */
+ install_element(BGP_NODE, &bgp_confederation_identifier_cmd);
+ install_element(BGP_NODE, &no_bgp_confederation_identifier_cmd);
+
+ /* "bgp confederation peers" commands. */
+ install_element(BGP_NODE, &bgp_confederation_peers_cmd);
+ install_element(BGP_NODE, &no_bgp_confederation_peers_cmd);
+
+ /* bgp max-med command */
+ install_element(BGP_NODE, &bgp_maxmed_admin_cmd);
+ install_element(BGP_NODE, &no_bgp_maxmed_admin_cmd);
+ install_element(BGP_NODE, &bgp_maxmed_admin_medv_cmd);
+ install_element(BGP_NODE, &bgp_maxmed_onstartup_cmd);
+ install_element(BGP_NODE, &no_bgp_maxmed_onstartup_cmd);
+
+ /* "neighbor role" commands. */
+ install_element(BGP_NODE, &neighbor_role_cmd);
+ install_element(BGP_NODE, &neighbor_role_strict_cmd);
+ install_element(BGP_NODE, &no_neighbor_role_cmd);
+
+ /* "neighbor aigp" commands. */
+ install_element(BGP_NODE, &neighbor_aigp_cmd);
+
+ /* "neighbor graceful-shutdown" command */
+ install_element(BGP_NODE, &neighbor_graceful_shutdown_cmd);
+
+ /* bgp disable-ebgp-connected-nh-check */
+ install_element(BGP_NODE, &bgp_disable_connected_route_check_cmd);
+ install_element(BGP_NODE, &no_bgp_disable_connected_route_check_cmd);
+
+ /* bgp update-delay command */
+ install_element(BGP_NODE, &bgp_update_delay_cmd);
+ install_element(BGP_NODE, &no_bgp_update_delay_cmd);
+
+ install_element(BGP_NODE, &bgp_wpkt_quanta_cmd);
+ install_element(BGP_NODE, &bgp_rpkt_quanta_cmd);
+
+ install_element(BGP_NODE, &bgp_coalesce_time_cmd);
+ install_element(BGP_NODE, &no_bgp_coalesce_time_cmd);
+
+ /* "maximum-paths" commands. */
+ install_element(BGP_NODE, &bgp_maxpaths_hidden_cmd);
+ install_element(BGP_NODE, &no_bgp_maxpaths_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_maxpaths_cmd);
+ install_element(BGP_IPV4_NODE, &no_bgp_maxpaths_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_maxpaths_cmd);
+ install_element(BGP_IPV6_NODE, &no_bgp_maxpaths_cmd);
+ install_element(BGP_NODE, &bgp_maxpaths_ibgp_hidden_cmd);
+ install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_hidden_cmd);
+ install_element(BGP_NODE, &no_bgp_maxpaths_ibgp_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
+ install_element(BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
+ install_element(BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
+
+ install_element(BGP_IPV4L_NODE, &bgp_maxpaths_cmd);
+ install_element(BGP_IPV4L_NODE, &no_bgp_maxpaths_cmd);
+ install_element(BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
+ install_element(BGP_IPV4L_NODE, &no_bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6L_NODE, &bgp_maxpaths_cmd);
+ install_element(BGP_IPV6L_NODE, &no_bgp_maxpaths_cmd);
+ install_element(BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
+ install_element(BGP_IPV6L_NODE, &no_bgp_maxpaths_ibgp_cmd);
+
+ /* "timers bgp" commands. */
+ install_element(BGP_NODE, &bgp_timers_cmd);
+ install_element(BGP_NODE, &no_bgp_timers_cmd);
+
+ /* "minimum-holdtime" commands. */
+ install_element(BGP_NODE, &bgp_minimum_holdtime_cmd);
+ install_element(BGP_NODE, &no_bgp_minimum_holdtime_cmd);
+
+ /* route-map delay-timer commands - per instance for backwards compat.
+ */
+ install_element(BGP_NODE, &bgp_set_route_map_delay_timer_cmd);
+ install_element(BGP_NODE, &no_bgp_set_route_map_delay_timer_cmd);
+
+ /* "bgp client-to-client reflection" commands */
+ install_element(BGP_NODE, &no_bgp_client_to_client_reflection_cmd);
+ install_element(BGP_NODE, &bgp_client_to_client_reflection_cmd);
+
+ /* "bgp always-compare-med" commands */
+ install_element(BGP_NODE, &bgp_always_compare_med_cmd);
+ install_element(BGP_NODE, &no_bgp_always_compare_med_cmd);
+
+ /* bgp ebgp-requires-policy */
+ install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);
+ install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd);
+
+ /* bgp labeled-unicast explicit-null */
+ install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd);
+
+ /* bgp suppress-duplicates */
+ install_element(BGP_NODE, &bgp_suppress_duplicates_cmd);
+ install_element(BGP_NODE, &no_bgp_suppress_duplicates_cmd);
+
+ /* bgp reject-as-sets */
+ install_element(BGP_NODE, &bgp_reject_as_sets_cmd);
+ install_element(BGP_NODE, &no_bgp_reject_as_sets_cmd);
+
+ /* "bgp deterministic-med" commands */
+ install_element(BGP_NODE, &bgp_deterministic_med_cmd);
+ install_element(BGP_NODE, &no_bgp_deterministic_med_cmd);
+
+ /* "bgp graceful-restart" command */
+ install_element(BGP_NODE, &bgp_graceful_restart_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_cmd);
+
+ /* "bgp graceful-restart-disable" command */
+ install_element(BGP_NODE, &bgp_graceful_restart_disable_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_disable_cmd);
+
+ /* "neighbor a:b:c:d graceful-restart" command */
+ install_element(BGP_NODE, &bgp_neighbor_graceful_restart_set_cmd);
+ install_element(BGP_NODE, &no_bgp_neighbor_graceful_restart_set_cmd);
+
+ /* "neighbor a:b:c:d graceful-restart-disable" command */
+ install_element(BGP_NODE,
+ &bgp_neighbor_graceful_restart_disable_set_cmd);
+ install_element(BGP_NODE,
+ &no_bgp_neighbor_graceful_restart_disable_set_cmd);
+
+ /* "neighbor a:b:c:d graceful-restart-helper" command */
+ install_element(BGP_NODE,
+ &bgp_neighbor_graceful_restart_helper_set_cmd);
+ install_element(BGP_NODE,
+ &no_bgp_neighbor_graceful_restart_helper_set_cmd);
+
+ install_element(BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd);
+ install_element(BGP_NODE, &bgp_graceful_restart_restart_time_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd);
+ install_element(BGP_NODE, &bgp_graceful_restart_select_defer_time_cmd);
+ install_element(BGP_NODE,
+ &no_bgp_graceful_restart_select_defer_time_cmd);
+ install_element(BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
+ install_element(BGP_NODE, &bgp_graceful_restart_notification_cmd);
+
+ install_element(BGP_NODE, &bgp_graceful_restart_disable_eor_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_disable_eor_cmd);
+ install_element(BGP_NODE, &bgp_graceful_restart_rib_stale_time_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_restart_rib_stale_time_cmd);
+
+ /* "bgp graceful-shutdown" commands */
+ install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
+ install_element(BGP_NODE, &no_bgp_graceful_shutdown_cmd);
+
+ /* "bgp hard-administrative-reset" commands */
+ install_element(BGP_NODE, &bgp_administrative_reset_cmd);
+
+ /* "bgp long-lived-graceful-restart" commands */
+ install_element(BGP_NODE, &bgp_llgr_stalepath_time_cmd);
+ install_element(BGP_NODE, &no_bgp_llgr_stalepath_time_cmd);
+
+ /* "bgp fast-external-failover" commands */
+ install_element(BGP_NODE, &bgp_fast_external_failover_cmd);
+ install_element(BGP_NODE, &no_bgp_fast_external_failover_cmd);
+
+ /* "bgp bestpath aigp" commands */
+ install_element(BGP_NODE, &bgp_bestpath_aigp_cmd);
+
+ /* "bgp bestpath compare-routerid" commands */
+ install_element(BGP_NODE, &bgp_bestpath_compare_router_id_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_compare_router_id_cmd);
+
+ /* "bgp bestpath as-path ignore" commands */
+ install_element(BGP_NODE, &bgp_bestpath_aspath_ignore_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_aspath_ignore_cmd);
+
+ /* "bgp bestpath as-path confed" commands */
+ install_element(BGP_NODE, &bgp_bestpath_aspath_confed_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_aspath_confed_cmd);
+
+ /* "bgp bestpath as-path multipath-relax" commands */
+ install_element(BGP_NODE, &bgp_bestpath_aspath_multipath_relax_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_aspath_multipath_relax_cmd);
+
+ /* "bgp bestpath peer-type multipath-relax" commands */
+ install_element(BGP_NODE, &bgp_bestpath_peer_type_multipath_relax_cmd);
+ install_element(BGP_NODE,
+ &no_bgp_bestpath_peer_type_multipath_relax_cmd);
+
+ /* "bgp log-neighbor-changes" commands */
+ install_element(BGP_NODE, &bgp_log_neighbor_changes_cmd);
+ install_element(BGP_NODE, &no_bgp_log_neighbor_changes_cmd);
+
+ /* "bgp bestpath med" commands */
+ install_element(BGP_NODE, &bgp_bestpath_med_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_med_cmd);
+
+ /* "bgp bestpath bandwidth" commands */
+ install_element(BGP_NODE, &bgp_bestpath_bw_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_bw_cmd);
+
+ /* "no bgp default <afi>-<safi>" commands. */
+ install_element(BGP_NODE, &bgp_default_afi_safi_cmd);
+
+ /* "bgp network import-check" commands. */
+ install_element(BGP_NODE, &bgp_network_import_check_cmd);
+ install_element(BGP_NODE, &bgp_network_import_check_exact_cmd);
+ install_element(BGP_NODE, &no_bgp_network_import_check_cmd);
+
+ /* "bgp default local-preference" commands. */
+ install_element(BGP_NODE, &bgp_default_local_preference_cmd);
+ install_element(BGP_NODE, &no_bgp_default_local_preference_cmd);
+
+ /* bgp default show-hostname */
+ install_element(BGP_NODE, &bgp_default_show_hostname_cmd);
+ install_element(BGP_NODE, &no_bgp_default_show_hostname_cmd);
+
+ /* bgp default show-nexthop-hostname */
+ install_element(BGP_NODE, &bgp_default_show_nexthop_hostname_cmd);
+ install_element(BGP_NODE, &no_bgp_default_show_nexthop_hostname_cmd);
+
+ /* bgp default software-version-capability */
+ install_element(BGP_NODE, &bgp_default_software_version_capability_cmd);
+
+ /* "bgp default subgroup-pkt-queue-max" commands. */
+ install_element(BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd);
+ install_element(BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd);
+
+ /* bgp ibgp-allow-policy-mods command */
+ install_element(BGP_NODE, &bgp_rr_allow_outbound_policy_cmd);
+ install_element(BGP_NODE, &no_bgp_rr_allow_outbound_policy_cmd);
+
+ /* "bgp listen limit" commands. */
+ install_element(BGP_NODE, &bgp_listen_limit_cmd);
+ install_element(BGP_NODE, &no_bgp_listen_limit_cmd);
+
+ /* "bgp listen range" commands. */
+ install_element(BGP_NODE, &bgp_listen_range_cmd);
+ install_element(BGP_NODE, &no_bgp_listen_range_cmd);
+
+ /* "bgp default shutdown" command */
+ install_element(BGP_NODE, &bgp_default_shutdown_cmd);
+
+ /* "bgp shutdown" commands */
+ install_element(BGP_NODE, &bgp_shutdown_cmd);
+ install_element(BGP_NODE, &bgp_shutdown_msg_cmd);
+ install_element(BGP_NODE, &no_bgp_shutdown_cmd);
+ install_element(BGP_NODE, &no_bgp_shutdown_msg_cmd);
+
+ /* "neighbor remote-as" commands. */
+ install_element(BGP_NODE, &neighbor_remote_as_cmd);
+ install_element(BGP_NODE, &neighbor_interface_config_cmd);
+ install_element(BGP_NODE, &neighbor_interface_config_v6only_cmd);
+ install_element(BGP_NODE, &neighbor_interface_config_remote_as_cmd);
+ install_element(BGP_NODE,
+ &neighbor_interface_v6only_config_remote_as_cmd);
+ install_element(BGP_NODE, &no_neighbor_cmd);
+ install_element(BGP_NODE, &no_neighbor_interface_config_cmd);
+
+ /* "neighbor peer-group" commands. */
+ install_element(BGP_NODE, &neighbor_peer_group_cmd);
+ install_element(BGP_NODE, &no_neighbor_peer_group_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_interface_peer_group_remote_as_cmd);
+
+ /* "neighbor local-as" commands. */
+ install_element(BGP_NODE, &neighbor_local_as_cmd);
+ install_element(BGP_NODE, &neighbor_local_as_no_prepend_cmd);
+ install_element(BGP_NODE, &neighbor_local_as_no_prepend_replace_as_cmd);
+ install_element(BGP_NODE, &no_neighbor_local_as_cmd);
+
+ /* "neighbor solo" commands. */
+ install_element(BGP_NODE, &neighbor_solo_cmd);
+ install_element(BGP_NODE, &no_neighbor_solo_cmd);
+
+ /* "neighbor password" commands. */
+ install_element(BGP_NODE, &neighbor_password_cmd);
+ install_element(BGP_NODE, &no_neighbor_password_cmd);
+
+ /* "neighbor activate" commands. */
+ install_element(BGP_NODE, &neighbor_activate_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_activate_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_activate_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_activate_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_activate_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_activate_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_activate_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_activate_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_activate_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_activate_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_activate_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_activate_cmd);
+
+ /* "no neighbor activate" commands. */
+ install_element(BGP_NODE, &no_neighbor_activate_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_activate_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_activate_cmd);
+
+ /* "neighbor peer-group" set commands. */
+ install_element(BGP_NODE, &neighbor_set_peer_group_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &neighbor_set_peer_group_hidden_cmd);
+
+ /* "no neighbor peer-group unset" commands. */
+ install_element(BGP_NODE, &no_neighbor_set_peer_group_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &no_neighbor_set_peer_group_hidden_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &no_neighbor_set_peer_group_hidden_cmd);
+
+ /* "neighbor softreconfiguration inbound" commands.*/
+ install_element(BGP_NODE, &neighbor_soft_reconfiguration_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_soft_reconfiguration_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soft_reconfiguration_cmd);
+
+ /* "neighbor attribute-unchanged" commands. */
+ install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_attr_unchanged_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_attr_unchanged_cmd);
+
+ install_element(BGP_EVPN_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_attr_unchanged_cmd);
+
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_attr_unchanged_cmd);
+
+ /* "nexthop-local unchanged" commands */
+ install_element(BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_nexthop_local_unchanged_cmd);
+
+ /* "neighbor next-hop-self" commands. */
+ install_element(BGP_NODE, &neighbor_nexthop_self_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_nexthop_self_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_nexthop_self_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_nexthop_self_cmd);
+
+ /* "neighbor next-hop-self force" commands. */
+ install_element(BGP_NODE, &neighbor_nexthop_self_force_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_nexthop_self_force_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_force_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_nexthop_self_force_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_nexthop_self_force_cmd);
+
+ /* "neighbor as-override" commands. */
+ install_element(BGP_NODE, &neighbor_as_override_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_as_override_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_as_override_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_as_override_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_as_override_cmd);
+
+ /* "neighbor remove-private-AS" commands. */
+ install_element(BGP_NODE, &neighbor_remove_private_as_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_remove_private_as_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_remove_private_as_all_hidden_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_remove_private_as_all_hidden_cmd);
+ install_element(BGP_NODE,
+ &neighbor_remove_private_as_replace_as_hidden_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_remove_private_as_replace_as_hidden_cmd);
+ install_element(BGP_NODE,
+ &neighbor_remove_private_as_all_replace_as_hidden_cmd);
+ install_element(
+ BGP_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV4_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_remove_private_as_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_remove_private_as_all_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_remove_private_as_replace_as_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_remove_private_as_all_replace_as_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_remove_private_as_all_replace_as_cmd);
+
+ /* "neighbor send-community" commands.*/
+ install_element(BGP_NODE, &neighbor_send_community_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_send_community_type_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_send_community_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_send_community_type_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_send_community_type_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_send_community_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_send_community_type_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_type_cmd);
+
+ /* "neighbor route-reflector" commands.*/
+ install_element(BGP_NODE, &neighbor_route_reflector_client_hidden_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_route_reflector_client_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &neighbor_route_reflector_client_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &neighbor_route_reflector_client_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &no_neighbor_route_reflector_client_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd);
+
+ /* "neighbor route-server" commands.*/
+ install_element(BGP_NODE, &neighbor_route_server_client_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_route_server_client_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_route_server_client_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_FLOWSPECV4_NODE,
+ &no_neighbor_route_server_client_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_route_server_client_cmd);
+ install_element(BGP_FLOWSPECV6_NODE,
+ &no_neighbor_route_server_client_cmd);
+
+ /* "neighbor disable-addpath-rx" commands. */
+ install_element(BGP_IPV4_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_disable_addpath_rx_cmd);
+
+ /* "neighbor addpath-tx-all-paths" commands.*/
+ install_element(BGP_NODE, &neighbor_addpath_tx_all_paths_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_addpath_tx_all_paths_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_addpath_tx_all_paths_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
+
+ /* "neighbor addpath-tx-best-selected" commands.*/
+ install_element(BGP_IPV4_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV4_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_addpath_tx_best_selected_paths_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_addpath_tx_best_selected_paths_cmd);
+
+ /* "neighbor addpath-tx-bestpath-per-AS" commands.*/
+ install_element(BGP_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_hidden_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd);
+ install_element(BGP_IPV4_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV4_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_addpath_tx_bestpath_per_as_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &no_neighbor_addpath_tx_bestpath_per_as_cmd);
+
+ /* "neighbor sender-as-path-loop-detection" commands. */
+ install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
+ install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
+
+ /* "neighbor path-attribute discard" commands. */
+ install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd);
+ install_element(BGP_NODE, &no_neighbor_path_attribute_discard_cmd);
+
+ /* "neighbor path-attribute treat-as-withdraw" commands. */
+ install_element(BGP_NODE,
+ &neighbor_path_attribute_treat_as_withdraw_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_path_attribute_treat_as_withdraw_cmd);
+
+ /* "neighbor passive" commands. */
+ install_element(BGP_NODE, &neighbor_passive_cmd);
+ install_element(BGP_NODE, &no_neighbor_passive_cmd);
+
+
+ /* "neighbor shutdown" commands. */
+ install_element(BGP_NODE, &neighbor_shutdown_cmd);
+ install_element(BGP_NODE, &no_neighbor_shutdown_cmd);
+ install_element(BGP_NODE, &neighbor_shutdown_msg_cmd);
+ install_element(BGP_NODE, &no_neighbor_shutdown_msg_cmd);
+ install_element(BGP_NODE, &neighbor_shutdown_rtt_cmd);
+ install_element(BGP_NODE, &no_neighbor_shutdown_rtt_cmd);
+
+ /* "neighbor capability extended-nexthop" commands.*/
+ install_element(BGP_NODE, &neighbor_capability_enhe_cmd);
+ install_element(BGP_NODE, &no_neighbor_capability_enhe_cmd);
+
+ /* "neighbor capability software-version" commands.*/
+ install_element(BGP_NODE, &neighbor_capability_software_version_cmd);
+
+ /* "neighbor capability orf prefix-list" commands.*/
+ install_element(BGP_NODE, &neighbor_capability_orf_prefix_hidden_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_capability_orf_prefix_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_capability_orf_prefix_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_capability_orf_prefix_cmd);
+
+ /* "neighbor capability dynamic" commands.*/
+ install_element(BGP_NODE, &neighbor_capability_dynamic_cmd);
+ install_element(BGP_NODE, &no_neighbor_capability_dynamic_cmd);
+
+ /* "neighbor dont-capability-negotiate" commands. */
+ install_element(BGP_NODE, &neighbor_dont_capability_negotiate_cmd);
+ install_element(BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd);
+
+ /* "neighbor ebgp-multihop" commands. */
+ install_element(BGP_NODE, &neighbor_ebgp_multihop_cmd);
+ install_element(BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd);
+ install_element(BGP_NODE, &no_neighbor_ebgp_multihop_cmd);
+
+ /* "neighbor disable-connected-check" commands. */
+ install_element(BGP_NODE, &neighbor_disable_connected_check_cmd);
+ install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd);
+
+ /* "neighbor disable-link-bw-encoding-ieee" commands. */
+ install_element(BGP_NODE, &neighbor_disable_link_bw_encoding_ieee_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_disable_link_bw_encoding_ieee_cmd);
+
+ /* "neighbor extended-optional-parameters" commands. */
+ install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
+ install_element(BGP_NODE,
+ &no_neighbor_extended_optional_parameters_cmd);
+
+ /* "neighbor enforce-first-as" commands. */
+ install_element(BGP_NODE, &neighbor_enforce_first_as_cmd);
+ install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd);
+
+ /* "neighbor description" commands. */
+ install_element(BGP_NODE, &neighbor_description_cmd);
+ install_element(BGP_NODE, &no_neighbor_description_cmd);
+ install_element(BGP_NODE, &no_neighbor_description_comment_cmd);
+
+ /* "neighbor update-source" commands. "*/
+ install_element(BGP_NODE, &neighbor_update_source_cmd);
+ install_element(BGP_NODE, &no_neighbor_update_source_cmd);
+
+ /* "neighbor default-originate" commands. */
+ install_element(BGP_NODE, &neighbor_default_originate_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_default_originate_rmap_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_default_originate_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_default_originate_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_default_originate_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_default_originate_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_default_originate_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_default_originate_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_default_originate_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_default_originate_rmap_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_default_originate_cmd);
+
+ /* "neighbor port" commands. */
+ install_element(BGP_NODE, &neighbor_port_cmd);
+ install_element(BGP_NODE, &no_neighbor_port_cmd);
+
+ /* "neighbor weight" commands. */
+ install_element(BGP_NODE, &neighbor_weight_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_weight_hidden_cmd);
+
+ install_element(BGP_IPV4_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_weight_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_weight_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_weight_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_weight_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_weight_cmd);
+
+ /* "neighbor override-capability" commands. */
+ install_element(BGP_NODE, &neighbor_override_capability_cmd);
+ install_element(BGP_NODE, &no_neighbor_override_capability_cmd);
+
+ /* "neighbor strict-capability-match" commands. */
+ install_element(BGP_NODE, &neighbor_strict_capability_cmd);
+ install_element(BGP_NODE, &no_neighbor_strict_capability_cmd);
+
+ /* "neighbor timers" commands. */
+ install_element(BGP_NODE, &neighbor_timers_cmd);
+ install_element(BGP_NODE, &no_neighbor_timers_cmd);
+
+ /* "neighbor timers connect" commands. */
+ install_element(BGP_NODE, &neighbor_timers_connect_cmd);
+ install_element(BGP_NODE, &no_neighbor_timers_connect_cmd);
+
+ /* "neighbor timers delayopen" commands. */
+ install_element(BGP_NODE, &neighbor_timers_delayopen_cmd);
+ install_element(BGP_NODE, &no_neighbor_timers_delayopen_cmd);
+
+ /* "neighbor advertisement-interval" commands. */
+ install_element(BGP_NODE, &neighbor_advertise_interval_cmd);
+ install_element(BGP_NODE, &no_neighbor_advertise_interval_cmd);
+
+ /* "neighbor interface" commands. */
+ install_element(BGP_NODE, &neighbor_interface_cmd);
+ install_element(BGP_NODE, &no_neighbor_interface_cmd);
+
+ /* "neighbor distribute" commands. */
+ install_element(BGP_NODE, &neighbor_distribute_list_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_distribute_list_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_distribute_list_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_distribute_list_cmd);
+
+ /* "neighbor prefix-list" commands. */
+ install_element(BGP_NODE, &neighbor_prefix_list_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_prefix_list_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_prefix_list_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_prefix_list_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_prefix_list_cmd);
+
+ /* "neighbor filter-list" commands. */
+ install_element(BGP_NODE, &neighbor_filter_list_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_filter_list_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_filter_list_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_filter_list_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_filter_list_cmd);
+
+ /* "neighbor route-map" commands. */
+ install_element(BGP_NODE, &neighbor_route_map_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_route_map_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_route_map_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_route_map_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_route_map_cmd);
+
+ /* "neighbor unsuppress-map" commands. */
+ install_element(BGP_NODE, &neighbor_unsuppress_map_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_unsuppress_map_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd);
+
+ /* "neighbor advertise-map" commands. */
+ install_element(BGP_NODE, &bgp_condadv_period_cmd);
+ install_element(BGP_NODE, &neighbor_advertise_map_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_advertise_map_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_advertise_map_cmd);
+
+ /* bgp default-originate timer */
+ install_element(BGP_NODE, &bgp_def_originate_eval_cmd);
+
+ /* neighbor maximum-prefix-out commands. */
+ install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_out_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_out_cmd);
+
+ /* "neighbor maximum-prefix" commands. */
+ install_element(BGP_NODE, &neighbor_maximum_prefix_hidden_cmd);
+ install_element(BGP_NODE,
+ &neighbor_maximum_prefix_threshold_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_maximum_prefix_warning_hidden_cmd);
+ install_element(BGP_NODE,
+ &neighbor_maximum_prefix_threshold_warning_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_maximum_prefix_restart_hidden_cmd);
+ install_element(BGP_NODE,
+ &neighbor_maximum_prefix_threshold_restart_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_maximum_prefix_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV4_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV4_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV4M_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV4L_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV6_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV6M_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_IPV6L_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_VPNV4_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_VPNV6_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd);
+
+ /* "neighbor allowas-in" */
+ install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_allowas_in_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd);
+
+ /* neighbor accept-own */
+ install_element(BGP_VPNV4_NODE, &neighbor_accept_own_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_accept_own_cmd);
+
+ /* "neighbor soo" */
+ install_element(BGP_IPV4_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_soo_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_soo_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soo_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soo_cmd);
+
+ /* address-family commands. */
+ install_element(BGP_NODE, &address_family_ipv4_safi_cmd);
+ install_element(BGP_NODE, &address_family_ipv6_safi_cmd);
+#ifdef KEEP_OLD_VPN_COMMANDS
+ install_element(BGP_NODE, &address_family_vpnv4_cmd);
+ install_element(BGP_NODE, &address_family_vpnv6_cmd);
+#endif /* KEEP_OLD_VPN_COMMANDS */
+
+ install_element(BGP_NODE, &address_family_evpn_cmd);
+
+ /* "exit-address-family" command. */
+ install_element(BGP_IPV4_NODE, &exit_address_family_cmd);
+ install_element(BGP_IPV4M_NODE, &exit_address_family_cmd);
+ install_element(BGP_IPV4L_NODE, &exit_address_family_cmd);
+ install_element(BGP_IPV6_NODE, &exit_address_family_cmd);
+ install_element(BGP_IPV6M_NODE, &exit_address_family_cmd);
+ install_element(BGP_IPV6L_NODE, &exit_address_family_cmd);
+ install_element(BGP_VPNV4_NODE, &exit_address_family_cmd);
+ install_element(BGP_VPNV6_NODE, &exit_address_family_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
+ install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
+
+ /* BGP retain all route-target */
+ install_element(BGP_VPNV4_NODE, &bgp_retain_route_target_cmd);
+ install_element(BGP_VPNV6_NODE, &bgp_retain_route_target_cmd);
+
+ /* "clear ip bgp commands" */
+ install_element(ENABLE_NODE, &clear_ip_bgp_all_cmd);
+
+ /* clear ip bgp prefix */
+ install_element(ENABLE_NODE, &clear_ip_bgp_prefix_cmd);
+ install_element(ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd);
+ install_element(ENABLE_NODE, &clear_bgp_instance_ipv6_safi_prefix_cmd);
+
+ /* "show [ip] bgp summary" commands. */
+ install_element(VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd);
+ install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_updgrps_cmd);
+ install_element(VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd);
+ install_element(VIEW_NODE, &show_bgp_updgrps_stats_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_summary_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_updgrps_cmd);
+
+ /* "show [ip] bgp neighbors" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_neighbors_cmd);
+
+ install_element(VIEW_NODE, &show_ip_bgp_neighbors_graceful_restart_cmd);
+
+ /* "show [ip] bgp peer-group" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_peer_groups_cmd);
+
+ /* "show [ip] bgp paths" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_paths_cmd);
+
+ /* "show [ip] bgp community" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_community_info_cmd);
+
+ /* "show ip bgp large-community" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_lcommunity_info_cmd);
+ /* "show [ip] bgp attribute-info" commands. */
+ install_element(VIEW_NODE, &show_ip_bgp_attr_info_cmd);
+ /* "show [ip] bgp route-leak" command */
+ install_element(VIEW_NODE, &show_ip_bgp_route_leak_cmd);
+
+ /* "redistribute" commands. */
+ install_element(BGP_NODE, &bgp_redistribute_ipv4_hidden_cmd);
+ install_element(BGP_NODE, &no_bgp_redistribute_ipv4_hidden_cmd);
+ install_element(BGP_NODE, &bgp_redistribute_ipv4_rmap_hidden_cmd);
+ install_element(BGP_NODE, &bgp_redistribute_ipv4_metric_hidden_cmd);
+ install_element(BGP_NODE,
+ &bgp_redistribute_ipv4_rmap_metric_hidden_cmd);
+ install_element(BGP_NODE,
+ &bgp_redistribute_ipv4_metric_rmap_hidden_cmd);
+ install_element(BGP_NODE, &bgp_redistribute_ipv4_ospf_hidden_cmd);
+ install_element(BGP_NODE, &no_bgp_redistribute_ipv4_ospf_hidden_cmd);
+ install_element(BGP_NODE, &bgp_redistribute_ipv4_ospf_rmap_hidden_cmd);
+ install_element(BGP_NODE,
+ &bgp_redistribute_ipv4_ospf_metric_hidden_cmd);
+ install_element(BGP_NODE,
+ &bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd);
+ install_element(BGP_NODE,
+ &bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_cmd);
+ install_element(BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_metric_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_rmap_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_cmd);
+ install_element(BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_ospf_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_rmap_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_metric_cmd);
+ install_element(BGP_IPV4_NODE,
+ &bgp_redistribute_ipv4_ospf_rmap_metric_cmd);
+ install_element(BGP_IPV4_NODE,
+ &bgp_redistribute_ipv4_ospf_metric_rmap_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_cmd);
+ install_element(BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
+
+ /* import|export vpn [route-map RMAP_NAME] */
+ install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_imexport_vpn_cmd);
+
+ install_element(BGP_IPV4_NODE, &bgp_imexport_vrf_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_imexport_vrf_cmd);
+
+ /* ttl_security commands */
+ install_element(BGP_NODE, &neighbor_ttl_security_cmd);
+ install_element(BGP_NODE, &no_neighbor_ttl_security_cmd);
+
+ /* "bgp tcp-keepalive" commands */
+ install_element(BGP_NODE, &bgp_tcp_keepalive_cmd);
+ install_element(BGP_NODE, &no_bgp_tcp_keepalive_cmd);
+
+ /* "show [ip] bgp memory" commands. */
+ install_element(VIEW_NODE, &show_bgp_memory_cmd);
+
+ /* "show bgp martian next-hop" */
+ install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
+
+ install_element(VIEW_NODE, &show_bgp_mac_hash_cmd);
+
+ /* "show [ip] bgp views" commands. */
+ install_element(VIEW_NODE, &show_bgp_views_cmd);
+
+ /* "show [ip] bgp vrfs" commands. */
+ install_element(VIEW_NODE, &show_bgp_vrfs_cmd);
+
+ /* Community-list. */
+ community_list_vty();
+
+ community_alias_vty();
+
+ /* vpn-policy commands */
+ install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd);
+ install_element(BGP_IPV4_NODE, &af_label_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_label_vpn_export_cmd);
+ install_element(BGP_IPV4_NODE,
+ &af_label_vpn_export_allocation_mode_cmd);
+ install_element(BGP_IPV6_NODE,
+ &af_label_vpn_export_allocation_mode_cmd);
+ install_element(BGP_IPV4_NODE, &af_nexthop_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_nexthop_vpn_export_cmd);
+ install_element(BGP_IPV4_NODE, &af_rt_vpn_imexport_cmd);
+ install_element(BGP_IPV6_NODE, &af_rt_vpn_imexport_cmd);
+ install_element(BGP_IPV4_NODE, &af_route_map_vpn_imexport_cmd);
+ install_element(BGP_IPV6_NODE, &af_route_map_vpn_imexport_cmd);
+ install_element(BGP_IPV4_NODE, &af_import_vrf_route_map_cmd);
+ install_element(BGP_IPV6_NODE, &af_import_vrf_route_map_cmd);
+
+ install_element(BGP_IPV4_NODE, &af_routetarget_import_cmd);
+ install_element(BGP_IPV6_NODE, &af_routetarget_import_cmd);
+
+ install_element(BGP_IPV4_NODE, &af_no_rd_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_no_rd_vpn_export_cmd);
+ install_element(BGP_IPV4_NODE, &af_no_label_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_no_label_vpn_export_cmd);
+ install_element(BGP_IPV4_NODE, &af_no_rt_vpn_imexport_cmd);
+ install_element(BGP_IPV6_NODE, &af_no_rt_vpn_imexport_cmd);
+ install_element(BGP_IPV4_NODE, &af_no_route_map_vpn_imexport_cmd);
+ install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd);
+ install_element(BGP_IPV4_NODE, &af_no_import_vrf_route_map_cmd);
+ install_element(BGP_IPV6_NODE, &af_no_import_vrf_route_map_cmd);
+
+ /* tcp-mss command */
+ install_element(BGP_NODE, &neighbor_tcp_mss_cmd);
+ install_element(BGP_NODE, &no_neighbor_tcp_mss_cmd);
+
+ /* srv6 commands */
+ install_element(VIEW_NODE, &show_bgp_srv6_cmd);
+ install_element(BGP_NODE, &bgp_segment_routing_srv6_cmd);
+ install_element(BGP_NODE, &no_bgp_segment_routing_srv6_cmd);
+ install_element(BGP_SRV6_NODE, &bgp_srv6_locator_cmd);
+ install_element(BGP_SRV6_NODE, &no_bgp_srv6_locator_cmd);
+ install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd);
+ install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd);
+ install_element(BGP_NODE, &bgp_sid_vpn_export_cmd);
+ install_element(BGP_NODE, &no_bgp_sid_vpn_export_cmd);
+
+ bgp_vty_if_init();
+}
+
+#include "memory.h"
+#include "bgp_regex.h"
+#include "bgp_clist.h"
+#include "bgp_ecommunity.h"
+
+/* VTY functions. */
+
+/* Direction value to string conversion. */
+static const char *community_direct_str(int direct)
+{
+ switch (direct) {
+ case COMMUNITY_DENY:
+ return "deny";
+ case COMMUNITY_PERMIT:
+ return "permit";
+ default:
+ return "unknown";
+ }
+}
+
+/* Display error string. */
+static void community_list_perror(struct vty *vty, int ret)
+{
+ switch (ret) {
+ case COMMUNITY_LIST_ERR_CANT_FIND_LIST:
+ vty_out(vty, "%% Can't find community-list\n");
+ break;
+ case COMMUNITY_LIST_ERR_MALFORMED_VAL:
+ vty_out(vty, "%% Malformed community-list value\n");
+ break;
+ case COMMUNITY_LIST_ERR_STANDARD_CONFLICT:
+ vty_out(vty,
+ "%% Community name conflict, previously defined as standard community\n");
+ break;
+ case COMMUNITY_LIST_ERR_EXPANDED_CONFLICT:
+ vty_out(vty,
+ "%% Community name conflict, previously defined as expanded community\n");
+ break;
+ }
+}
+
+/* "community-list" keyword help string. */
+#define COMMUNITY_LIST_STR "Add a community list entry\n"
+
+/*community-list standard */
+DEFUN (community_list_standard,
+ bgp_community_list_standard_cmd,
+ "bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ BGP_STR
+ COMMUNITY_LIST_STR
+ "Community list number (standard)\n"
+ "Add an standard community-list entry\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ COMMUNITY_VAL_STR)
+{
+ char *cl_name_or_number = NULL;
+ char *seq = NULL;
+ int direct = 0;
+ int style = COMMUNITY_LIST_STANDARD;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
+ cl_name_or_number = argv[idx]->arg;
+ direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+ argv_find(argv, argc, "AA:NN", &idx);
+ char *str = argv_concat(argv, argc, idx);
+
+ assert(str);
+ int ret = community_list_set(bgp_clist, cl_name_or_number, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ /* Display error string. */
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_community_list_standard_all,
+ no_bgp_community_list_standard_all_cmd,
+ "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ NO_STR
+ BGP_STR
+ COMMUNITY_LIST_STR
+ "Community list number (standard)\n"
+ "Add an standard community-list entry\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ COMMUNITY_VAL_STR)
+{
+ char *cl_name_or_number = NULL;
+ char *str = NULL;
+ int direct = 0;
+ int style = COMMUNITY_LIST_STANDARD;
+ char *seq = NULL;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "AA:NN", &idx);
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
+ cl_name_or_number = argv[idx]->arg;
+
+ int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd,
+ "no bgp community-list <(1-99)|standard COMMUNITY_LIST_NAME>",
+ NO_STR BGP_STR COMMUNITY_LIST_STR
+ "Community list number (standard)\n"
+ "Add an standard community-list entry\n"
+ "Community list name\n")
+
+/*community-list expanded */
+DEFUN (community_list_expanded_all,
+ bgp_community_list_expanded_all_cmd,
+ "bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ BGP_STR
+ COMMUNITY_LIST_STR
+ "Community list number (expanded)\n"
+ "Add an expanded community-list entry\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ COMMUNITY_VAL_STR)
+{
+ char *cl_name_or_number = NULL;
+ char *seq = NULL;
+ int direct = 0;
+ int style = COMMUNITY_LIST_EXPANDED;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+
+ argv_find(argv, argc, "(100-500)", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
+ cl_name_or_number = argv[idx]->arg;
+ direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+ argv_find(argv, argc, "AA:NN", &idx);
+ char *str = argv_concat(argv, argc, idx);
+
+ assert(str);
+ int ret = community_list_set(bgp_clist, cl_name_or_number, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ /* Display error string. */
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_community_list_expanded_all,
+ no_bgp_community_list_expanded_all_cmd,
+ "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ NO_STR
+ BGP_STR
+ COMMUNITY_LIST_STR
+ "Community list number (expanded)\n"
+ "Add an expanded community-list entry\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ COMMUNITY_VAL_STR)
+{
+ char *cl_name_or_number = NULL;
+ char *seq = NULL;
+ char *str = NULL;
+ int direct = 0;
+ int style = COMMUNITY_LIST_EXPANDED;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "AA:NN", &idx);
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "(100-500)", &idx);
+ argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
+ cl_name_or_number = argv[idx]->arg;
+
+ int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_community_list_expanded_all,
+ no_bgp_community_list_expanded_all_list_cmd,
+ "no bgp community-list <(100-500)|expanded COMMUNITY_LIST_NAME>",
+ NO_STR BGP_STR COMMUNITY_LIST_STR
+ "Community list number (expanded)\n"
+ "Add an expanded community-list entry\n"
+ "Community list name\n")
+
+/* Return configuration string of community-list entry. */
+static const char *community_list_config_str(struct community_entry *entry)
+{
+ const char *str;
+
+ if (entry->style == COMMUNITY_LIST_STANDARD)
+ str = community_str(entry->u.com, false, false);
+ else if (entry->style == LARGE_COMMUNITY_LIST_STANDARD)
+ str = lcommunity_str(entry->u.lcom, false, false);
+ else
+ str = entry->config;
+
+ return str;
+}
+
+static void community_list_show(struct vty *vty, struct community_list *list)
+{
+ struct community_entry *entry;
+
+ for (entry = list->head; entry; entry = entry->next) {
+ if (entry == list->head) {
+ if (all_digit(list->name))
+ vty_out(vty, "Community %s list %s\n",
+ entry->style == COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "(expanded) access",
+ list->name);
+ else
+ vty_out(vty, "Named Community %s list %s\n",
+ entry->style == COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name);
+ }
+ vty_out(vty, " %s %s\n", community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ }
+}
+
+DEFUN (show_community_list,
+ show_bgp_community_list_cmd,
+ "show bgp community-list",
+ SHOW_STR
+ BGP_STR
+ "List community-list\n")
+{
+ struct community_list *list;
+ struct community_list_master *cm;
+
+ cm = community_list_master_lookup(bgp_clist, COMMUNITY_LIST_MASTER);
+ if (!cm)
+ return CMD_SUCCESS;
+
+ for (list = cm->num.head; list; list = list->next)
+ community_list_show(vty, list);
+
+ for (list = cm->str.head; list; list = list->next)
+ community_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_community_list_arg,
+ show_bgp_community_list_arg_cmd,
+ "show bgp community-list <(1-500)|COMMUNITY_LIST_NAME> detail",
+ SHOW_STR
+ BGP_STR
+ "List community-list\n"
+ "Community-list number\n"
+ "Community-list name\n"
+ "Detailed information on community-list\n")
+{
+ int idx_comm_list = 3;
+ struct community_list *list;
+
+ list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
+ COMMUNITY_LIST_MASTER);
+ if (!list) {
+ vty_out(vty, "%% Can't find community-list\n");
+ return CMD_WARNING;
+ }
+
+ community_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+/*
+ * Large Community code.
+ */
+static int lcommunity_list_set_vty(struct vty *vty, int argc,
+ struct cmd_token **argv, int style,
+ int reject_all_digit_name)
+{
+ int ret;
+ int direct;
+ char *str;
+ int idx = 0;
+ char *cl_name;
+ char *seq = NULL;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ /* All digit name check. */
+ idx = 0;
+ argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx);
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "(100-500)", &idx);
+ cl_name = argv[idx]->arg;
+ if (reject_all_digit_name && all_digit(cl_name)) {
+ vty_out(vty, "%% Community name cannot have all digits\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "AA:BB:CC", &idx);
+ argv_find(argv, argc, "LINE", &idx);
+ /* Concat community string argument. */
+ if (idx)
+ str = argv_concat(argv, argc, idx);
+ else
+ str = NULL;
+
+ ret = lcommunity_list_set(bgp_clist, cl_name, str, seq, direct, style);
+
+ /* Free temporary community list string allocated by
+ argv_concat(). */
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ return CMD_SUCCESS;
+}
+
+static int lcommunity_list_unset_vty(struct vty *vty, int argc,
+ struct cmd_token **argv, int style)
+{
+ int ret;
+ int direct = 0;
+ char *str = NULL;
+ int idx = 0;
+ char *seq = NULL;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ /* Check the list direct. */
+ if (strncmp(argv[idx]->arg, "p", 1) == 0)
+ direct = COMMUNITY_PERMIT;
+ else
+ direct = COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "LINE", &idx);
+ argv_find(argv, argc, "AA:AA:NN", &idx);
+ /* Concat community string argument. */
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "(100-500)", &idx);
+ argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx);
+
+ /* Unset community list. */
+ ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct,
+ style);
+
+ /* Free temporary community list string allocated by
+ argv_concat(). */
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* "large-community-list" keyword help string. */
+#define LCOMMUNITY_LIST_STR "Add a large community list entry\n"
+#define LCOMMUNITY_VAL_STR "large community in 'aa:bb:cc' format\n"
+
+DEFUN (lcommunity_list_standard,
+ bgp_lcommunity_list_standard_cmd,
+ "bgp large-community-list (1-99) [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Large Community list number (standard)\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ LCOMMUNITY_VAL_STR)
+{
+ return lcommunity_list_set_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD, 0);
+}
+
+DEFUN (lcommunity_list_expanded,
+ bgp_lcommunity_list_expanded_cmd,
+ "bgp large-community-list (100-500) [seq (0-4294967295)] <deny|permit> LINE...",
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Large Community list number (expanded)\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ return lcommunity_list_set_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_EXPANDED, 0);
+}
+
+DEFUN (lcommunity_list_name_standard,
+ bgp_lcommunity_list_name_standard_cmd,
+ "bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify standard large-community-list\n"
+ "Large Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ LCOMMUNITY_VAL_STR)
+{
+ return lcommunity_list_set_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD, 1);
+}
+
+DEFUN (lcommunity_list_name_expanded,
+ bgp_lcommunity_list_name_expanded_cmd,
+ "bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...",
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify expanded large-community-list\n"
+ "Large Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ return lcommunity_list_set_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_EXPANDED, 1);
+}
+
+DEFUN (no_lcommunity_list_all,
+ no_bgp_lcommunity_list_all_cmd,
+ "no bgp large-community-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME>",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Large Community list number (standard)\n"
+ "Large Community list number (expanded)\n"
+ "Large Community list name\n")
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_lcommunity_list_name_standard_all,
+ no_bgp_lcommunity_list_name_standard_all_cmd,
+ "no bgp large-community-list standard LCOMMUNITY_LIST_NAME",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify standard large-community-list\n"
+ "Large Community list name\n")
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_lcommunity_list_name_expanded_all,
+ no_bgp_lcommunity_list_name_expanded_all_cmd,
+ "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify expanded large-community-list\n"
+ "Large Community list name\n")
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_EXPANDED);
+}
+
+DEFUN (no_lcommunity_list_standard,
+ no_bgp_lcommunity_list_standard_cmd,
+ "no bgp large-community-list (1-99) [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Large Community list number (standard)\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ LCOMMUNITY_VAL_STR)
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_lcommunity_list_expanded,
+ no_bgp_lcommunity_list_expanded_cmd,
+ "no bgp large-community-list (100-500) [seq (0-4294967295)] <deny|permit> LINE...",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Large Community list number (expanded)\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_EXPANDED);
+}
+
+DEFUN (no_lcommunity_list_name_standard,
+ no_bgp_lcommunity_list_name_standard_cmd,
+ "no bgp large-community-list standard LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify standard large-community-list\n"
+ "Large Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ LCOMMUNITY_VAL_STR)
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_lcommunity_list_name_expanded,
+ no_bgp_lcommunity_list_name_expanded_cmd,
+ "no bgp large-community-list expanded LCOMMUNITY_LIST_NAME [seq (0-4294967295)] <deny|permit> LINE...",
+ NO_STR
+ BGP_STR
+ LCOMMUNITY_LIST_STR
+ "Specify expanded large-community-list\n"
+ "Large community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify large community to reject\n"
+ "Specify large community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ return lcommunity_list_unset_vty(vty, argc, argv,
+ LARGE_COMMUNITY_LIST_EXPANDED);
+}
+
+static void lcommunity_list_show(struct vty *vty, struct community_list *list)
+{
+ struct community_entry *entry;
+
+ for (entry = list->head; entry; entry = entry->next) {
+ if (entry == list->head) {
+ if (all_digit(list->name))
+ vty_out(vty, "Large community %s list %s\n",
+ entry->style ==
+ LARGE_COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "(expanded) access",
+ list->name);
+ else
+ vty_out(vty,
+ "Named large community %s list %s\n",
+ entry->style ==
+ LARGE_COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name);
+ }
+ vty_out(vty, " %s %s\n", community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ }
+}
+
+DEFUN (show_lcommunity_list,
+ show_bgp_lcommunity_list_cmd,
+ "show bgp large-community-list",
+ SHOW_STR
+ BGP_STR
+ "List large-community list\n")
+{
+ struct community_list *list;
+ struct community_list_master *cm;
+
+ cm = community_list_master_lookup(bgp_clist,
+ LARGE_COMMUNITY_LIST_MASTER);
+ if (!cm)
+ return CMD_SUCCESS;
+
+ for (list = cm->num.head; list; list = list->next)
+ lcommunity_list_show(vty, list);
+
+ for (list = cm->str.head; list; list = list->next)
+ lcommunity_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_lcommunity_list_arg,
+ show_bgp_lcommunity_list_arg_cmd,
+ "show bgp large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> detail",
+ SHOW_STR
+ BGP_STR
+ "List large-community list\n"
+ "Large-community-list number\n"
+ "Large-community-list name\n"
+ "Detailed information on large-community-list\n")
+{
+ struct community_list *list;
+
+ list = community_list_lookup(bgp_clist, argv[3]->arg, 0,
+ LARGE_COMMUNITY_LIST_MASTER);
+ if (!list) {
+ vty_out(vty, "%% Can't find large-community-list\n");
+ return CMD_WARNING;
+ }
+
+ lcommunity_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+/* "extcommunity-list" keyword help string. */
+#define EXTCOMMUNITY_LIST_STR "Add a extended community list entry\n"
+#define EXTCOMMUNITY_VAL_STR "Extended community attribute in 'rt aa:nn_or_IPaddr:nn' OR 'soo aa:nn_or_IPaddr:nn' format\n"
+
+DEFUN (extcommunity_list_standard,
+ bgp_extcommunity_list_standard_cmd,
+ "bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ BGP_STR
+ EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (standard)\n"
+ "Specify standard extcommunity-list\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ EXTCOMMUNITY_VAL_STR)
+{
+ int style = EXTCOMMUNITY_LIST_STANDARD;
+ int direct = 0;
+ char *cl_number_or_name = NULL;
+ char *seq = NULL;
+
+ int idx = 0;
+
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
+ cl_number_or_name = argv[idx]->arg;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+ argv_find(argv, argc, "AA:NN", &idx);
+ char *str = argv_concat(argv, argc, idx);
+
+ int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (extcommunity_list_name_expanded,
+ bgp_extcommunity_list_name_expanded_cmd,
+ "bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...",
+ BGP_STR
+ EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (expanded)\n"
+ "Specify expanded extcommunity-list\n"
+ "Extended Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ int style = EXTCOMMUNITY_LIST_EXPANDED;
+ int direct = 0;
+ char *cl_number_or_name = NULL;
+ char *seq = NULL;
+ int idx = 0;
+
+ argv_find(argv, argc, "(100-500)", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
+ cl_number_or_name = argv[idx]->arg;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+ argv_find(argv, argc, "LINE", &idx);
+ char *str = argv_concat(argv, argc, idx);
+
+ int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, seq,
+ direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_extcommunity_list_standard_all,
+ no_bgp_extcommunity_list_standard_all_cmd,
+ "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> AA:NN...",
+ NO_STR
+ BGP_STR
+ EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (standard)\n"
+ "Specify standard extcommunity-list\n"
+ "Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ EXTCOMMUNITY_VAL_STR)
+{
+ int style = EXTCOMMUNITY_LIST_STANDARD;
+ int direct = 0;
+ char *cl_number_or_name = NULL;
+ char *str = NULL;
+ char *seq = NULL;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "AA:NN", &idx);
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "(1-99)", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
+ cl_number_or_name = argv[idx]->arg;
+
+ int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
+ seq, direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_extcommunity_list_standard_all,
+ no_bgp_extcommunity_list_standard_all_list_cmd,
+ "no bgp extcommunity-list <(1-99)|standard EXTCOMMUNITY_LIST_NAME>",
+ NO_STR BGP_STR EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (standard)\n"
+ "Specify standard extcommunity-list\n"
+ "Community list name\n")
+
+DEFUN (no_extcommunity_list_expanded_all,
+ no_bgp_extcommunity_list_expanded_all_cmd,
+ "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME> [seq (0-4294967295)] <deny|permit> LINE...",
+ NO_STR
+ BGP_STR
+ EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (expanded)\n"
+ "Specify expanded extcommunity-list\n"
+ "Extended Community list name\n"
+ "Sequence number of an entry\n"
+ "Sequence number\n"
+ "Specify community to reject\n"
+ "Specify community to accept\n"
+ "An ordered list as a regular-expression\n")
+{
+ int style = EXTCOMMUNITY_LIST_EXPANDED;
+ int direct = 0;
+ char *cl_number_or_name = NULL;
+ char *str = NULL;
+ char *seq = NULL;
+ int idx = 0;
+
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
+ seq = argv[idx]->arg;
+
+ idx = 0;
+ argv_find(argv, argc, "permit", &idx);
+ argv_find(argv, argc, "deny", &idx);
+
+ if (idx) {
+ direct = argv_find(argv, argc, "permit", &idx)
+ ? COMMUNITY_PERMIT
+ : COMMUNITY_DENY;
+
+ idx = 0;
+ argv_find(argv, argc, "LINE", &idx);
+ str = argv_concat(argv, argc, idx);
+ }
+
+ idx = 0;
+ argv_find(argv, argc, "(100-500)", &idx);
+ argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
+ cl_number_or_name = argv[idx]->arg;
+
+ int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
+ seq, direct, style);
+
+ XFREE(MTYPE_TMP, str);
+
+ if (ret < 0) {
+ community_list_perror(vty, ret);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS(no_extcommunity_list_expanded_all,
+ no_bgp_extcommunity_list_expanded_all_list_cmd,
+ "no bgp extcommunity-list <(100-500)|expanded EXTCOMMUNITY_LIST_NAME>",
+ NO_STR BGP_STR EXTCOMMUNITY_LIST_STR
+ "Extended Community list number (expanded)\n"
+ "Specify expanded extcommunity-list\n"
+ "Extended Community list name\n")
+
+static void extcommunity_list_show(struct vty *vty, struct community_list *list)
+{
+ struct community_entry *entry;
+
+ for (entry = list->head; entry; entry = entry->next) {
+ if (entry == list->head) {
+ if (all_digit(list->name))
+ vty_out(vty, "Extended community %s list %s\n",
+ entry->style == EXTCOMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "(expanded) access",
+ list->name);
+ else
+ vty_out(vty,
+ "Named extended community %s list %s\n",
+ entry->style == EXTCOMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name);
+ }
+ vty_out(vty, " %s %s\n", community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ }
+}
+
+DEFUN (show_extcommunity_list,
+ show_bgp_extcommunity_list_cmd,
+ "show bgp extcommunity-list",
+ SHOW_STR
+ BGP_STR
+ "List extended-community list\n")
+{
+ struct community_list *list;
+ struct community_list_master *cm;
+
+ cm = community_list_master_lookup(bgp_clist, EXTCOMMUNITY_LIST_MASTER);
+ if (!cm)
+ return CMD_SUCCESS;
+
+ for (list = cm->num.head; list; list = list->next)
+ extcommunity_list_show(vty, list);
+
+ for (list = cm->str.head; list; list = list->next)
+ extcommunity_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_extcommunity_list_arg,
+ show_bgp_extcommunity_list_arg_cmd,
+ "show bgp extcommunity-list <(1-500)|EXTCOMMUNITY_LIST_NAME> detail",
+ SHOW_STR
+ BGP_STR
+ "List extended-community list\n"
+ "Extcommunity-list number\n"
+ "Extcommunity-list name\n"
+ "Detailed information on extcommunity-list\n")
+{
+ int idx_comm_list = 3;
+ struct community_list *list;
+
+ list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
+ EXTCOMMUNITY_LIST_MASTER);
+ if (!list) {
+ vty_out(vty, "%% Can't find extcommunity-list\n");
+ return CMD_WARNING;
+ }
+
+ extcommunity_list_show(vty, list);
+
+ return CMD_SUCCESS;
+}
+
+/* Display community-list and extcommunity-list configuration. */
+static int community_list_config_write(struct vty *vty)
+{
+ struct community_list *list;
+ struct community_entry *entry;
+ struct community_list_master *cm;
+ int write = 0;
+
+ /* Community-list. */
+ cm = community_list_master_lookup(bgp_clist, COMMUNITY_LIST_MASTER);
+
+ for (list = cm->num.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp community-list %s seq %" PRId64 " %s %s\n",
+ list->name, entry->seq,
+ community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+ for (list = cm->str.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp community-list %s %s seq %" PRId64 " %s %s\n",
+ entry->style == COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name, entry->seq,
+ community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+
+ /* Extcommunity-list. */
+ cm = community_list_master_lookup(bgp_clist, EXTCOMMUNITY_LIST_MASTER);
+
+ for (list = cm->num.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp extcommunity-list %s seq %" PRId64 " %s %s\n",
+ list->name, entry->seq,
+ community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+ for (list = cm->str.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp extcommunity-list %s %s seq %" PRId64" %s %s\n",
+ entry->style == EXTCOMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name, entry->seq,
+ community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+
+
+ /* lcommunity-list. */
+ cm = community_list_master_lookup(bgp_clist,
+ LARGE_COMMUNITY_LIST_MASTER);
+
+ for (list = cm->num.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp large-community-list %s seq %" PRId64" %s %s\n",
+ list->name, entry->seq,
+ community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+ for (list = cm->str.head; list; list = list->next)
+ for (entry = list->head; entry; entry = entry->next) {
+ vty_out(vty,
+ "bgp large-community-list %s %s seq %" PRId64" %s %s\n",
+
+ entry->style == LARGE_COMMUNITY_LIST_STANDARD
+ ? "standard"
+ : "expanded",
+ list->name, entry->seq, community_direct_str(entry->direct),
+ community_list_config_str(entry));
+ write++;
+ }
+
+ return write;
+}
+
+static int community_list_config_write(struct vty *vty);
+static struct cmd_node community_list_node = {
+ .name = "community list",
+ .node = COMMUNITY_LIST_NODE,
+ .prompt = "",
+ .config_write = community_list_config_write,
+};
+
+static void community_list_vty(void)
+{
+ install_node(&community_list_node);
+
+ /* Community-list. */
+ install_element(CONFIG_NODE, &bgp_community_list_standard_cmd);
+ install_element(CONFIG_NODE, &bgp_community_list_expanded_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_standard_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_standard_all_list_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_expanded_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_community_list_expanded_all_list_cmd);
+ install_element(VIEW_NODE, &show_bgp_community_list_cmd);
+ install_element(VIEW_NODE, &show_bgp_community_list_arg_cmd);
+
+ /* Extcommunity-list. */
+ install_element(CONFIG_NODE, &bgp_extcommunity_list_standard_cmd);
+ install_element(CONFIG_NODE, &bgp_extcommunity_list_name_expanded_cmd);
+ install_element(CONFIG_NODE, &no_bgp_extcommunity_list_standard_all_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_extcommunity_list_standard_all_list_cmd);
+ install_element(CONFIG_NODE, &no_bgp_extcommunity_list_expanded_all_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_extcommunity_list_expanded_all_list_cmd);
+ install_element(VIEW_NODE, &show_bgp_extcommunity_list_cmd);
+ install_element(VIEW_NODE, &show_bgp_extcommunity_list_arg_cmd);
+
+ /* Large Community List */
+ install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd);
+ install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd);
+ install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd);
+ install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd);
+ install_element(CONFIG_NODE, &no_bgp_lcommunity_list_all_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_lcommunity_list_name_standard_all_cmd);
+ install_element(CONFIG_NODE,
+ &no_bgp_lcommunity_list_name_expanded_all_cmd);
+ install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_cmd);
+ install_element(CONFIG_NODE, &no_bgp_lcommunity_list_expanded_cmd);
+ install_element(CONFIG_NODE, &no_bgp_lcommunity_list_name_standard_cmd);
+ install_element(CONFIG_NODE, &no_bgp_lcommunity_list_name_expanded_cmd);
+ install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd);
+ install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd);
+
+ bgp_community_list_command_completion_setup();
+}
+
+static struct cmd_node community_alias_node = {
+ .name = "community alias",
+ .node = COMMUNITY_ALIAS_NODE,
+ .prompt = "",
+ .config_write = bgp_community_alias_write,
+};
+
+void community_alias_vty(void)
+{
+ install_node(&community_alias_node);
+
+ /* Community-list. */
+ install_element(CONFIG_NODE, &bgp_community_alias_cmd);
+
+ bgp_community_alias_command_completion_setup();
+}