mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 18:56:53 +00:00
15573 lines
466 KiB
C
15573 lines
466 KiB
C
/* BGP VTY interface.
|
||
* Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
|
||
*
|
||
* This file is part of GNU Zebra.
|
||
*
|
||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||
* under the terms of the GNU General Public License as published by the
|
||
* Free Software Foundation; either version 2, or (at your option) any
|
||
* later version.
|
||
*
|
||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
* General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License along
|
||
* with this program; see the file COPYING; if not, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
|
||
#include <zebra.h>
|
||
|
||
#include "command.h"
|
||
#include "lib/json.h"
|
||
#include "lib/zclient.h"
|
||
#include "prefix.h"
|
||
#include "plist.h"
|
||
#include "buffer.h"
|
||
#include "linklist.h"
|
||
#include "stream.h"
|
||
#include "thread.h"
|
||
#include "log.h"
|
||
#include "memory.h"
|
||
#include "memory_vty.h"
|
||
#include "hash.h"
|
||
#include "queue.h"
|
||
#include "filter.h"
|
||
#include "frrstr.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_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_nexthop.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_addpath.h"
|
||
#include "bgpd/bgp_mac.h"
|
||
|
||
static struct peer_group *listen_range_exists(struct bgp *bgp,
|
||
struct prefix *range, int exact);
|
||
|
||
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;
|
||
break;
|
||
case SAFI_MULTICAST:
|
||
return BGP_IPV4M_NODE;
|
||
break;
|
||
case SAFI_LABELED_UNICAST:
|
||
return BGP_IPV4L_NODE;
|
||
break;
|
||
case SAFI_MPLS_VPN:
|
||
return BGP_VPNV4_NODE;
|
||
break;
|
||
case SAFI_FLOWSPEC:
|
||
return BGP_FLOWSPECV4_NODE;
|
||
default:
|
||
/* not expected */
|
||
return BGP_IPV4_NODE;
|
||
break;
|
||
}
|
||
break;
|
||
case AFI_IP6:
|
||
switch (safi) {
|
||
case SAFI_UNICAST:
|
||
return BGP_IPV6_NODE;
|
||
break;
|
||
case SAFI_MULTICAST:
|
||
return BGP_IPV6M_NODE;
|
||
break;
|
||
case SAFI_LABELED_UNICAST:
|
||
return BGP_IPV6L_NODE;
|
||
break;
|
||
case SAFI_MPLS_VPN:
|
||
return BGP_VPNV6_NODE;
|
||
break;
|
||
case SAFI_FLOWSPEC:
|
||
return BGP_FLOWSPECV6_NODE;
|
||
default:
|
||
/* not expected */
|
||
return BGP_IPV4_NODE;
|
||
break;
|
||
}
|
||
break;
|
||
case AFI_L2VPN:
|
||
return BGP_EVPN_NODE;
|
||
break;
|
||
case AFI_UNSPEC:
|
||
case AFI_MAX:
|
||
// We should never be here but to clarify the switch statement..
|
||
return BGP_IPV4_NODE;
|
||
break;
|
||
}
|
||
|
||
// Impossible to happen
|
||
return BGP_IPV4_NODE;
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
|
||
/*
|
||
* 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_out(vty, "%s\n",
|
||
json_object_to_json_string_ext(json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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_out(vty, "%s\n",
|
||
json_object_to_json_string_ext(json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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 int peer_address_self_check(struct bgp *bgp, union sockunion *su)
|
||
{
|
||
struct interface *ifp = NULL;
|
||
|
||
if (su->sa.sa_family == AF_INET)
|
||
ifp = if_lookup_by_ipv4_exact(&su->sin.sin_addr, bgp->vrf_id);
|
||
else if (su->sa.sa_family == AF_INET6)
|
||
ifp = if_lookup_by_ipv6_exact(&su->sin6.sin6_addr,
|
||
su->sin6.sin6_scope_id,
|
||
bgp->vrf_id);
|
||
|
||
if (ifp)
|
||
return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* 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)) {
|
||
vty_out(vty,
|
||
"%% Operation not allowed on a dynamic neighbor\n");
|
||
return NULL;
|
||
}
|
||
|
||
return peer;
|
||
}
|
||
|
||
if (group)
|
||
return group->conf;
|
||
|
||
vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
|
||
|
||
return NULL;
|
||
}
|
||
|
||
int bgp_vty_return(struct vty *vty, int ret)
|
||
{
|
||
const char *str = NULL;
|
||
|
||
switch (ret) {
|
||
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_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
|
||
str = "Local-AS allowed only for EBGP 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;
|
||
}
|
||
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:
|
||
vty_out(vty,
|
||
"%%BGP: Enable %s address family for the neighbor %s\n",
|
||
afi_safi_print(afi, safi), peer->host);
|
||
break;
|
||
case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
|
||
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);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* `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;
|
||
bool found = false;
|
||
struct peer *peer;
|
||
struct listnode *node, *nnode;
|
||
|
||
/* 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)) {
|
||
if (!peer->afc[afi][safi])
|
||
continue;
|
||
|
||
if (stype == BGP_CLEAR_SOFT_NONE)
|
||
ret = peer_clear(peer, &nnode);
|
||
else
|
||
ret = peer_clear_soft(peer, afi, safi, stype);
|
||
|
||
if (ret < 0)
|
||
bgp_clear_vty_error(vty, peer, afi, safi, ret);
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
}
|
||
|
||
if (!peer->afc[afi][safi])
|
||
ret = BGP_ERR_AF_UNCONFIGURED;
|
||
else if (stype == BGP_CLEAR_SOFT_NONE)
|
||
ret = peer_clear(peer, NULL);
|
||
else
|
||
ret = peer_clear_soft(peer, afi, safi, stype);
|
||
|
||
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)) {
|
||
if (!peer->afc[afi][safi])
|
||
continue;
|
||
|
||
if (stype == BGP_CLEAR_SOFT_NONE)
|
||
ret = peer_clear(peer, NULL);
|
||
else
|
||
ret = peer_clear_soft(peer, afi, safi, 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",
|
||
afi_safi_print(afi, safi), 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;
|
||
|
||
if (!peer->afc[afi][safi])
|
||
continue;
|
||
|
||
if (stype == BGP_CLEAR_SOFT_NONE)
|
||
ret = peer_clear(peer, &nnode);
|
||
else
|
||
ret = peer_clear_soft(peer, afi, safi, stype);
|
||
|
||
if (ret < 0)
|
||
bgp_clear_vty_error(vty, peer, afi, safi, ret);
|
||
else
|
||
found = true;
|
||
}
|
||
|
||
if (!found)
|
||
vty_out(vty,
|
||
"%%BGP: No external %s peer is configured\n",
|
||
afi_safi_print(afi, safi));
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* Clear all neighbors belonging to a specific AS. */
|
||
if (sort == clear_as) {
|
||
as_t as = strtoul(arg, NULL, 10);
|
||
|
||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||
if (peer->as != as)
|
||
continue;
|
||
|
||
if (!peer->afc[afi][safi])
|
||
ret = BGP_ERR_AF_UNCONFIGURED;
|
||
else if (stype == BGP_CLEAR_SOFT_NONE)
|
||
ret = peer_clear(peer, &nnode);
|
||
else
|
||
ret = peer_clear_soft(peer, afi, safi, 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 is configured with AS %s\n",
|
||
afi_safi_print(afi, safi), 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);
|
||
}
|
||
|
||
|
||
#ifndef VTYSH_EXTRACT_PL
|
||
#include "bgpd/bgp_vty_clippy.c"
|
||
#endif
|
||
|
||
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);
|
||
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 [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]",
|
||
ROUTER_STR
|
||
BGP_STR
|
||
AS_STR
|
||
BGP_INSTANCE_HELP_STR)
|
||
{
|
||
int idx_asn = 2;
|
||
int idx_view_vrf = 3;
|
||
int idx_vrf = 4;
|
||
int is_new_bgp = 0;
|
||
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 {
|
||
as = strtoul(argv[idx_asn]->arg, NULL, 10);
|
||
|
||
inst_type = BGP_INSTANCE_TYPE_DEFAULT;
|
||
if (argc > 3) {
|
||
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 (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
|
||
is_new_bgp = (bgp_lookup(as, name) == NULL);
|
||
|
||
ret = bgp_get(&bgp, &as, name, inst_type);
|
||
switch (ret) {
|
||
case BGP_ERR_AS_MISMATCH:
|
||
vty_out(vty, "BGP is already running; AS is %u\n", as);
|
||
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 %u\n",
|
||
as);
|
||
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.
|
||
*/
|
||
}
|
||
|
||
/* 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 [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]",
|
||
NO_STR
|
||
ROUTER_STR
|
||
BGP_STR
|
||
AS_STR
|
||
BGP_INSTANCE_HELP_STR)
|
||
{
|
||
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",
|
||
bgp->l3vni);
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
} else {
|
||
as = strtoul(argv[idx_asn]->arg, NULL, 10);
|
||
|
||
if (argc > 4)
|
||
name = argv[idx_vrf]->arg;
|
||
|
||
/* 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) {
|
||
vty_out(vty,
|
||
"%% Cannot delete default BGP instance. Dependent VRF instances exist\n");
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (bgp_vpn_leak_unimport(bgp, vty))
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
|
||
bgp_delete(bgp);
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
/* 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;
|
||
}
|
||
|
||
DEFUN (bgp_confederation_identifier,
|
||
bgp_confederation_identifier_cmd,
|
||
"bgp confederation identifier (1-4294967295)",
|
||
"BGP specific commands\n"
|
||
"AS confederation parameters\n"
|
||
"AS number\n"
|
||
"Set routing domain confederation AS\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
int idx_number = 3;
|
||
as_t as;
|
||
|
||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
|
||
bgp_confederation_id_set(bgp, as);
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (no_bgp_confederation_identifier,
|
||
no_bgp_confederation_identifier_cmd,
|
||
"no bgp confederation identifier [(1-4294967295)]",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"AS confederation parameters\n"
|
||
"AS number\n"
|
||
"Set routing domain confederation AS\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_confederation_id_unset(bgp);
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (bgp_confederation_peers,
|
||
bgp_confederation_peers_cmd,
|
||
"bgp confederation peers (1-4294967295)...",
|
||
"BGP specific commands\n"
|
||
"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++) {
|
||
as = strtoul(argv[i]->arg, NULL, 10);
|
||
|
||
if (bgp->as == as) {
|
||
vty_out(vty,
|
||
"%% Local member-AS not allowed in confed peer list\n");
|
||
continue;
|
||
}
|
||
|
||
bgp_confederation_peers_add(bgp, as);
|
||
}
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (no_bgp_confederation_peers,
|
||
no_bgp_confederation_peers_cmd,
|
||
"no bgp confederation peers (1-4294967295)...",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"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++) {
|
||
as = strtoul(argv[i]->arg, NULL, 10);
|
||
|
||
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;
|
||
|
||
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) {
|
||
THREAD_TIMER_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_update_delay_config_vty(struct vty *vty, const char *delay,
|
||
const char *wait)
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
uint16_t update_delay;
|
||
uint16_t establish_wait;
|
||
|
||
update_delay = strtoul(delay, NULL, 10);
|
||
|
||
if (!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> */
|
||
establish_wait = atoi(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);
|
||
|
||
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 (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
|
||
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");
|
||
}
|
||
}
|
||
|
||
|
||
/* Update-delay configuration */
|
||
DEFUN (bgp_update_delay,
|
||
bgp_update_delay_cmd,
|
||
"update-delay (0-3600)",
|
||
"Force initial delay for best-path and updates\n"
|
||
"Seconds\n")
|
||
{
|
||
int idx_number = 1;
|
||
return bgp_update_delay_config_vty(vty, argv[idx_number]->arg, NULL);
|
||
}
|
||
|
||
DEFUN (bgp_update_delay_establish_wait,
|
||
bgp_update_delay_establish_wait_cmd,
|
||
"update-delay (0-3600) (1-3600)",
|
||
"Force initial delay for best-path and updates\n"
|
||
"Seconds\n"
|
||
"Seconds\n")
|
||
{
|
||
int idx_number = 1;
|
||
int idx_number_2 = 2;
|
||
return bgp_update_delay_config_vty(vty, argv[idx_number]->arg,
|
||
argv[idx_number_2]->arg);
|
||
}
|
||
|
||
/* Update-delay deconfiguration */
|
||
DEFUN (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"
|
||
"Seconds\n"
|
||
"Seconds\n")
|
||
{
|
||
return bgp_update_delay_deconfig_vty(vty);
|
||
}
|
||
|
||
|
||
static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num,
|
||
char set)
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (set) {
|
||
uint32_t quanta = strtoul(num, NULL, 10);
|
||
atomic_store_explicit(&bgp->wpkt_quanta, quanta,
|
||
memory_order_relaxed);
|
||
} else {
|
||
atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
|
||
memory_order_relaxed);
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
static int bgp_rpkt_quanta_config_vty(struct vty *vty, const char *num,
|
||
char set)
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (set) {
|
||
uint32_t quanta = strtoul(num, NULL, 10);
|
||
atomic_store_explicit(&bgp->rpkt_quanta, quanta,
|
||
memory_order_relaxed);
|
||
} else {
|
||
atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
|
||
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 */
|
||
DEFUN (bgp_wpkt_quanta,
|
||
bgp_wpkt_quanta_cmd,
|
||
"write-quanta (1-10)",
|
||
"How many packets to write to peer socket per run\n"
|
||
"Number of packets\n")
|
||
{
|
||
int idx_number = 1;
|
||
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1);
|
||
}
|
||
|
||
DEFUN (no_bgp_wpkt_quanta,
|
||
no_bgp_wpkt_quanta_cmd,
|
||
"no write-quanta (1-10)",
|
||
NO_STR
|
||
"How many packets to write to peer socket per I/O cycle\n"
|
||
"Number of packets\n")
|
||
{
|
||
int idx_number = 2;
|
||
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
|
||
}
|
||
|
||
DEFUN (bgp_rpkt_quanta,
|
||
bgp_rpkt_quanta_cmd,
|
||
"read-quanta (1-10)",
|
||
"How many packets to read from peer socket per I/O cycle\n"
|
||
"Number of packets\n")
|
||
{
|
||
int idx_number = 1;
|
||
return bgp_rpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1);
|
||
}
|
||
|
||
DEFUN (no_bgp_rpkt_quanta,
|
||
no_bgp_rpkt_quanta_cmd,
|
||
"no read-quanta (1-10)",
|
||
NO_STR
|
||
"How many packets to read from peer socket per I/O cycle\n"
|
||
"Number of packets\n")
|
||
{
|
||
int idx_number = 2;
|
||
return bgp_rpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
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;
|
||
argv_find(argv, argc, "(0-4294967295)", &idx);
|
||
bgp->heuristic_coalesce = false;
|
||
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,
|
||
BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 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")
|
||
|
||
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 (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags,
|
||
BGP_FLAG_IBGP_MULTIPATH_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(bgp, keepalive, holdtime);
|
||
|
||
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_unset(bgp);
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
|
||
DEFUN (bgp_client_to_client_reflection,
|
||
bgp_client_to_client_reflection_cmd,
|
||
"bgp client-to-client reflection",
|
||
"BGP specific commands\n"
|
||
"Configure client to client route reflection\n"
|
||
"reflection of routes allowed\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"Configure client to client route reflection\n"
|
||
"reflection of routes allowed\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Allow comparing MED from different neighbors\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Allow comparing MED from different neighbors\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"Require in and out policy for eBGP peers (RFC8212)\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_ENABLED;
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,
|
||
"no bgp ebgp-requires-policy",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"Require in and out policy for eBGP peers (RFC8212)\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
|
||
/* "bgp deterministic-med" configuration. */
|
||
DEFUN (bgp_deterministic_med,
|
||
bgp_deterministic_med_cmd,
|
||
"bgp deterministic-med",
|
||
"BGP specific commands\n"
|
||
"Pick the best-MED path among paths advertised from the neighboring AS\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"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 (bgp_flag_check(bgp, 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 {
|
||
bgp_flag_unset(bgp, BGP_FLAG_DETERMINISTIC_MED);
|
||
bgp_recalculate_all_bestpaths(bgp);
|
||
}
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* "bgp graceful-restart" configuration. */
|
||
DEFUN (bgp_graceful_restart,
|
||
bgp_graceful_restart_cmd,
|
||
"bgp graceful-restart",
|
||
"BGP specific commands\n"
|
||
"Graceful restart capability parameters\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, BGP_FLAG_GRACEFUL_RESTART);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (no_bgp_graceful_restart,
|
||
no_bgp_graceful_restart_cmd,
|
||
"no bgp graceful-restart",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"Graceful restart capability parameters\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, BGP_FLAG_GRACEFUL_RESTART);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (bgp_graceful_restart_stalepath_time,
|
||
bgp_graceful_restart_stalepath_time_cmd,
|
||
"bgp graceful-restart stalepath-time (1-4095)",
|
||
"BGP specific commands\n"
|
||
"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 (1-4095)",
|
||
"BGP specific commands\n"
|
||
"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;
|
||
|
||
restart = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
bgp->restart_time = restart;
|
||
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 specific commands\n"
|
||
"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 [(1-4095)]",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"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);
|
||
|
||
bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (bgp_graceful_restart_preserve_fw,
|
||
bgp_graceful_restart_preserve_fw_cmd,
|
||
"bgp graceful-restart preserve-fw-state",
|
||
"BGP specific commands\n"
|
||
"Graceful restart capability parameters\n"
|
||
"Sets F-bit indication that fib is preserved while doing Graceful Restart\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Graceful restart capability parameters\n"
|
||
"Unsets F-bit indication that fib is preserved while doing Graceful Restart\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, BGP_FLAG_GR_PRESERVE_FWD);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* "bgp graceful-shutdown" configuration */
|
||
DEFUN (bgp_graceful_shutdown,
|
||
bgp_graceful_shutdown_cmd,
|
||
"bgp graceful-shutdown",
|
||
BGP_STR
|
||
"Graceful shutdown parameters\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (!bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||
bgp_flag_set(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN);
|
||
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);
|
||
}
|
||
|
||
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")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
|
||
bgp_flag_unset(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN);
|
||
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);
|
||
}
|
||
|
||
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);
|
||
bgp_flag_unset(bgp, 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);
|
||
bgp_flag_set(bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER);
|
||
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 specific commands\n"
|
||
"Change the default bestpath selection\n"
|
||
"Compare router-id for identical EBGP paths\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Change the default bestpath selection\n"
|
||
"Compare router-id for identical EBGP paths\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"Change the default bestpath selection\n"
|
||
"AS-path attribute\n"
|
||
"Ignore as-path length in selecting a route\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Change the default bestpath selection\n"
|
||
"AS-path attribute\n"
|
||
"Ignore as-path length in selecting a route\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"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);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"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);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"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;
|
||
bgp_flag_set(bgp, 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))
|
||
bgp_flag_set(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET);
|
||
else
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"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);
|
||
bgp_flag_unset(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX);
|
||
bgp_flag_unset(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET);
|
||
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 specific commands\n"
|
||
"Log neighbor up/down and reset reason\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Log neighbor up/down and reset reason\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"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))
|
||
bgp_flag_set(bgp, BGP_FLAG_MED_CONFED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "missing-as-worst", &idx))
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"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))
|
||
bgp_flag_unset(bgp, BGP_FLAG_MED_CONFED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "missing-as-worst", &idx))
|
||
bgp_flag_unset(bgp, BGP_FLAG_MED_MISSING_AS_WORST);
|
||
|
||
bgp_recalculate_all_bestpaths(bgp);
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* "no bgp default ipv4-unicast". */
|
||
DEFUN (no_bgp_default_ipv4_unicast,
|
||
no_bgp_default_ipv4_unicast_cmd,
|
||
"no bgp default ipv4-unicast",
|
||
NO_STR
|
||
"BGP specific commands\n"
|
||
"Configure BGP defaults\n"
|
||
"Activate ipv4-unicast for a peer by default\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, BGP_FLAG_NO_DEFAULT_IPV4);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (bgp_default_ipv4_unicast,
|
||
bgp_default_ipv4_unicast_cmd,
|
||
"bgp default ipv4-unicast",
|
||
"BGP specific commands\n"
|
||
"Configure BGP defaults\n"
|
||
"Activate ipv4-unicast for a peer by default\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, BGP_FLAG_NO_DEFAULT_IPV4);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* Display hostname in certain command outputs */
|
||
DEFUN (bgp_default_show_hostname,
|
||
bgp_default_show_hostname_cmd,
|
||
"bgp default show-hostname",
|
||
"BGP specific commands\n"
|
||
"Configure BGP defaults\n"
|
||
"Show hostname in certain command outputs\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Configure BGP defaults\n"
|
||
"Show hostname in certain command outputs\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, BGP_FLAG_SHOW_HOSTNAME);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
/* "bgp network import-check" configuration. */
|
||
DEFUN (bgp_network_import_check,
|
||
bgp_network_import_check_cmd,
|
||
"bgp network import-check",
|
||
"BGP specific commands\n"
|
||
"BGP network command\n"
|
||
"Check BGP network route exists in IGP\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
if (!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) {
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"BGP network command\n"
|
||
"Check BGP network route exists in IGP\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) {
|
||
bgp_flag_unset(bgp, 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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"Allow modifications made by out route-map\n"
|
||
"on ibgp neighbors\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (!bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Allow modifications made by out route-map\n"
|
||
"on ibgp neighbors\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
|
||
if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
|
||
bgp_flag_unset(bgp, 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-5000)",
|
||
"BGP specific commands\n"
|
||
"Configure BGP defaults\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-5000)]",
|
||
"BGP specific commands\n"
|
||
"Configure BGP defaults\n"
|
||
"unset maximum number of BGP Dynamic Neighbors that can be created\n"
|
||
"Configure Dynamic Neighbors listen limit value to default\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 specific commands\n"
|
||
"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 specific commands\n"
|
||
"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, "WORD", &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;
|
||
char buf[PREFIX2STR_BUFFER];
|
||
|
||
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)) {
|
||
prefix2str(range, buf, sizeof(buf));
|
||
vty_out(vty,
|
||
" bgp listen range %s peer-group %s\n",
|
||
buf, group->name);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
DEFUN (bgp_disable_connected_route_check,
|
||
bgp_disable_connected_route_check_cmd,
|
||
"bgp disable-ebgp-connected-route-check",
|
||
"BGP specific commands\n"
|
||
"Disable checking if nexthop is connected on ebgp sessions\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_set(bgp, 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 specific commands\n"
|
||
"Disable checking if nexthop is connected on ebgp sessions\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
bgp_flag_unset(bgp, 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, afi_t afi, safi_t safi)
|
||
{
|
||
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 {
|
||
/* Get AS number. */
|
||
as = strtoul(as_str, NULL, 10);
|
||
}
|
||
|
||
/* 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, afi,
|
||
safi);
|
||
|
||
/* if not interface peer, check peer-group settings */
|
||
if (ret < 0 && !peer) {
|
||
ret = peer_group_remote_as(bgp, peer_str, &as, as_type);
|
||
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, afi, safi);
|
||
}
|
||
|
||
/* This peer belongs to peer group. */
|
||
switch (ret) {
|
||
case BGP_ERR_PEER_GROUP_MEMBER:
|
||
vty_out(vty,
|
||
"%% Peer-group member cannot override remote-as of peer-group\n");
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
|
||
vty_out(vty,
|
||
"%% Peer-group members must be all internal or all external\n");
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
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;
|
||
}
|
||
|
||
DEFUN (neighbor_remote_as,
|
||
neighbor_remote_as_cmd,
|
||
"neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <(1-4294967295)|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, AFI_IP,
|
||
SAFI_UNICAST);
|
||
}
|
||
|
||
static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
|
||
afi_t afi, safi_t safi, 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;
|
||
union sockunion su;
|
||
|
||
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. */
|
||
as = strtoul(as_str, NULL, 10);
|
||
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,
|
||
afi, safi);
|
||
} else {
|
||
if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)
|
||
&& afi == AFI_IP && safi == SAFI_UNICAST)
|
||
peer = peer_create(NULL, conf_if, bgp, bgp->as, as,
|
||
as_type, 0, 0, NULL);
|
||
else
|
||
peer = peer_create(NULL, conf_if, bgp, bgp->as, as,
|
||
as_type, afi, safi, NULL);
|
||
|
||
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->status)) {
|
||
peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
|
||
bgp_notify_send(peer, 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, &su, 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, AFI_IP, SAFI_UNICAST, 0,
|
||
argv[idx_peer_group_word]->arg, NULL);
|
||
else
|
||
return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP,
|
||
SAFI_UNICAST, 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, AFI_IP, SAFI_UNICAST, 1,
|
||
argv[idx_peer_group_word]->arg, NULL);
|
||
|
||
return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP,
|
||
SAFI_UNICAST, 1, NULL, NULL);
|
||
}
|
||
|
||
|
||
DEFUN (neighbor_interface_config_remote_as,
|
||
neighbor_interface_config_remote_as_cmd,
|
||
"neighbor WORD interface remote-as <(1-4294967295)|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, AFI_IP,
|
||
SAFI_UNICAST, 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 <(1-4294967295)|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, AFI_IP,
|
||
SAFI_UNICAST, 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_delete(peer);
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
group = peer_group_lookup(bgp, argv[idx_peer]->arg);
|
||
if (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;
|
||
peer_delete(peer);
|
||
if (other && other->status != Deleted)
|
||
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_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_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 <(1-4294967295)|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);
|
||
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 (1-4294967295)",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Specify a local-as number\n"
|
||
"AS number 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;
|
||
|
||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
ret = peer_local_as_set(peer, as, 0, 0);
|
||
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 (1-4294967295) no-prepend",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Specify a local-as number\n"
|
||
"AS number 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;
|
||
|
||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
ret = peer_local_as_set(peer, as, 1, 0);
|
||
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 (1-4294967295) no-prepend replace-as",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Specify a local-as number\n"
|
||
"AS number 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;
|
||
|
||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
ret = peer_local_as_set(peer, as, 1, 1);
|
||
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 [(1-4294967295) [no-prepend [replace-as]]]",
|
||
NO_STR
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Specify a local-as number\n"
|
||
"AS number 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);
|
||
|
||
if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) {
|
||
vty_out(vty,
|
||
"%% Peer with AS %u cannot be in this peer-group, members must be all internal or all external\n",
|
||
as);
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
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")
|
||
|
||
static int peer_flag_modify_vty(struct vty *vty, const char *ip_str,
|
||
uint32_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, uint32_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,
|
||
uint32_t flag)
|
||
{
|
||
return peer_flag_modify_vty(vty, ip_str, flag, 0);
|
||
}
|
||
|
||
/* 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 (draft-ietf-idr-shutdown-06)\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 (draft-ietf-idr-shutdown-06)\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")
|
||
|
||
/* 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;
|
||
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;
|
||
return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
|
||
PEER_FLAG_CAPABILITY_ENHE);
|
||
}
|
||
|
||
static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
|
||
afi_t afi, safi_t safi, uint32_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, uint32_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, uint32_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_peer = 1;
|
||
int idx_send_recv = 5;
|
||
uint16_t flag = 0;
|
||
|
||
if (strmatch(argv[idx_send_recv]->text, "send"))
|
||
flag = PEER_FLAG_ORF_PREFIX_SM;
|
||
else if (strmatch(argv[idx_send_recv]->text, "receive"))
|
||
flag = PEER_FLAG_ORF_PREFIX_RM;
|
||
else if (strmatch(argv[idx_send_recv]->text, "both"))
|
||
flag = PEER_FLAG_ORF_PREFIX_SM | PEER_FLAG_ORF_PREFIX_RM;
|
||
else {
|
||
vty_out(vty, "%% BGP invalid orf prefix-list option\n");
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
|
||
return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
|
||
bgp_node_safi(vty), flag);
|
||
}
|
||
|
||
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_peer = 2;
|
||
int idx_send_recv = 6;
|
||
uint16_t flag = 0;
|
||
|
||
if (strmatch(argv[idx_send_recv]->text, "send"))
|
||
flag = PEER_FLAG_ORF_PREFIX_SM;
|
||
else if (strmatch(argv[idx_send_recv]->text, "receive"))
|
||
flag = PEER_FLAG_ORF_PREFIX_RM;
|
||
else if (strmatch(argv[idx_send_recv]->text, "both"))
|
||
flag = PEER_FLAG_ORF_PREFIX_SM | PEER_FLAG_ORF_PREFIX_RM;
|
||
else {
|
||
vty_out(vty, "%% BGP invalid orf prefix-list option\n");
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
|
||
return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
|
||
bgp_node_afi(vty), bgp_node_safi(vty),
|
||
flag);
|
||
}
|
||
|
||
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")
|
||
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
uint32_t flag = 0;
|
||
const char *type = argv[argc - 1]->text;
|
||
|
||
if (strmatch(type, "standard")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
} else if (strmatch(type, "extended")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
} else if (strmatch(type, "large")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY);
|
||
} else if (strmatch(type, "both")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
} else { /* if (strmatch(type, "all")) */
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY);
|
||
}
|
||
|
||
return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty),
|
||
bgp_node_safi(vty), flag);
|
||
}
|
||
|
||
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")
|
||
{
|
||
int idx_peer = 2;
|
||
uint32_t flag = 0;
|
||
const char *type = argv[argc - 1]->text;
|
||
|
||
if (strmatch(type, "standard")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
} else if (strmatch(type, "extended")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
} else if (strmatch(type, "large")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY);
|
||
} else if (strmatch(type, "both")) {
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
} else { /* if (strmatch(type, "all")) */
|
||
SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY);
|
||
SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY);
|
||
}
|
||
|
||
return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg,
|
||
bgp_node_afi(vty), bgp_node_safi(vty),
|
||
flag);
|
||
}
|
||
|
||
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;
|
||
uint16_t flags = 0;
|
||
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 (argv_find(argv, argc, "as-path", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "next-hop", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "med", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||
|
||
/* no flags means all of them! */
|
||
if (!flags) {
|
||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||
} else {
|
||
if (!CHECK_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED)
|
||
&& peer_af_flag_check(peer, afi, safi,
|
||
PEER_FLAG_AS_PATH_UNCHANGED)) {
|
||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||
PEER_FLAG_AS_PATH_UNCHANGED);
|
||
}
|
||
|
||
if (!CHECK_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED)
|
||
&& peer_af_flag_check(peer, afi, safi,
|
||
PEER_FLAG_NEXTHOP_UNCHANGED)) {
|
||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||
PEER_FLAG_NEXTHOP_UNCHANGED);
|
||
}
|
||
|
||
if (!CHECK_FLAG(flags, PEER_FLAG_MED_UNCHANGED)
|
||
&& peer_af_flag_check(peer, afi, safi,
|
||
PEER_FLAG_MED_UNCHANGED)) {
|
||
peer_af_flag_unset_vty(vty, peer_str, afi, safi,
|
||
PEER_FLAG_MED_UNCHANGED);
|
||
}
|
||
}
|
||
|
||
return peer_af_flag_set_vty(vty, peer_str, afi, safi, flags);
|
||
}
|
||
|
||
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 = argv[2]->arg;
|
||
uint16_t flags = 0;
|
||
|
||
if (argv_find(argv, argc, "as-path", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "next-hop", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||
idx = 0;
|
||
if (argv_find(argv, argc, "med", &idx))
|
||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||
|
||
if (!flags) // no flags means all of them!
|
||
{
|
||
SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED);
|
||
SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED);
|
||
SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED);
|
||
}
|
||
|
||
return peer_af_flag_unset_vty(vty, peer, bgp_node_afi(vty),
|
||
bgp_node_safi(vty), flags);
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
/* 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);
|
||
}
|
||
|
||
|
||
/* 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 WORD",
|
||
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 WORD",
|
||
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 WORD]",
|
||
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 WORD]",
|
||
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_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> port (0-65535)",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR
|
||
"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> port [(0-65535)]",
|
||
NO_STR
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR
|
||
"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);
|
||
}
|
||
|
||
|
||
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) {
|
||
BGP_TIMER_OFF(bm->t_rmap_update);
|
||
thread_execute(bm->master, bgp_route_map_update_timer,
|
||
NULL, 0);
|
||
}
|
||
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|WORD> interface WORD",
|
||
NO_STR
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"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 <(1-199)|(1300-2699)|WORD> <in|out>",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Filter updates to/from this neighbor\n"
|
||
"IP access-list number\n"
|
||
"IP access-list number (expanded range)\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 <(1-199)|(1300-2699)|WORD> <in|out>",
|
||
NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
||
"Filter updates to/from this neighbor\n"
|
||
"IP access-list number\n"
|
||
"IP access-list number (expanded range)\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 <(1-199)|(1300-2699)|WORD> <in|out>",
|
||
NO_STR
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Filter updates to/from this neighbor\n"
|
||
"IP access-list number\n"
|
||
"IP access-list number (expanded range)\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 <(1-199)|(1300-2699)|WORD> <in|out>",
|
||
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
||
"Filter updates to/from this neighbor\n"
|
||
"IP access-list number\n"
|
||
"IP access-list number (expanded range)\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 WORD <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 WORD <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 WORD <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 WORD <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 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 WORD <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 WORD <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 WORD <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 WORD <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)
|
||
{
|
||
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);
|
||
|
||
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 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)",
|
||
NEIGHBOR_STR
|
||
NEIGHBOR_ADDR_STR2
|
||
"Maximum number of prefix accept from this peer\n"
|
||
"maximum no. of prefix limit\n")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
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);
|
||
}
|
||
|
||
ALIAS_HIDDEN(neighbor_maximum_prefix, neighbor_maximum_prefix_hidden_cmd,
|
||
"neighbor <A.B.C.D|X:X::X:X|WORD> maximum-prefix (1-4294967295)",
|
||
NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
||
"Maximum number of prefix accept from this peer\n"
|
||
"maximum no. of prefix limit\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)",
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
int idx_number_2 = 4;
|
||
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);
|
||
}
|
||
|
||
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)",
|
||
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")
|
||
|
||
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",
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
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);
|
||
}
|
||
|
||
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",
|
||
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")
|
||
|
||
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",
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
int idx_number_2 = 4;
|
||
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);
|
||
}
|
||
|
||
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",
|
||
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")
|
||
|
||
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)",
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
int idx_number_2 = 5;
|
||
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);
|
||
}
|
||
|
||
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)",
|
||
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")
|
||
|
||
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)",
|
||
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")
|
||
{
|
||
int idx_peer = 1;
|
||
int idx_number = 3;
|
||
int idx_number_2 = 4;
|
||
int idx_number_3 = 6;
|
||
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);
|
||
}
|
||
|
||
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)",
|
||
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")
|
||
|
||
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]]",
|
||
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")
|
||
{
|
||
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]]",
|
||
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")
|
||
|
||
|
||
/* "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 occurences 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 occurences 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 occurences 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 occurences 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 > 1)) {
|
||
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));
|
||
}
|
||
|
||
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);
|
||
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);
|
||
|
||
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")
|
||
|
||
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);
|
||
|
||
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);
|
||
|
||
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")
|
||
|
||
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
|
||
struct ecommunity **list)
|
||
{
|
||
struct ecommunity *ecom = NULL;
|
||
struct ecommunity *ecomadd;
|
||
|
||
for (; argc; --argc, ++argv) {
|
||
|
||
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;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
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 = prd;
|
||
SET_FLAG(bgp->vpn_policy[afi].flags,
|
||
BGP_VPN_POLICY_TOVPN_RD_SET);
|
||
} else {
|
||
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,
|
||
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;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
/* 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);
|
||
|
||
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")
|
||
|
||
DEFPY (af_nexthop_vpn_export,
|
||
af_nexthop_vpn_export_cmd,
|
||
"[no] nexthop vpn export <A.B.C.D|X:X::X:X>$nexthop_str",
|
||
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;
|
||
int idx = 0;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
if (yes) {
|
||
if (!sockunion2hostprefix(nexthop_str, &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 (yes) {
|
||
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;
|
||
}
|
||
|
||
ALIAS (af_nexthop_vpn_export,
|
||
af_no_nexthop_vpn_export_cmd,
|
||
"no nexthop vpn export",
|
||
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")
|
||
|
||
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};
|
||
vpn_policy_direction_t dir;
|
||
afi_t afi;
|
||
int idx = 0;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
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);
|
||
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};
|
||
vpn_policy_direction_t dir;
|
||
afi_t afi;
|
||
int idx = 0;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
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,
|
||
"[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);
|
||
vpn_policy_direction_t dir = BGP_VPN_POLICY_DIR_FROMVPN;
|
||
afi_t afi;
|
||
int idx = 0;
|
||
int yes = 1;
|
||
struct bgp *bgp_default;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
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(&bgp_default, &as, NULL,
|
||
BGP_INSTANCE_TYPE_DEFAULT);
|
||
|
||
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 (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_import_vrf_route_map, af_no_import_vrf_route_map_cmd,
|
||
"no import vrf route-map",
|
||
NO_STR
|
||
"Import routes from another VRF\n"
|
||
"Vrf routes being filtered\n"
|
||
"Specify route map\n")
|
||
|
||
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 (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(&bgp_default, &as, NULL,
|
||
BGP_INSTANCE_TYPE_DEFAULT);
|
||
|
||
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(&vrf_bgp, &as, import_name, bgp_type);
|
||
|
||
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;
|
||
int yes = 1;
|
||
int flag;
|
||
vpn_policy_direction_t dir;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
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_get_default(), bgp);
|
||
}
|
||
} else {
|
||
if (previous_state) {
|
||
/* trigger un-export current vrf */
|
||
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
|
||
}
|
||
UNSET_FLAG(bgp->af_flags[afi][safi], flag);
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFPY (af_routetarget_import,
|
||
af_routetarget_import_cmd,
|
||
"[no] <rt|route-target> redirect import RTLIST...",
|
||
NO_STR
|
||
"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)\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
int ret;
|
||
struct ecommunity *ecom = NULL;
|
||
afi_t afi;
|
||
int idx = 0;
|
||
int yes = 1;
|
||
|
||
if (argv_find(argv, argc, "no", &idx))
|
||
yes = 0;
|
||
|
||
afi = vpn_policy_getafi(vty, bgp, false);
|
||
if (afi == AFI_MAX)
|
||
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);
|
||
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"
|
||
"Address Family\n"
|
||
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"
|
||
"Address Family\n"
|
||
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"
|
||
"Address Family\n"
|
||
"Address Family modifier\n")
|
||
{
|
||
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"
|
||
"Address Family\n"
|
||
"Address Family modifier\n")
|
||
{
|
||
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"
|
||
"Address Family\n"
|
||
"Address Family modifier\n")
|
||
{
|
||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||
vty->node = BGP_EVPN_NODE;
|
||
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_node *rn;
|
||
struct bgp_node *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 (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
|
||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||
continue;
|
||
|
||
table = bgp_node_get_bgp_table_info(rn);
|
||
if (table != NULL) {
|
||
|
||
if ((rm = bgp_node_match(table, &match))
|
||
!= NULL) {
|
||
if (rm->p.prefixlen
|
||
== match.prefixlen) {
|
||
SET_FLAG(rm->flags,
|
||
BGP_NODE_USER_CLEAR);
|
||
bgp_process(bgp, rm, afi, safi);
|
||
}
|
||
bgp_unlock_node(rm);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if ((rn = bgp_node_match(rib, &match)) != NULL) {
|
||
if (rn->p.prefixlen == match.prefixlen) {
|
||
SET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
|
||
bgp_process(bgp, rn, afi, safi);
|
||
}
|
||
bgp_unlock_node(rn);
|
||
}
|
||
}
|
||
|
||
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|X:X::X:X|WORD|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out>]",
|
||
CLEAR_STR
|
||
IP_STR
|
||
BGP_STR
|
||
BGP_INSTANCE_HELP_STR
|
||
BGP_AFI_HELP_STR
|
||
"Address Family\n"
|
||
BGP_SAFI_WITH_LABEL_HELP_STR
|
||
"Address Family modifier\n"
|
||
"Clear all peers\n"
|
||
"BGP neighbor address to clear\n"
|
||
"BGP IPv6 neighbor to clear\n"
|
||
"BGP neighbor on interface to clear\n"
|
||
"Clear peers with the AS number\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)
|
||
{
|
||
char *vrf = NULL;
|
||
|
||
afi_t afi = AFI_IP6;
|
||
safi_t safi = SAFI_UNICAST;
|
||
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|(1-4294967295)|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, "(1-4294967295)", &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>] */
|
||
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
|
||
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
|
||
"Address Family\n"
|
||
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
|
||
"Address Family\n"
|
||
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%u)\n", bgp->name ? bgp->name : "(null)",
|
||
bgp->as);
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (show_bgp_vrfs,
|
||
show_bgp_vrfs_cmd,
|
||
"show [ip] bgp vrfs [json]",
|
||
SHOW_STR
|
||
IP_STR
|
||
BGP_STR
|
||
"Show BGP VRFs\n"
|
||
JSON_STR)
|
||
{
|
||
char buf[ETHER_ADDR_STRLEN];
|
||
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;
|
||
int count = 0;
|
||
|
||
if (uj) {
|
||
json = json_object_new_object();
|
||
json_vrfs = json_object_new_object();
|
||
}
|
||
|
||
for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) {
|
||
const char *name, *type;
|
||
struct peer *peer;
|
||
struct listnode *node2, *nnode2;
|
||
int peers_cfg, peers_estb;
|
||
json_object *json_vrf = NULL;
|
||
|
||
/* 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", "#PeersVfg",
|
||
"#PeersEstb", "Name");
|
||
vty_out(vty, "%11s %-16s %-21s %-6s\n", " ",
|
||
"L3-VNI", "RouterMAC", "Interface");
|
||
}
|
||
|
||
peers_cfg = peers_estb = 0;
|
||
if (uj)
|
||
json_vrf = json_object_new_object();
|
||
|
||
|
||
for (ALL_LIST_ELEMENTS(bgp->peer, node2, nnode2, peer)) {
|
||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
||
continue;
|
||
peers_cfg++;
|
||
if (peer->status == Established)
|
||
peers_estb++;
|
||
}
|
||
|
||
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
|
||
name = VRF_DEFAULT_NAME;
|
||
type = "DFLT";
|
||
} else {
|
||
name = bgp->name;
|
||
type = "VRF";
|
||
}
|
||
|
||
|
||
if (uj) {
|
||
int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
|
||
? -1
|
||
: (int64_t)bgp->vrf_id;
|
||
json_object_string_add(json_vrf, "type", type);
|
||
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
|
||
json_object_string_add(json_vrf, "routerId",
|
||
inet_ntoa(bgp->router_id));
|
||
json_object_int_add(json_vrf, "numConfiguredPeers",
|
||
peers_cfg);
|
||
json_object_int_add(json_vrf, "numEstablishedPeers",
|
||
peers_estb);
|
||
|
||
json_object_int_add(json_vrf, "l3vni", bgp->l3vni);
|
||
json_object_string_add(
|
||
json_vrf, "rmac",
|
||
prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
|
||
json_object_string_add(json_vrf, "interface",
|
||
ifindex2ifname(bgp->l3vni_svi_ifindex,
|
||
bgp->vrf_id));
|
||
json_object_object_add(json_vrfs, name, json_vrf);
|
||
} else {
|
||
vty_out(vty,
|
||
"%4s %-5d %-16s %-9u %-10u %-37s\n",
|
||
type,
|
||
bgp->vrf_id == VRF_UNKNOWN ? -1
|
||
: (int)bgp->vrf_id,
|
||
inet_ntoa(bgp->router_id), peers_cfg,
|
||
peers_estb, name);
|
||
vty_out(vty,"%11s %-16u %-21s %-20s\n", " ",
|
||
bgp->l3vni,
|
||
prefix_mac2str(&bgp->rmac, buf, sizeof(buf)),
|
||
ifindex2ifname(bgp->l3vni_svi_ifindex,
|
||
bgp->vrf_id));
|
||
}
|
||
}
|
||
|
||
if (uj) {
|
||
json_object_object_add(json, "vrfs", json_vrfs);
|
||
|
||
json_object_int_add(json, "totalVrfs", count);
|
||
|
||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||
json, JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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: %s, count: %d\n", inet_ntoa(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_node)));
|
||
|
||
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)));
|
||
|
||
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 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 (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE))
|
||
json_object_string_add(bestpath, "asPath", "ignore");
|
||
|
||
if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED))
|
||
json_object_string_add(bestpath, "asPath", "confed");
|
||
|
||
if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
|
||
if (bgp_flag_check(bgp, 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 (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
|
||
json_object_string_add(bestpath, "compareRouterId", "true");
|
||
if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
|
||
|| bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
|
||
if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
|
||
json_object_string_add(bestpath, "med", "confed");
|
||
if (bgp_flag_check(bgp, 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);
|
||
}
|
||
|
||
/* Show BGP peer's summary information. */
|
||
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||
bool use_json)
|
||
{
|
||
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;
|
||
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;
|
||
|
||
/* 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();
|
||
} 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 (!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
|
||
&& bgp_flag_check(bgp,
|
||
BGP_FLAG_SHOW_HOSTNAME))
|
||
sprintf(neighbor_buf, "%s%s(%s) ",
|
||
dn_flag, peer->hostname,
|
||
peer->host);
|
||
else
|
||
sprintf(neighbor_buf, "%s%s ", dn_flag,
|
||
peer->host);
|
||
|
||
len = strlen(neighbor_buf);
|
||
|
||
if (len > max_neighbor_width)
|
||
max_neighbor_width = len;
|
||
}
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
|
||
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_add(
|
||
json, "routerId",
|
||
inet_ntoa(bgp->router_id));
|
||
json_object_int_add(json, "as", bgp->as);
|
||
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 %s, local AS number %u vrf-id %d",
|
||
inet_ntoa(bgp->router_id), bgp->as,
|
||
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_node));
|
||
|
||
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 (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_node)));
|
||
|
||
/* 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");
|
||
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,
|
||
"V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n");
|
||
}
|
||
}
|
||
|
||
count++;
|
||
|
||
if (use_json) {
|
||
json_peer = json_object_new_object();
|
||
|
||
if (peer_dynamic_neighbor(peer)) {
|
||
dn_count++;
|
||
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, "remoteAs", peer->as);
|
||
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));
|
||
|
||
json_object_int_add(json_peer, "tableVersion",
|
||
peer->version[afi][safi]);
|
||
json_object_int_add(json_peer, "outq",
|
||
peer->obuf->count);
|
||
json_object_int_add(json_peer, "inq", 0);
|
||
peer_uptime(peer->uptime, timebuf, BGP_UPTIME_LEN,
|
||
use_json, json_peer);
|
||
|
||
/*
|
||
* Adding "pfxRcd" field to match with the corresponding
|
||
* CLI. "prefixReceivedCount" will be deprecated in
|
||
* future.
|
||
*/
|
||
json_object_int_add(json_peer, "prefixReceivedCount",
|
||
peer->pcount[afi][pfx_rcd_safi]);
|
||
json_object_int_add(json_peer, "pfxRcd",
|
||
peer->pcount[afi][pfx_rcd_safi]);
|
||
|
||
paf = peer_af_find(peer, afi, pfx_rcd_safi);
|
||
if (paf && PAF_SUBGRP(paf))
|
||
json_object_int_add(json_peer,
|
||
"pfxSnt",
|
||
(PAF_SUBGRP(paf))->scount);
|
||
|
||
if (CHECK_FLAG(peer->flags, PEER_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->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->status,
|
||
NULL));
|
||
|
||
if (peer->conf_if)
|
||
json_object_string_add(json_peer, "idType",
|
||
"interface");
|
||
else if (peer->su.sa.sa_family == AF_INET)
|
||
json_object_string_add(json_peer, "idType",
|
||
"ipv4");
|
||
else if (peer->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 {
|
||
memset(dn_flag, '\0', sizeof(dn_flag));
|
||
if (peer_dynamic_neighbor(peer)) {
|
||
dn_count++;
|
||
dn_flag[0] = '*';
|
||
}
|
||
|
||
if (peer->hostname
|
||
&& bgp_flag_check(bgp, 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, "4 %10u %7u %7u %8" PRIu64 " %4d %4zd %8s",
|
||
peer->as, PEER_TOTAL_RX(peer),
|
||
PEER_TOTAL_TX(peer), peer->version[afi][safi],
|
||
0, peer->obuf->count,
|
||
peer_uptime(peer->uptime, timebuf,
|
||
BGP_UPTIME_LEN, 0, NULL));
|
||
|
||
if (peer->status == Established)
|
||
if (peer->afc_recv[afi][safi])
|
||
vty_out(vty, " %12ld",
|
||
peer->pcount[afi]
|
||
[pfx_rcd_safi]);
|
||
else
|
||
vty_out(vty, " NoNeg");
|
||
else {
|
||
if (CHECK_FLAG(peer->flags, PEER_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->status, NULL));
|
||
}
|
||
vty_out(vty, "\n");
|
||
}
|
||
}
|
||
|
||
if (use_json) {
|
||
json_object_object_add(json, "peers", json_peers);
|
||
|
||
json_object_int_add(json, "totalPeers", count);
|
||
json_object_int_add(json, "dynamicPeers", dn_count);
|
||
|
||
bgp_show_bestpath_json(bgp, json);
|
||
|
||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||
json, JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(json);
|
||
} else {
|
||
if (count)
|
||
vty_out(vty, "\nTotal number of neighbors %d\n", count);
|
||
else {
|
||
vty_out(vty, "No %s neighbor is configured\n",
|
||
afi_safi_print(afi, safi));
|
||
}
|
||
|
||
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, bool use_json)
|
||
{
|
||
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;
|
||
|
||
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\":",
|
||
afi_safi_json(afi,
|
||
safi));
|
||
} else {
|
||
vty_out(vty, "\n%s Summary:\n",
|
||
afi_safi_print(afi,
|
||
safi));
|
||
}
|
||
}
|
||
bgp_show_summary(vty, bgp, afi, safi, use_json);
|
||
}
|
||
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\n");
|
||
}
|
||
}
|
||
|
||
static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
|
||
safi_t safi, bool use_json)
|
||
{
|
||
struct listnode *node, *nnode;
|
||
struct bgp *bgp;
|
||
int 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 (!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);
|
||
}
|
||
bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
|
||
}
|
||
|
||
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, bool use_json)
|
||
{
|
||
struct bgp *bgp;
|
||
|
||
if (name) {
|
||
if (strmatch(name, "all")) {
|
||
bgp_show_all_instances_summary_vty(vty, afi, safi,
|
||
use_json);
|
||
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;
|
||
}
|
||
|
||
bgp_show_summary_afi_safi(vty, bgp, afi, safi,
|
||
use_json);
|
||
return CMD_SUCCESS;
|
||
}
|
||
}
|
||
|
||
bgp = bgp_get_default();
|
||
|
||
if (bgp)
|
||
bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
|
||
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. */
|
||
DEFUN (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"]] summary [json]",
|
||
SHOW_STR
|
||
IP_STR
|
||
BGP_STR
|
||
BGP_INSTANCE_HELP_STR
|
||
BGP_AFI_HELP_STR
|
||
BGP_SAFI_WITH_LABEL_HELP_STR
|
||
"Summary of BGP neighbor status\n"
|
||
JSON_STR)
|
||
{
|
||
char *vrf = NULL;
|
||
afi_t afi = AFI_MAX;
|
||
safi_t safi = SAFI_MAX;
|
||
|
||
int idx = 0;
|
||
|
||
/* 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);
|
||
}
|
||
|
||
bool uj = use_json(argc, argv);
|
||
|
||
return bgp_show_summary_vty(vty, vrf, afi, safi, uj);
|
||
}
|
||
|
||
const char *afi_safi_print(afi_t afi, safi_t safi)
|
||
{
|
||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
||
return "IPv4 Unicast";
|
||
else if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||
return "IPv4 Multicast";
|
||
else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
|
||
return "IPv4 Labeled Unicast";
|
||
else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
|
||
return "IPv4 VPN";
|
||
else if (afi == AFI_IP && safi == SAFI_ENCAP)
|
||
return "IPv4 Encap";
|
||
else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
|
||
return "IPv4 Flowspec";
|
||
else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
||
return "IPv6 Unicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
||
return "IPv6 Multicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
|
||
return "IPv6 Labeled Unicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
|
||
return "IPv6 VPN";
|
||
else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
|
||
return "IPv6 Encap";
|
||
else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
|
||
return "IPv6 Flowspec";
|
||
else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
|
||
return "L2VPN EVPN";
|
||
else
|
||
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
|
||
*/
|
||
const char *afi_safi_json(afi_t afi, safi_t safi)
|
||
{
|
||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
||
return "ipv4Unicast";
|
||
else if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||
return "ipv4Multicast";
|
||
else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
|
||
return "ipv4LabeledUnicast";
|
||
else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
|
||
return "ipv4Vpn";
|
||
else if (afi == AFI_IP && safi == SAFI_ENCAP)
|
||
return "ipv4Encap";
|
||
else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
|
||
return "ipv4Flowspec";
|
||
else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
||
return "ipv6Unicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
||
return "ipv6Multicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
|
||
return "ipv6LabeledUnicast";
|
||
else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
|
||
return "ipv6Vpn";
|
||
else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
|
||
return "ipv6Encap";
|
||
else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
|
||
return "ipv6Flowspec";
|
||
else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
|
||
return "l2VpnEvpn";
|
||
else
|
||
return "Unknown";
|
||
}
|
||
|
||
/* 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 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_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_prefB = NULL;
|
||
json_object *json_addr = 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_OLD_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_OLD_RCV)) {
|
||
json_object_int_add(json_af, "orfOldType",
|
||
ORF_TYPE_PREFIX_OLD);
|
||
json_prefB = 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_OLD_RCV,
|
||
PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json,
|
||
json_prefB);
|
||
json_object_object_add(json_af, "orfOldPrefixList",
|
||
json_prefB);
|
||
}
|
||
|
||
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_SM_OLD_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)
|
||
|| CHECK_FLAG(p->af_cap[afi][safi],
|
||
PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
|
||
json_object_object_add(json_addr, "afDependentCap",
|
||
json_af);
|
||
else
|
||
json_object_free(json_af);
|
||
|
||
sprintf(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 (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 (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
|
||
&& !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 (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
|
||
&& (!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);
|
||
|
||
/* 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)) {
|
||
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, afi_safi_print(afi, safi),
|
||
json_addr);
|
||
|
||
} else {
|
||
filter = &p->filter[afi][safi];
|
||
|
||
vty_out(vty, " For address family: %s\n",
|
||
afi_safi_print(afi, safi));
|
||
|
||
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_SM_OLD_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)
|
||
|| CHECK_FLAG(p->af_cap[afi][safi],
|
||
PEER_CAP_ORF_PREFIX_RM_OLD_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);
|
||
}
|
||
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_OLD_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_OLD_RCV)) {
|
||
vty_out(vty,
|
||
" Outbound Route Filter (ORF) type (%d) Prefix-list:\n",
|
||
ORF_TYPE_PREFIX_OLD);
|
||
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_OLD_RCV,
|
||
PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, NULL);
|
||
}
|
||
|
||
sprintf(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 (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 (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
|
||
&& !bgp_inbound_policy_exists(p, filter))
|
||
vty_out(vty,
|
||
" Inbound updates discarded due to missing policy\n");
|
||
|
||
/* ebgp-requires-policy (outbound) */
|
||
if (p->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED
|
||
&& !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);
|
||
|
||
/* Receive prefix count */
|
||
vty_out(vty, " %ld accepted prefixes\n", p->pcount[afi][safi]);
|
||
|
||
/* Maximum prefix */
|
||
if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) {
|
||
vty_out(vty, " Maximum prefixes allowed %ld%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 buf1[PREFIX2STR_BUFFER], buf[SU_ADDRSTRLEN];
|
||
char timebuf[BGP_UPTIME_LEN];
|
||
char dn_flag[2];
|
||
const char *subcode_str;
|
||
const char *code_str;
|
||
afi_t afi;
|
||
safi_t safi;
|
||
uint16_t i;
|
||
uint8_t *msg;
|
||
json_object *json_neigh = NULL;
|
||
time_t epoch_tbuf;
|
||
|
||
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: %s, ", p->conf_if,
|
||
BGP_PEER_SU_UNSPEC(p)
|
||
? "None"
|
||
: sockunion2str(&p->su, buf,
|
||
SU_ADDRSTRLEN));
|
||
else /* Configured IP address. */
|
||
vty_out(vty, "BGP neighbor is %s%s, ", dn_flag,
|
||
p->host);
|
||
}
|
||
|
||
if (use_json) {
|
||
if (p->conf_if && BGP_PEER_SU_UNSPEC(p))
|
||
json_object_string_add(json_neigh, "bgpNeighborAddr",
|
||
"none");
|
||
else if (p->conf_if && !BGP_PEER_SU_UNSPEC(p))
|
||
json_object_string_add(
|
||
json_neigh, "bgpNeighborAddr",
|
||
sockunion2str(&p->su, buf, SU_ADDRSTRLEN));
|
||
|
||
json_object_int_add(json_neigh, "remoteAs", p->as);
|
||
|
||
if (p->change_local_as)
|
||
json_object_int_add(json_neigh, "localAs",
|
||
p->change_local_as);
|
||
else
|
||
json_object_int_add(json_neigh, "localAs", p->local_as);
|
||
|
||
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 %u, ", p->as);
|
||
else
|
||
vty_out(vty, "remote AS Unspecified, ");
|
||
vty_out(vty, "local AS %u%s%s, ",
|
||
p->change_local_as ? p->change_local_as : p->local_as,
|
||
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");
|
||
}
|
||
|
||
/* 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) {
|
||
if (p->hostname)
|
||
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);
|
||
}
|
||
}
|
||
|
||
/* 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;
|
||
|
||
sockunion2hostprefix(&(p->su), &prefix);
|
||
range = peer_group_lookup_dynamic_neighbor_range(
|
||
p->group, &prefix);
|
||
|
||
if (range) {
|
||
prefix2str(range, buf1, sizeof(buf1));
|
||
json_object_string_add(
|
||
json_neigh,
|
||
"peerSubnetRangeGroup", buf1);
|
||
}
|
||
}
|
||
} 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;
|
||
|
||
sockunion2hostprefix(&(p->su), &prefix);
|
||
range = peer_group_lookup_dynamic_neighbor_range(
|
||
p->group, &prefix);
|
||
|
||
if (range) {
|
||
prefix2str(range, buf1, sizeof(buf1));
|
||
vty_out(vty,
|
||
" Belongs to the subnet range group: %s\n",
|
||
buf1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (use_json) {
|
||
/* Administrative shutdown. */
|
||
if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN))
|
||
json_object_boolean_true_add(json_neigh,
|
||
"adminShutDown");
|
||
|
||
/* BGP Version. */
|
||
json_object_int_add(json_neigh, "bgpVersion", 4);
|
||
json_object_string_add(
|
||
json_neigh, "remoteRouterId",
|
||
inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1)));
|
||
json_object_string_add(
|
||
json_neigh, "localRouterId",
|
||
inet_ntop(AF_INET, &bgp->router_id, buf1,
|
||
sizeof(buf1)));
|
||
|
||
/* 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->status, NULL));
|
||
|
||
if (p->status == Established) {
|
||
time_t uptime;
|
||
|
||
uptime = bgp_clock();
|
||
uptime -= p->uptime;
|
||
epoch_tbuf = time(NULL) - uptime;
|
||
|
||
#if CONFDATE > 20200101
|
||
CPP_NOTICE(
|
||
"bgpTimerUp should be deprecated and can be removed now");
|
||
#endif
|
||
/*
|
||
* bgpTimerUp was miliseconds that was accurate
|
||
* up to 1 day, then the value returned
|
||
* became garbage. So in order to provide
|
||
* some level of backwards compatability,
|
||
* we still provde the data, but now
|
||
* we are returning the correct value
|
||
* and also adding a new bgpTimerUpMsec
|
||
* which will allow us to deprecate
|
||
* this eventually
|
||
*/
|
||
json_object_int_add(json_neigh, "bgpTimerUp",
|
||
uptime * 1000);
|
||
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->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 = bgp_clock();
|
||
uptime -= p->readtime;
|
||
tm = gmtime(&uptime);
|
||
json_object_int_add(json_neigh, "bgpTimerLastRead",
|
||
(tm->tm_sec * 1000) + (tm->tm_min * 60000)
|
||
+ (tm->tm_hour * 3600000));
|
||
|
||
uptime = bgp_clock();
|
||
uptime -= p->last_write;
|
||
tm = gmtime(&uptime);
|
||
json_object_int_add(json_neigh, "bgpTimerLastWrite",
|
||
(tm->tm_sec * 1000) + (tm->tm_min * 60000)
|
||
+ (tm->tm_hour * 3600000));
|
||
|
||
uptime = bgp_clock();
|
||
uptime -= p->update_time;
|
||
tm = gmtime(&uptime);
|
||
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, "bgpTimerHoldTimeMsecs",
|
||
p->v_holdtime * 1000);
|
||
json_object_int_add(json_neigh,
|
||
"bgpTimerKeepAliveIntervalMsecs",
|
||
p->v_keepalive * 1000);
|
||
if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER)) {
|
||
json_object_int_add(json_neigh,
|
||
"bgpTimerConfiguredHoldTimeMsecs",
|
||
p->holdtime * 1000);
|
||
json_object_int_add(
|
||
json_neigh,
|
||
"bgpTimerConfiguredKeepAliveIntervalMsecs",
|
||
p->keepalive * 1000);
|
||
} else if ((bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
||
|| (bgp->default_keepalive
|
||
!= BGP_DEFAULT_KEEPALIVE)) {
|
||
json_object_int_add(json_neigh,
|
||
"bgpTimerConfiguredHoldTimeMsecs",
|
||
bgp->default_holdtime);
|
||
json_object_int_add(
|
||
json_neigh,
|
||
"bgpTimerConfiguredKeepAliveIntervalMsecs",
|
||
bgp->default_keepalive);
|
||
}
|
||
} else {
|
||
/* Administrative shutdown. */
|
||
if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN))
|
||
vty_out(vty, " Administratively shut down\n");
|
||
|
||
/* BGP Version. */
|
||
vty_out(vty, " BGP version 4");
|
||
vty_out(vty, ", remote router ID %s",
|
||
inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1)));
|
||
vty_out(vty, ", local router ID %s\n",
|
||
inet_ntop(AF_INET, &bgp->router_id, buf1,
|
||
sizeof(buf1)));
|
||
|
||
/* 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->status, NULL));
|
||
|
||
if (p->status == Established)
|
||
vty_out(vty, ", up for %8s",
|
||
peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN,
|
||
0, NULL));
|
||
|
||
else if (p->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, keepalive interval is %d seconds\n",
|
||
p->v_holdtime, p->v_keepalive);
|
||
if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER)) {
|
||
vty_out(vty, " Configured hold time is %d",
|
||
p->holdtime);
|
||
vty_out(vty, ", keepalive interval is %d seconds\n",
|
||
p->keepalive);
|
||
} else if ((bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
||
|| (bgp->default_keepalive
|
||
!= BGP_DEFAULT_KEEPALIVE)) {
|
||
vty_out(vty, " Configured hold time is %d",
|
||
bgp->default_holdtime);
|
||
vty_out(vty, ", keepalive interval is %d seconds\n",
|
||
bgp->default_keepalive);
|
||
}
|
||
}
|
||
/* Capability. */
|
||
if (p->status == Established) {
|
||
if (p->cap || p->afc_adv[AFI_IP][SAFI_UNICAST]
|
||
|| p->afc_recv[AFI_IP][SAFI_UNICAST]
|
||
|| p->afc_adv[AFI_IP][SAFI_MULTICAST]
|
||
|| p->afc_recv[AFI_IP][SAFI_MULTICAST]
|
||
|| p->afc_adv[AFI_IP6][SAFI_UNICAST]
|
||
|| p->afc_recv[AFI_IP6][SAFI_UNICAST]
|
||
|| p->afc_adv[AFI_IP6][SAFI_MULTICAST]
|
||
|| p->afc_recv[AFI_IP6][SAFI_MULTICAST]
|
||
|| p->afc_adv[AFI_IP6][SAFI_MPLS_VPN]
|
||
|| p->afc_recv[AFI_IP6][SAFI_MPLS_VPN]
|
||
|| p->afc_adv[AFI_IP6][SAFI_ENCAP]
|
||
|| p->afc_recv[AFI_IP6][SAFI_ENCAP]
|
||
|| p->afc_adv[AFI_IP6][SAFI_FLOWSPEC]
|
||
|| p->afc_recv[AFI_IP6][SAFI_FLOWSPEC]
|
||
|| p->afc_adv[AFI_IP][SAFI_ENCAP]
|
||
|| p->afc_recv[AFI_IP][SAFI_ENCAP]
|
||
|| p->afc_adv[AFI_IP][SAFI_FLOWSPEC]
|
||
|| p->afc_recv[AFI_IP][SAFI_FLOWSPEC]
|
||
|| p->afc_adv[AFI_IP][SAFI_MPLS_VPN]
|
||
|| p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) {
|
||
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");
|
||
}
|
||
|
||
/* 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 = afi_safi_print(
|
||
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)) {
|
||
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");
|
||
}
|
||
|
||
/* 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 = afi_safi_print(
|
||
AFI_IP,
|
||
safi);
|
||
json_object_string_add(
|
||
json_nxt,
|
||
print_store,
|
||
"recieved"); /* misspelled for compatibility */
|
||
}
|
||
}
|
||
json_object_object_add(
|
||
json_cap,
|
||
"extendedNexthopFamililesByPeer",
|
||
json_nxt);
|
||
}
|
||
}
|
||
|
||
/* Route Refresh */
|
||
if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV)
|
||
|| CHECK_FLAG(p->cap,
|
||
PEER_CAP_REFRESH_NEW_RCV)
|
||
|| CHECK_FLAG(p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV)) {
|
||
if (CHECK_FLAG(p->cap,
|
||
PEER_CAP_REFRESH_ADV)
|
||
&& (CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_NEW_RCV)
|
||
|| CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV))) {
|
||
if (CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV)
|
||
&& CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_NEW_RCV))
|
||
json_object_string_add(
|
||
json_cap,
|
||
"routeRefresh",
|
||
"advertisedAndReceivedOldNew");
|
||
else {
|
||
if (CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV))
|
||
json_object_string_add(
|
||
json_cap,
|
||
"routeRefresh",
|
||
"advertisedAndReceivedOld");
|
||
else
|
||
json_object_string_add(
|
||
json_cap,
|
||
"routeRefresh",
|
||
"advertisedAndReceivedNew");
|
||
}
|
||
} 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_NEW_RCV)
|
||
|| CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV))
|
||
json_object_string_add(
|
||
json_cap,
|
||
"routeRefresh",
|
||
"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,
|
||
afi_safi_print(afi,
|
||
safi),
|
||
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);
|
||
|
||
/* Gracefull 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,
|
||
afi_safi_print(
|
||
afi,
|
||
safi),
|
||
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");
|
||
}
|
||
|
||
/* 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 ",
|
||
afi_safi_print(
|
||
afi,
|
||
safi));
|
||
|
||
if (CHECK_FLAG(
|
||
p->af_cap
|
||
[afi]
|
||
[safi],
|
||
PEER_CAP_ADDPATH_AF_TX_ADV))
|
||
vty_out(vty,
|
||
"advertised %s",
|
||
afi_safi_print(
|
||
afi,
|
||
safi));
|
||
|
||
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 ",
|
||
afi_safi_print(
|
||
afi,
|
||
safi));
|
||
|
||
if (CHECK_FLAG(
|
||
p->af_cap
|
||
[afi]
|
||
[safi],
|
||
PEER_CAP_ADDPATH_AF_RX_ADV))
|
||
vty_out(vty,
|
||
"advertised %s",
|
||
afi_safi_print(
|
||
afi,
|
||
safi));
|
||
|
||
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");
|
||
}
|
||
|
||
/* 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",
|
||
afi_safi_print(
|
||
AFI_IP,
|
||
safi));
|
||
}
|
||
}
|
||
|
||
/* Route Refresh */
|
||
if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV)
|
||
|| CHECK_FLAG(p->cap,
|
||
PEER_CAP_REFRESH_NEW_RCV)
|
||
|| CHECK_FLAG(p->cap,
|
||
PEER_CAP_REFRESH_OLD_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_NEW_RCV)
|
||
|| CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV))
|
||
vty_out(vty, " %sreceived(%s)",
|
||
CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_ADV)
|
||
? "and "
|
||
: "",
|
||
(CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV)
|
||
&& CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_NEW_RCV))
|
||
? "old & new"
|
||
: CHECK_FLAG(
|
||
p->cap,
|
||
PEER_CAP_REFRESH_OLD_RCV)
|
||
? "old"
|
||
: "new");
|
||
|
||
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:",
|
||
afi_safi_print(afi,
|
||
safi));
|
||
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");
|
||
|
||
/* Gracefull Restart */
|
||
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
|
||
|| CHECK_FLAG(p->cap,
|
||
PEER_CAP_RESTART_ADV)) {
|
||
vty_out(vty,
|
||
" Graceful Restart Capabilty:");
|
||
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
|
||
? ", "
|
||
: "",
|
||
afi_safi_print(
|
||
afi,
|
||
safi),
|
||
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 information */
|
||
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) || p->t_gr_restart
|
||
|| p->t_gr_stale) {
|
||
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 (p->status == Established) {
|
||
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,
|
||
afi_safi_print(afi,
|
||
safi));
|
||
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,
|
||
afi_safi_print(afi,
|
||
safi));
|
||
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->t_gr_restart)
|
||
json_object_int_add(json_grace,
|
||
"gracefulRestartTimerMsecs",
|
||
thread_timer_remain_second(
|
||
p->t_gr_restart)
|
||
* 1000);
|
||
|
||
if (p->t_gr_stale)
|
||
json_object_int_add(
|
||
json_grace,
|
||
"gracefulStalepathTimerMsecs",
|
||
thread_timer_remain_second(
|
||
p->t_gr_stale)
|
||
* 1000);
|
||
|
||
json_object_object_add(
|
||
json_neigh, "gracefulRestartInfo", json_grace);
|
||
} else {
|
||
vty_out(vty, " Graceful restart information:\n");
|
||
if (p->status == Established) {
|
||
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 ? ", "
|
||
: "",
|
||
afi_safi_print(afi,
|
||
safi));
|
||
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
|
||
? ", "
|
||
: "",
|
||
afi_safi_print(afi,
|
||
safi));
|
||
eor_receive_af_count++;
|
||
}
|
||
}
|
||
vty_out(vty, "\n");
|
||
}
|
||
|
||
if (p->t_gr_restart)
|
||
vty_out(vty,
|
||
" The remaining time of restart timer is %ld\n",
|
||
thread_timer_remain_second(
|
||
p->t_gr_restart));
|
||
|
||
if (p->t_gr_stale)
|
||
vty_out(vty,
|
||
" The remaining time of stalepath timer is %ld\n",
|
||
thread_timer_remain_second(
|
||
p->t_gr_stale));
|
||
}
|
||
}
|
||
if (use_json) {
|
||
json_object *json_stat = NULL;
|
||
json_stat = json_object_new_object();
|
||
/* Packet counts. */
|
||
json_object_int_add(json_stat, "depthInq", 0);
|
||
json_object_int_add(json_stat, "depthOutq",
|
||
(unsigned long)p->obuf->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 {
|
||
/* Packet counts. */
|
||
vty_out(vty, " Message statistics:\n");
|
||
vty_out(vty, " Inq depth is 0\n");
|
||
vty_out(vty, " Outq depth is %lu\n",
|
||
(unsigned long)p->obuf->count);
|
||
vty_out(vty, " Sent Rcvd\n");
|
||
vty_out(vty, " Opens: %10d %10d\n",
|
||
atomic_load_explicit(&p->open_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->open_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Notifications: %10d %10d\n",
|
||
atomic_load_explicit(&p->notify_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->notify_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Updates: %10d %10d\n",
|
||
atomic_load_explicit(&p->update_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->update_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Keepalives: %10d %10d\n",
|
||
atomic_load_explicit(&p->keepalive_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->keepalive_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Route Refresh: %10d %10d\n",
|
||
atomic_load_explicit(&p->refresh_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->refresh_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Capability: %10d %10d\n",
|
||
atomic_load_explicit(&p->dynamic_cap_out,
|
||
memory_order_relaxed),
|
||
atomic_load_explicit(&p->dynamic_cap_in,
|
||
memory_order_relaxed));
|
||
vty_out(vty, " Total: %10d %10d\n", PEER_TOTAL_TX(p),
|
||
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_add(
|
||
json_neigh, "updateSource",
|
||
sockunion2str(p->update_source, buf1,
|
||
SU_ADDRSTRLEN));
|
||
}
|
||
} 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, "%s",
|
||
sockunion2str(p->update_source, buf1,
|
||
SU_ADDRSTRLEN));
|
||
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 = bgp_clock();
|
||
uptime -= p->resettime;
|
||
tm = gmtime(&uptime);
|
||
json_object_int_add(json_neigh, "lastResetTimerMsecs",
|
||
(tm->tm_sec * 1000)
|
||
+ (tm->tm_min * 60000)
|
||
+ (tm->tm_hour * 3600000));
|
||
json_object_string_add(
|
||
json_neigh, "lastResetDueTo",
|
||
peer_down_str[(int)p->last_reset]);
|
||
if (p->last_reset == PEER_DOWN_NOTIFY_SEND
|
||
|| p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) {
|
||
char errorcodesubcode_hexstr[5];
|
||
char errorcodesubcode_str[256];
|
||
|
||
code_str = bgp_notify_code_str(p->notify.code);
|
||
subcode_str = bgp_notify_subcode_str(
|
||
p->notify.code, p->notify.subcode);
|
||
|
||
sprintf(errorcodesubcode_hexstr, "%02X%02X",
|
||
p->notify.code, p->notify.subcode);
|
||
json_object_string_add(json_neigh,
|
||
"lastErrorCodeSubcode",
|
||
errorcodesubcode_hexstr);
|
||
snprintf(errorcodesubcode_str, 255, "%s%s",
|
||
code_str, subcode_str);
|
||
json_object_string_add(json_neigh,
|
||
"lastNotificationReason",
|
||
errorcodesubcode_str);
|
||
if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED
|
||
&& p->notify.code == BGP_NOTIFY_CEASE
|
||
&& (p->notify.subcode
|
||
== BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN
|
||
|| p->notify.subcode
|
||
== BGP_NOTIFY_CEASE_ADMIN_RESET)
|
||
&& p->notify.length) {
|
||
char msgbuf[1024];
|
||
const char *msg_str;
|
||
|
||
msg_str = bgp_notify_admin_message(
|
||
msgbuf, sizeof(msgbuf),
|
||
(uint8_t *)p->notify.data,
|
||
p->notify.length);
|
||
if (msg_str)
|
||
json_object_string_add(
|
||
json_neigh,
|
||
"lastShutdownDescription",
|
||
msg_str);
|
||
}
|
||
}
|
||
} else {
|
||
vty_out(vty, " Last reset %s, ",
|
||
peer_uptime(p->resettime, timebuf,
|
||
BGP_UPTIME_LEN, 0, NULL));
|
||
|
||
if (p->last_reset == PEER_DOWN_NOTIFY_SEND
|
||
|| p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) {
|
||
code_str = bgp_notify_code_str(p->notify.code);
|
||
subcode_str = bgp_notify_subcode_str(
|
||
p->notify.code, p->notify.subcode);
|
||
vty_out(vty, "due to NOTIFICATION %s (%s%s)\n",
|
||
p->last_reset == PEER_DOWN_NOTIFY_SEND
|
||
? "sent"
|
||
: "received",
|
||
code_str, subcode_str);
|
||
if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED
|
||
&& p->notify.code == BGP_NOTIFY_CEASE
|
||
&& (p->notify.subcode
|
||
== BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN
|
||
|| p->notify.subcode
|
||
== BGP_NOTIFY_CEASE_ADMIN_RESET)
|
||
&& p->notify.length) {
|
||
char msgbuf[1024];
|
||
const char *msg_str;
|
||
|
||
msg_str = bgp_notify_admin_message(
|
||
msgbuf, sizeof(msgbuf),
|
||
(uint8_t *)p->notify.data,
|
||
p->notify.length);
|
||
if (msg_str)
|
||
vty_out(vty,
|
||
" Message: \"%s\"\n",
|
||
msg_str);
|
||
}
|
||
} else {
|
||
vty_out(vty, "due to %s\n",
|
||
peer_down_str[(int)p->last_reset]);
|
||
}
|
||
|
||
if (p->last_reset_cause_size) {
|
||
msg = p->last_reset_cause;
|
||
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->t_pmax_restart) {
|
||
if (use_json) {
|
||
json_object_boolean_true_add(
|
||
json_neigh, "reducePrefixNumFrom");
|
||
json_object_int_add(json_neigh,
|
||
"restartInTimerMsec",
|
||
thread_timer_remain_second(
|
||
p->t_pmax_restart)
|
||
* 1000);
|
||
} else
|
||
vty_out(vty,
|
||
" Reduce the no. of prefix from %s, will restart in %ld seconds\n",
|
||
p->host, thread_timer_remain_second(
|
||
p->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 > 0)
|
||
json_object_int_add(json_neigh,
|
||
"externalBgpNbrMaxHopsAway",
|
||
p->gtsm_hops);
|
||
else if (p->ttl > 1)
|
||
json_object_int_add(json_neigh,
|
||
"externalBgpNbrMaxHopsAway",
|
||
p->ttl);
|
||
} else {
|
||
if (p->gtsm_hops > 0)
|
||
vty_out(vty,
|
||
" External BGP neighbor may be up to %d hops away.\n",
|
||
p->gtsm_hops);
|
||
else if (p->ttl > 1)
|
||
vty_out(vty,
|
||
" External BGP neighbor may be up to %d hops away.\n",
|
||
p->ttl);
|
||
}
|
||
} else {
|
||
if (p->gtsm_hops > 0) {
|
||
if (use_json)
|
||
json_object_int_add(json_neigh,
|
||
"internalBgpNbrMaxHopsAway",
|
||
p->gtsm_hops);
|
||
else
|
||
vty_out(vty,
|
||
" Internal BGP neighbor may be up to %d hops away.\n",
|
||
p->gtsm_hops);
|
||
}
|
||
}
|
||
|
||
/* Local address. */
|
||
if (p->su_local) {
|
||
if (use_json) {
|
||
json_object_string_add(json_neigh, "hostLocal",
|
||
sockunion2str(p->su_local, buf1,
|
||
SU_ADDRSTRLEN));
|
||
json_object_int_add(json_neigh, "portLocal",
|
||
ntohs(p->su_local->sin.sin_port));
|
||
} else
|
||
vty_out(vty, "Local host: %s, Local port: %d\n",
|
||
sockunion2str(p->su_local, buf1, SU_ADDRSTRLEN),
|
||
ntohs(p->su_local->sin.sin_port));
|
||
}
|
||
|
||
/* Remote address. */
|
||
if (p->su_remote) {
|
||
if (use_json) {
|
||
json_object_string_add(json_neigh, "hostForeign",
|
||
sockunion2str(p->su_remote, buf1,
|
||
SU_ADDRSTRLEN));
|
||
json_object_int_add(json_neigh, "portForeign",
|
||
ntohs(p->su_remote->sin.sin_port));
|
||
} else
|
||
vty_out(vty, "Foreign host: %s, Foreign port: %d\n",
|
||
sockunion2str(p->su_remote, buf1,
|
||
SU_ADDRSTRLEN),
|
||
ntohs(p->su_remote->sin.sin_port));
|
||
}
|
||
|
||
/* Nexthop display. */
|
||
if (p->su_local) {
|
||
if (use_json) {
|
||
json_object_string_add(json_neigh, "nexthop",
|
||
inet_ntop(AF_INET,
|
||
&p->nexthop.v4, buf1,
|
||
sizeof(buf1)));
|
||
json_object_string_add(json_neigh, "nexthopGlobal",
|
||
inet_ntop(AF_INET6,
|
||
&p->nexthop.v6_global,
|
||
buf1, sizeof(buf1)));
|
||
json_object_string_add(json_neigh, "nexthopLocal",
|
||
inet_ntop(AF_INET6,
|
||
&p->nexthop.v6_local,
|
||
buf1, sizeof(buf1)));
|
||
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: %s\n",
|
||
inet_ntop(AF_INET, &p->nexthop.v4, buf1,
|
||
sizeof(buf1)));
|
||
vty_out(vty, "Nexthop global: %s\n",
|
||
inet_ntop(AF_INET6, &p->nexthop.v6_global, buf1,
|
||
sizeof(buf1)));
|
||
vty_out(vty, "Nexthop local: %s\n",
|
||
inet_ntop(AF_INET6, &p->nexthop.v6_local, buf1,
|
||
sizeof(buf1)));
|
||
vty_out(vty, "BGP connection: %s\n",
|
||
p->shared_network ? "shared network"
|
||
: "non shared network");
|
||
}
|
||
}
|
||
|
||
/* Timer information. */
|
||
if (use_json) {
|
||
json_object_int_add(json_neigh, "connectRetryTimer",
|
||
p->v_connect);
|
||
if (p->status == Established && p->rtt)
|
||
json_object_int_add(json_neigh, "estimatedRttInMsecs",
|
||
p->rtt);
|
||
if (p->t_start)
|
||
json_object_int_add(
|
||
json_neigh, "nextStartTimerDueInMsecs",
|
||
thread_timer_remain_second(p->t_start) * 1000);
|
||
if (p->t_connect)
|
||
json_object_int_add(
|
||
json_neigh, "nextConnectTimerDueInMsecs",
|
||
thread_timer_remain_second(p->t_connect)
|
||
* 1000);
|
||
if (p->t_routeadv) {
|
||
json_object_int_add(json_neigh, "mraiInterval",
|
||
p->v_routeadv);
|
||
json_object_int_add(
|
||
json_neigh, "mraiTimerExpireInMsecs",
|
||
thread_timer_remain_second(p->t_routeadv)
|
||
* 1000);
|
||
}
|
||
if (p->password)
|
||
json_object_int_add(json_neigh, "authenticationEnabled",
|
||
1);
|
||
|
||
if (p->t_read)
|
||
json_object_string_add(json_neigh, "readThread", "on");
|
||
else
|
||
json_object_string_add(json_neigh, "readThread", "off");
|
||
|
||
if (CHECK_FLAG(p->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 (p->status == Established && p->rtt)
|
||
vty_out(vty, "Estimated round trip time: %d ms\n",
|
||
p->rtt);
|
||
if (p->t_start)
|
||
vty_out(vty, "Next start timer due in %ld seconds\n",
|
||
thread_timer_remain_second(p->t_start));
|
||
if (p->t_connect)
|
||
vty_out(vty, "Next connect timer due in %ld seconds\n",
|
||
thread_timer_remain_second(p->t_connect));
|
||
if (p->t_routeadv)
|
||
vty_out(vty,
|
||
"MRAI (interval %u) timer expires in %ld seconds\n",
|
||
p->v_routeadv,
|
||
thread_timer_remain_second(p->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->t_read ? "on" : "off",
|
||
CHECK_FLAG(p->thread_flags, PEER_THREAD_WRITES_ON)
|
||
? "on"
|
||
: "off", p->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. */
|
||
bgp_bfd_show_info(vty, p, use_json, 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(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->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->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_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);
|
||
}
|
||
|
||
if (use_json) {
|
||
vty_out(vty, "}\n");
|
||
json_object_free(json);
|
||
}
|
||
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_out(vty, "%s\n",
|
||
json_object_to_json_string_ext(
|
||
json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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" 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
|
||
"Address Family\n"
|
||
"Address Family\n"
|
||
"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));
|
||
}
|
||
|
||
/* 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));
|
||
}
|
||
|
||
/* 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;
|
||
}
|
||
|
||
|
||
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 buf1[INET6_ADDRSTRLEN];
|
||
char *ecom_str;
|
||
vpn_policy_direction_t 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_out(vty, "%s\n",
|
||
json_object_to_json_string_ext(
|
||
json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(json);
|
||
|
||
return CMD_WARNING;
|
||
}
|
||
|
||
/* Provide context for the block */
|
||
json_object_string_add(json, "vrf", name ? name : "default");
|
||
json_object_string_add(json, "afiSafi",
|
||
afi_safi_print(afi, safi));
|
||
|
||
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_add(json, "routeDistinguisher",
|
||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
|
||
buf1, RD_ADDRSTRLEN));
|
||
|
||
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_out(vty, "%s\n",
|
||
json_object_to_json_string_ext(json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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",
|
||
afi_safi_print(afi, safi));
|
||
else {
|
||
vty_out(vty,
|
||
"This VRF is importing %s routes from the following VRFs:\n",
|
||
afi_safi_print(afi, safi));
|
||
|
||
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",
|
||
afi_safi_print(afi, safi));
|
||
else {
|
||
vty_out(vty,
|
||
"This VRF is exporting %s routes to the following VRFs:\n",
|
||
afi_safi_print(afi, safi));
|
||
|
||
for (ALL_LIST_ELEMENTS_RO(
|
||
bgp->vpn_policy[afi].export_vrf,
|
||
node, vname))
|
||
vty_out(vty, " %s\n", vname);
|
||
|
||
vty_out(vty, "RD: %s\n",
|
||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
|
||
buf1, RD_ADDRSTRLEN));
|
||
|
||
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_out(vty, "%s\n", json_object_to_json_string_ext(json,
|
||
JSON_C_TO_STRING_PRETTY));
|
||
json_object_free(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)
|
||
{
|
||
struct listnode *node, *nnode;
|
||
struct bgp *bgp;
|
||
|
||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
||
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);
|
||
}
|
||
}
|
||
|
||
static int bgp_show_update_groups(struct vty *vty, const char *name, int afi,
|
||
int safi, uint64_t subgrp_id)
|
||
{
|
||
struct bgp *bgp;
|
||
|
||
if (name) {
|
||
if (strmatch(name, "all")) {
|
||
bgp_show_all_instances_updgrps_vty(vty, afi, safi);
|
||
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);
|
||
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]",
|
||
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")
|
||
{
|
||
char *vrf = NULL;
|
||
afi_t afi = AFI_IP6;
|
||
safi_t safi = SAFI_UNICAST;
|
||
uint64_t subgrp_id = 0;
|
||
|
||
int idx = 0;
|
||
|
||
/* 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));
|
||
}
|
||
|
||
DEFUN (show_bgp_instance_all_ipv6_updgrps,
|
||
show_bgp_instance_all_ipv6_updgrps_cmd,
|
||
"show [ip] bgp <view|vrf> all update-groups",
|
||
SHOW_STR
|
||
IP_STR
|
||
BGP_STR
|
||
BGP_INSTANCE_ALL_HELP_STR
|
||
"Detailed info about dynamic update groups\n")
|
||
{
|
||
bgp_show_all_instances_updgrps_vty(vty, AFI_IP6, SAFI_UNICAST);
|
||
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);
|
||
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)
|
||
{
|
||
struct listnode *node, *nnode;
|
||
struct prefix *range;
|
||
struct peer *conf;
|
||
struct peer *peer;
|
||
char buf[PREFIX2STR_BUFFER];
|
||
afi_t afi;
|
||
safi_t safi;
|
||
const char *peer_status;
|
||
const char *af_str;
|
||
int lr_count;
|
||
int dynamic;
|
||
int af_cfgd;
|
||
|
||
conf = group->conf;
|
||
|
||
if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
|
||
vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
|
||
group->name, conf->as);
|
||
} else if (conf->as_type == AS_INTERNAL) {
|
||
vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
|
||
group->name, group->bgp->as);
|
||
} else {
|
||
vty_out(vty, "\nBGP peer-group %s\n", group->name);
|
||
}
|
||
|
||
if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL))
|
||
vty_out(vty, " Peer-group type is internal\n");
|
||
else
|
||
vty_out(vty, " Peer-group type is external\n");
|
||
|
||
/* Display AFs configured. */
|
||
vty_out(vty, " Configured address-families:");
|
||
FOREACH_AFI_SAFI (afi, safi) {
|
||
if (conf->afc[afi][safi]) {
|
||
af_cfgd = 1;
|
||
vty_out(vty, " %s;", afi_safi_print(afi, safi));
|
||
}
|
||
}
|
||
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++) {
|
||
if (afi == AFI_IP)
|
||
af_str = "IPv4";
|
||
else if (afi == AFI_IP6)
|
||
af_str = "IPv6";
|
||
else
|
||
af_str = "???";
|
||
lr_count = listcount(group->listen_range[afi]);
|
||
if (lr_count) {
|
||
vty_out(vty, " %d %s listen range(s)\n", lr_count,
|
||
af_str);
|
||
|
||
|
||
for (ALL_LIST_ELEMENTS(group->listen_range[afi], node,
|
||
nnode, range)) {
|
||
prefix2str(range, buf, sizeof(buf));
|
||
vty_out(vty, " %s\n", buf);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Display group members and their status */
|
||
if (listcount(group->peer)) {
|
||
vty_out(vty, " Peer-group members:\n");
|
||
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
|
||
if (CHECK_FLAG(peer->flags, PEER_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->status, NULL);
|
||
|
||
dynamic = peer_dynamic_neighbor(peer);
|
||
vty_out(vty, " %s %s %s \n", peer->host,
|
||
dynamic ? "(dynamic)" : "", peer_status);
|
||
}
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
|
||
const char *group_name)
|
||
{
|
||
struct bgp *bgp;
|
||
struct listnode *node, *nnode;
|
||
struct peer_group *group;
|
||
bool found = false;
|
||
|
||
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
|
||
|
||
if (!bgp) {
|
||
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);
|
||
found = true;
|
||
break;
|
||
}
|
||
} else {
|
||
bgp_show_one_peer_group(vty, group);
|
||
}
|
||
}
|
||
|
||
if (group_name && !found)
|
||
vty_out(vty, "%% No such peer-group\n");
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
DEFUN (show_ip_bgp_peer_groups,
|
||
show_ip_bgp_peer_groups_cmd,
|
||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME]",
|
||
SHOW_STR
|
||
IP_STR
|
||
BGP_STR
|
||
BGP_INSTANCE_HELP_STR
|
||
"Detailed information on BGP peer groups\n"
|
||
"Peer group name\n")
|
||
{
|
||
char *vrf, *pg;
|
||
int idx = 0;
|
||
|
||
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);
|
||
}
|
||
|
||
|
||
/* 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 WORD",
|
||
"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 WORD",
|
||
"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 WORD 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 WORD 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 WORD",
|
||
"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 WORD",
|
||
"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
|
||
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 WORD",
|
||
"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
|
||
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 WORD",
|
||
"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
|
||
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 WORD 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
|
||
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 WORD 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 WORD",
|
||
"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
|
||
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 WORD",
|
||
"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 WORD}]",
|
||
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
|
||
protocol = ZEBRA_ROUTE_TABLE;
|
||
|
||
instance = strtoul(argv[idx_number]->arg, NULL, 10);
|
||
return bgp_redistribute_unset(bgp, AFI_IP, protocol, instance);
|
||
}
|
||
|
||
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 WORD}]",
|
||
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 WORD}]",
|
||
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;
|
||
}
|
||
return bgp_redistribute_unset(bgp, AFI_IP, type, 0);
|
||
}
|
||
|
||
ALIAS_HIDDEN(
|
||
no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_hidden_cmd,
|
||
"no redistribute " FRR_IP_REDIST_STR_BGPD
|
||
" [{metric (0-4294967295)|route-map WORD}]",
|
||
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 WORD",
|
||
"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 WORD 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 WORD",
|
||
"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 WORD}]",
|
||
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;
|
||
}
|
||
|
||
return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
|
||
}
|
||
|
||
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");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* This is part of the address-family block (unicast only) */
|
||
void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
|
||
afi_t afi)
|
||
{
|
||
int indent = 2;
|
||
|
||
if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) {
|
||
if (listcount(bgp->vpn_policy[afi].import_vrf))
|
||
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_RD_SET)) {
|
||
char buf[RD_ADDRSTRLEN];
|
||
vty_out(vty, "%*srd vpn export %s\n", indent, "",
|
||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
|
||
sizeof(buf)));
|
||
}
|
||
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);
|
||
|
||
vty_out(vty, "%*srt redirect import %s\n", indent, "", b);
|
||
XFREE(MTYPE_ECOMMUNITY_STR, b);
|
||
}
|
||
}
|
||
|
||
|
||
/* BGP node structure. */
|
||
static struct cmd_node bgp_node = {
|
||
BGP_NODE, "%s(config-router)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv4_unicast_node = {
|
||
BGP_IPV4_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv4_multicast_node = {
|
||
BGP_IPV4M_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv4_labeled_unicast_node = {
|
||
BGP_IPV4L_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv6_unicast_node = {
|
||
BGP_IPV6_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv6_multicast_node = {
|
||
BGP_IPV6M_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_ipv6_labeled_unicast_node = {
|
||
BGP_IPV6L_NODE, "%s(config-router-af)# ", 1,
|
||
};
|
||
|
||
static struct cmd_node bgp_vpnv4_node = {BGP_VPNV4_NODE,
|
||
"%s(config-router-af)# ", 1};
|
||
|
||
static struct cmd_node bgp_vpnv6_node = {BGP_VPNV6_NODE,
|
||
"%s(config-router-af-vpnv6)# ", 1};
|
||
|
||
static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
|
||
"%s(config-router-evpn)# ", 1};
|
||
|
||
static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
|
||
"%s(config-router-af-vni)# ", 1};
|
||
|
||
static struct cmd_node bgp_flowspecv4_node = {BGP_FLOWSPECV4_NODE,
|
||
"%s(config-router-af)# ", 1};
|
||
|
||
static struct cmd_node bgp_flowspecv6_node = {BGP_FLOWSPECV6_NODE,
|
||
"%s(config-router-af-vpnv6)# ", 1};
|
||
|
||
static void community_list_vty(void);
|
||
|
||
static void bgp_ac_neighbor(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 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 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 const struct cmd_variable_handler bgp_var_peergroup[] = {
|
||
{.tokenname = "PGNAME", .completions = bgp_ac_peergroup},
|
||
{.completions = NULL} };
|
||
|
||
void bgp_vty_init(void)
|
||
{
|
||
cmd_variable_handler_register(bgp_var_neighbor);
|
||
cmd_variable_handler_register(bgp_var_peergroup);
|
||
|
||
/* Install bgp top node. */
|
||
install_node(&bgp_node, bgp_config_write);
|
||
install_node(&bgp_ipv4_unicast_node, NULL);
|
||
install_node(&bgp_ipv4_multicast_node, NULL);
|
||
install_node(&bgp_ipv4_labeled_unicast_node, NULL);
|
||
install_node(&bgp_ipv6_unicast_node, NULL);
|
||
install_node(&bgp_ipv6_multicast_node, NULL);
|
||
install_node(&bgp_ipv6_labeled_unicast_node, NULL);
|
||
install_node(&bgp_vpnv4_node, NULL);
|
||
install_node(&bgp_vpnv6_node, NULL);
|
||
install_node(&bgp_evpn_node, NULL);
|
||
install_node(&bgp_evpn_vni_node, NULL);
|
||
install_node(&bgp_flowspecv4_node, NULL);
|
||
install_node(&bgp_flowspecv6_node, NULL);
|
||
|
||
/* 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);
|
||
|
||
/* "bgp local-mac" hidden commands. */
|
||
install_element(CONFIG_NODE, &bgp_local_mac_cmd);
|
||
install_element(CONFIG_NODE, &no_bgp_local_mac_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);
|
||
|
||
/* 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 router-id" commands. */
|
||
install_element(BGP_NODE, &bgp_router_id_cmd);
|
||
install_element(BGP_NODE, &no_bgp_router_id_cmd);
|
||
|
||
/* "bgp cluster-id" commands. */
|
||
install_element(BGP_NODE, &bgp_cluster_id_cmd);
|
||
install_element(BGP_NODE, &no_bgp_cluster_id_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);
|
||
|
||
/* 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_update_delay_establish_wait_cmd);
|
||
|
||
install_element(BGP_NODE, &bgp_wpkt_quanta_cmd);
|
||
install_element(BGP_NODE, &no_bgp_wpkt_quanta_cmd);
|
||
install_element(BGP_NODE, &bgp_rpkt_quanta_cmd);
|
||
install_element(BGP_NODE, &no_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_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);
|
||
|
||
/* 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 deterministic-med" commands */
|
||
install_element(BGP_NODE, &bgp_deterministic_med_cmd);
|
||
install_element(BGP_NODE, &no_bgp_deterministic_med_cmd);
|
||
|
||
/* "bgp graceful-restart" commands */
|
||
install_element(BGP_NODE, &bgp_graceful_restart_cmd);
|
||
install_element(BGP_NODE, &no_bgp_graceful_restart_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_preserve_fw_cmd);
|
||
install_element(BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd);
|
||
|
||
/* "bgp graceful-shutdown" commands */
|
||
install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
|
||
install_element(BGP_NODE, &no_bgp_graceful_shutdown_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 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 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);
|
||
|
||
/* "no bgp default ipv4-unicast" commands. */
|
||
install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd);
|
||
install_element(BGP_NODE, &bgp_default_ipv4_unicast_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 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);
|
||
|
||
/* "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);
|
||
|
||
/* "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);
|
||
|
||
/* "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 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-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 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);
|
||
|
||
/* "neighbor capability extended-nexthop" commands.*/
|
||
install_element(BGP_NODE, &neighbor_capability_enhe_cmd);
|
||
install_element(BGP_NODE, &no_neighbor_capability_enhe_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 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 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 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);
|
||
|
||
/* 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);
|
||
|
||
/* "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);
|
||
|
||
/* "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 WORD] */
|
||
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);
|
||
|
||
/* "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();
|
||
|
||
/* 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_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_nexthop_vpn_export_cmd);
|
||
install_element(BGP_IPV6_NODE, &af_no_nexthop_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);
|
||
}
|
||
|
||
#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 WORD> <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"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
{
|
||
char *cl_name_or_number = NULL;
|
||
int direct = 0;
|
||
int style = COMMUNITY_LIST_STANDARD;
|
||
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'bgp community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
|
||
zlog_warn("Deprecated option: 'ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' being used");
|
||
}
|
||
|
||
argv_find(argv, argc, "(1-99)", &idx);
|
||
argv_find(argv, argc, "WORD", &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);
|
||
|
||
int ret = community_list_set(bgp_clist, cl_name_or_number, str, 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;
|
||
}
|
||
|
||
#if CONFDATE > 20191005
|
||
CPP_NOTICE("bgpd: remove deprecated 'ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' command")
|
||
#endif
|
||
ALIAS (community_list_standard,
|
||
ip_community_list_standard_cmd,
|
||
"ip community-list <(1-99)|standard WORD> <deny|permit> AA:NN...",
|
||
IP_STR
|
||
COMMUNITY_LIST_STR
|
||
"Community list number (standard)\n"
|
||
"Add an standard community-list entry\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
|
||
DEFUN (no_community_list_standard_all,
|
||
no_bgp_community_list_standard_all_cmd,
|
||
"no bgp community-list <(1-99)|standard WORD> <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"
|
||
"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;
|
||
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'no bgp community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
|
||
zlog_warn("Deprecated option: 'no ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> |AA:NN' being used");
|
||
}
|
||
|
||
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, "WORD", &idx);
|
||
cl_name_or_number = argv[idx]->arg;
|
||
|
||
int ret = community_list_unset(bgp_clist, cl_name_or_number, str,
|
||
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_ip_community_list_standard_all_cmd,
|
||
"no ip community-list <(1-99)|standard WORD> <deny|permit> AA:NN...",
|
||
NO_STR
|
||
IP_STR
|
||
COMMUNITY_LIST_STR
|
||
"Community list number (standard)\n"
|
||
"Add an standard community-list entry\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
|
||
ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cmd,
|
||
"no bgp community-list <(1-99)|standard WORD>",
|
||
NO_STR BGP_STR COMMUNITY_LIST_STR
|
||
"Community list number (standard)\n"
|
||
"Add an standard community-list entry\n"
|
||
"Community list name\n")
|
||
|
||
ALIAS(no_community_list_standard_all, no_ip_community_list_standard_all_list_cmd,
|
||
"no ip community-list <(1-99)|standard WORD>",
|
||
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 WORD> <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"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
{
|
||
char *cl_name_or_number = NULL;
|
||
int direct = 0;
|
||
int style = COMMUNITY_LIST_EXPANDED;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'bgp community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
|
||
zlog_warn("Deprecated option: 'ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' being used");
|
||
}
|
||
argv_find(argv, argc, "(100-500)", &idx);
|
||
argv_find(argv, argc, "WORD", &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);
|
||
|
||
int ret = community_list_set(bgp_clist, cl_name_or_number, str, 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;
|
||
}
|
||
|
||
ALIAS (community_list_expanded_all,
|
||
ip_community_list_expanded_all_cmd,
|
||
"ip community-list <(100-500)|expanded WORD> <deny|permit> AA:NN...",
|
||
IP_STR
|
||
COMMUNITY_LIST_STR
|
||
"Community list number (expanded)\n"
|
||
"Add an expanded community-list entry\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
|
||
DEFUN (no_community_list_expanded_all,
|
||
no_bgp_community_list_expanded_all_cmd,
|
||
"no bgp community-list <(100-500)|expanded WORD> <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"
|
||
"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_EXPANDED;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'no bgp community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN'\n");
|
||
zlog_warn("Deprecated option: 'no ip community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> AA:NN' being used");
|
||
}
|
||
|
||
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, "WORD", &idx);
|
||
cl_name_or_number = argv[idx]->arg;
|
||
|
||
int ret = community_list_unset(bgp_clist, cl_name_or_number, str,
|
||
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_ip_community_list_expanded_all_cmd,
|
||
"no ip community-list <(100-500)|expanded WORD> <deny|permit> AA:NN...",
|
||
NO_STR
|
||
IP_STR
|
||
COMMUNITY_LIST_STR
|
||
"Community list number (expanded)\n"
|
||
"Add an expanded community-list entry\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
COMMUNITY_VAL_STR)
|
||
|
||
ALIAS(no_community_list_expanded_all, no_bgp_community_list_expanded_all_list_cmd,
|
||
"no bgp community-list <(100-500)|expanded WORD>",
|
||
NO_STR IP_STR COMMUNITY_LIST_STR
|
||
"Community list number (expanded)\n"
|
||
"Add an expanded community-list entry\n"
|
||
"Community list name\n")
|
||
|
||
ALIAS(no_community_list_expanded_all, no_ip_community_list_expanded_all_list_cmd,
|
||
"no ip community-list <(100-500)|expanded WORD>",
|
||
NO_STR IP_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->any)
|
||
str = "";
|
||
else {
|
||
if (entry->style == COMMUNITY_LIST_STANDARD)
|
||
str = community_str(entry->u.com, false);
|
||
else if (entry->style == LARGE_COMMUNITY_LIST_STANDARD)
|
||
str = lcommunity_str(entry->u.lcom, 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);
|
||
}
|
||
if (entry->any)
|
||
vty_out(vty, " %s\n",
|
||
community_direct_str(entry->direct));
|
||
else
|
||
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;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used");
|
||
}
|
||
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;
|
||
}
|
||
|
||
ALIAS (show_community_list,
|
||
show_ip_community_list_cmd,
|
||
"show ip community-list",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List community-list\n")
|
||
|
||
DEFUN (show_community_list_arg,
|
||
show_bgp_community_list_arg_cmd,
|
||
"show bgp community-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
BGP_STR
|
||
"List community-list\n"
|
||
"Community-list number\n"
|
||
"Community-list name\n")
|
||
{
|
||
int idx_comm_list = 3;
|
||
struct community_list *list;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used");
|
||
}
|
||
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;
|
||
}
|
||
|
||
ALIAS (show_community_list_arg,
|
||
show_ip_community_list_arg_cmd,
|
||
"show ip community-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List community-list\n"
|
||
"Community-list number\n"
|
||
"Community-list name\n")
|
||
|
||
/*
|
||
* 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;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'bgp large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>'\n");
|
||
zlog_warn("Deprecated option: 'large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>' being used");
|
||
}
|
||
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
|
||
: COMMUNITY_DENY;
|
||
|
||
/* All digit name check. */
|
||
idx = 0;
|
||
argv_find(argv, argc, "WORD", &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, 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;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'no bgp large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>'\n");
|
||
zlog_warn("Deprecated option: 'no ip large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>' being used");
|
||
}
|
||
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, "WORD", &idx);
|
||
|
||
/* Unset community list. */
|
||
ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, 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"
|
||
|
||
#if CONFDATE > 20191005
|
||
CPP_NOTICE("bgpd: remove deprecated 'ip large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>' command")
|
||
#endif
|
||
DEFUN (lcommunity_list_standard,
|
||
bgp_lcommunity_list_standard_cmd,
|
||
"bgp large-community-list (1-99) <deny|permit>",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n")
|
||
{
|
||
return lcommunity_list_set_vty(vty, argc, argv,
|
||
LARGE_COMMUNITY_LIST_STANDARD, 0);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_standard,
|
||
ip_lcommunity_list_standard_cmd,
|
||
"ip large-community-list (1-99) <deny|permit>",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n")
|
||
|
||
DEFUN (lcommunity_list_standard1,
|
||
bgp_lcommunity_list_standard1_cmd,
|
||
"bgp large-community-list (1-99) <deny|permit> AA:BB:CC...",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\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);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_standard1,
|
||
ip_lcommunity_list_standard1_cmd,
|
||
"ip large-community-list (1-99) <deny|permit> AA:BB:CC...",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
LCOMMUNITY_VAL_STR)
|
||
|
||
DEFUN (lcommunity_list_expanded,
|
||
bgp_lcommunity_list_expanded_cmd,
|
||
"bgp large-community-list (100-500) <deny|permit> LINE...",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (expanded)\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);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_expanded,
|
||
ip_lcommunity_list_expanded_cmd,
|
||
"ip large-community-list (100-500) <deny|permit> LINE...",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (expanded)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
DEFUN (lcommunity_list_name_standard,
|
||
bgp_lcommunity_list_name_standard_cmd,
|
||
"bgp large-community-list standard WORD <deny|permit>",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n")
|
||
{
|
||
return lcommunity_list_set_vty(vty, argc, argv,
|
||
LARGE_COMMUNITY_LIST_STANDARD, 1);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_name_standard,
|
||
ip_lcommunity_list_name_standard_cmd,
|
||
"ip large-community-list standard WORD <deny|permit>",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n")
|
||
|
||
DEFUN (lcommunity_list_name_standard1,
|
||
bgp_lcommunity_list_name_standard1_cmd,
|
||
"bgp large-community-list standard WORD <deny|permit> AA:BB:CC...",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\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);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_name_standard1,
|
||
ip_lcommunity_list_name_standard1_cmd,
|
||
"ip large-community-list standard WORD <deny|permit> AA:BB:CC...",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
LCOMMUNITY_VAL_STR)
|
||
|
||
DEFUN (lcommunity_list_name_expanded,
|
||
bgp_lcommunity_list_name_expanded_cmd,
|
||
"bgp large-community-list expanded WORD <deny|permit> LINE...",
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify expanded large-community-list\n"
|
||
"Large Community list name\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);
|
||
}
|
||
|
||
ALIAS (lcommunity_list_name_expanded,
|
||
ip_lcommunity_list_name_expanded_cmd,
|
||
"ip large-community-list expanded WORD <deny|permit> LINE...",
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify expanded large-community-list\n"
|
||
"Large Community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
DEFUN (no_lcommunity_list_standard_all,
|
||
no_bgp_lcommunity_list_standard_all_cmd,
|
||
"no bgp large-community-list <(1-99)|(100-500)|WORD>",
|
||
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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_standard_all,
|
||
no_ip_lcommunity_list_standard_all_cmd,
|
||
"no ip large-community-list <(1-99)|(100-500)|WORD>",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\n"
|
||
"Large Community list number (expanded)\n"
|
||
"Large Community list name\n")
|
||
|
||
DEFUN (no_lcommunity_list_name_expanded_all,
|
||
no_bgp_lcommunity_list_name_expanded_all_cmd,
|
||
"no bgp large-community-list expanded WORD",
|
||
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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_name_expanded_all,
|
||
no_ip_lcommunity_list_name_expanded_all_cmd,
|
||
"no ip large-community-list expanded WORD",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify expanded large-community-list\n"
|
||
"Large Community list name\n")
|
||
|
||
DEFUN (no_lcommunity_list_standard,
|
||
no_bgp_lcommunity_list_standard_cmd,
|
||
"no bgp large-community-list (1-99) <deny|permit> AA:AA:NN...",
|
||
NO_STR
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_standard,
|
||
no_ip_lcommunity_list_standard_cmd,
|
||
"no ip large-community-list (1-99) <deny|permit> AA:AA:NN...",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (standard)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
LCOMMUNITY_VAL_STR)
|
||
|
||
DEFUN (no_lcommunity_list_expanded,
|
||
no_bgp_lcommunity_list_expanded_cmd,
|
||
"no bgp large-community-list (100-500) <deny|permit> LINE...",
|
||
NO_STR
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (expanded)\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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_expanded,
|
||
no_ip_lcommunity_list_expanded_cmd,
|
||
"no ip large-community-list (100-500) <deny|permit> LINE...",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Large Community list number (expanded)\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
DEFUN (no_lcommunity_list_name_standard,
|
||
no_bgp_lcommunity_list_name_standard_cmd,
|
||
"no bgp large-community-list standard WORD <deny|permit> AA:AA:NN...",
|
||
NO_STR
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_name_standard,
|
||
no_ip_lcommunity_list_name_standard_cmd,
|
||
"no ip large-community-list standard WORD <deny|permit> AA:AA:NN...",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify standard large-community-list\n"
|
||
"Large Community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
LCOMMUNITY_VAL_STR)
|
||
|
||
DEFUN (no_lcommunity_list_name_expanded,
|
||
no_bgp_lcommunity_list_name_expanded_cmd,
|
||
"no bgp large-community-list expanded WORD <deny|permit> LINE...",
|
||
NO_STR
|
||
BGP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify expanded large-community-list\n"
|
||
"Large community list name\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);
|
||
}
|
||
|
||
ALIAS (no_lcommunity_list_name_expanded,
|
||
no_ip_lcommunity_list_name_expanded_cmd,
|
||
"no ip large-community-list expanded WORD <deny|permit> LINE...",
|
||
NO_STR
|
||
IP_STR
|
||
LCOMMUNITY_LIST_STR
|
||
"Specify expanded large-community-list\n"
|
||
"Large community list name\n"
|
||
"Specify large community to reject\n"
|
||
"Specify large community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
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);
|
||
}
|
||
if (entry->any)
|
||
vty_out(vty, " %s\n",
|
||
community_direct_str(entry->direct));
|
||
else
|
||
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;
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used");
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
ALIAS (show_lcommunity_list,
|
||
show_ip_lcommunity_list_cmd,
|
||
"show ip large-community-list",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List large-community list\n")
|
||
|
||
DEFUN (show_lcommunity_list_arg,
|
||
show_bgp_lcommunity_list_arg_cmd,
|
||
"show bgp large-community-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
BGP_STR
|
||
"List large-community list\n"
|
||
"large-community-list number\n"
|
||
"large-community-list name\n")
|
||
{
|
||
struct community_list *list;
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used");
|
||
}
|
||
|
||
list = community_list_lookup(bgp_clist, argv[3]->arg, 0,
|
||
LARGE_COMMUNITY_LIST_MASTER);
|
||
if (!list) {
|
||
vty_out(vty, "%% Can't find extcommunity-list\n");
|
||
return CMD_WARNING;
|
||
}
|
||
|
||
lcommunity_list_show(vty, list);
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
ALIAS (show_lcommunity_list_arg,
|
||
show_ip_lcommunity_list_arg_cmd,
|
||
"show ip large-community-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List large-community list\n"
|
||
"large-community-list number\n"
|
||
"large-community-list name\n")
|
||
|
||
/* "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 WORD> <deny|permit> AA:NN...",
|
||
BGP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (standard)\n"
|
||
"Specify standard extcommunity-list\n"
|
||
"Community list name\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;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>'\n");
|
||
zlog_warn("Deprecated option: 'ip extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>' being used");
|
||
}
|
||
argv_find(argv, argc, "(1-99)", &idx);
|
||
argv_find(argv, argc, "WORD", &idx);
|
||
cl_number_or_name = 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,
|
||
direct, style);
|
||
|
||
XFREE(MTYPE_TMP, str);
|
||
|
||
if (ret < 0) {
|
||
community_list_perror(vty, ret);
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
#if CONFDATE > 20191005
|
||
CPP_NOTICE("bgpd: remove deprecated 'ip extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>' command")
|
||
#endif
|
||
ALIAS (extcommunity_list_standard,
|
||
ip_extcommunity_list_standard_cmd,
|
||
"ip extcommunity-list <(1-99)|standard WORD> <deny|permit> AA:NN...",
|
||
IP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (standard)\n"
|
||
"Specify standard extcommunity-list\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
EXTCOMMUNITY_VAL_STR)
|
||
|
||
DEFUN (extcommunity_list_name_expanded,
|
||
bgp_extcommunity_list_name_expanded_cmd,
|
||
"bgp extcommunity-list <(100-500)|expanded WORD> <deny|permit> LINE...",
|
||
BGP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (expanded)\n"
|
||
"Specify expanded extcommunity-list\n"
|
||
"Extended Community list name\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;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>'\n");
|
||
zlog_warn("Deprecated option: ‘ip extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>' being used");
|
||
}
|
||
|
||
argv_find(argv, argc, "(100-500)", &idx);
|
||
argv_find(argv, argc, "WORD", &idx);
|
||
cl_number_or_name = 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,
|
||
direct, style);
|
||
|
||
XFREE(MTYPE_TMP, str);
|
||
|
||
if (ret < 0) {
|
||
community_list_perror(vty, ret);
|
||
return CMD_WARNING_CONFIG_FAILED;
|
||
}
|
||
|
||
return CMD_SUCCESS;
|
||
}
|
||
|
||
ALIAS (extcommunity_list_name_expanded,
|
||
ip_extcommunity_list_name_expanded_cmd,
|
||
"ip extcommunity-list <(100-500)|expanded WORD> <deny|permit> LINE...",
|
||
IP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (expanded)\n"
|
||
"Specify expanded extcommunity-list\n"
|
||
"Extended Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
DEFUN (no_extcommunity_list_standard_all,
|
||
no_bgp_extcommunity_list_standard_all_cmd,
|
||
"no bgp extcommunity-list <(1-99)|standard WORD> <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"
|
||
"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;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'no bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>'\n");
|
||
zlog_warn("Deprecated option: ‘no ip extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>' being used");
|
||
}
|
||
|
||
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, "WORD", &idx);
|
||
cl_number_or_name = argv[idx]->arg;
|
||
|
||
int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
|
||
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_ip_extcommunity_list_standard_all_cmd,
|
||
"no ip extcommunity-list <(1-99)|standard WORD> <deny|permit> AA:NN...",
|
||
NO_STR
|
||
IP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (standard)\n"
|
||
"Specify standard extcommunity-list\n"
|
||
"Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
EXTCOMMUNITY_VAL_STR)
|
||
|
||
ALIAS(no_extcommunity_list_standard_all,
|
||
no_bgp_extcommunity_list_standard_all_list_cmd,
|
||
"no bgp extcommunity-list <(1-99)|standard WORD>",
|
||
NO_STR IP_STR EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (standard)\n"
|
||
"Specify standard extcommunity-list\n"
|
||
"Community list name\n")
|
||
|
||
ALIAS(no_extcommunity_list_standard_all,
|
||
no_ip_extcommunity_list_standard_all_list_cmd,
|
||
"no ip extcommunity-list <(1-99)|standard WORD>",
|
||
NO_STR IP_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 WORD> <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"
|
||
"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;
|
||
|
||
int idx = 0;
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'no bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>'\n");
|
||
zlog_warn("Deprecated option: ‘no ip extcommunity-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:NN>' being used");
|
||
}
|
||
|
||
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, "WORD", &idx);
|
||
cl_number_or_name = argv[idx]->arg;
|
||
|
||
int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
|
||
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_ip_extcommunity_list_expanded_all_cmd,
|
||
"no ip extcommunity-list <(100-500)|expanded WORD> <deny|permit> LINE...",
|
||
NO_STR
|
||
IP_STR
|
||
EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (expanded)\n"
|
||
"Specify expanded extcommunity-list\n"
|
||
"Extended Community list name\n"
|
||
"Specify community to reject\n"
|
||
"Specify community to accept\n"
|
||
"An ordered list as a regular-expression\n")
|
||
|
||
ALIAS(no_extcommunity_list_expanded_all,
|
||
no_ip_extcommunity_list_expanded_all_list_cmd,
|
||
"no ip extcommunity-list <(100-500)|expanded WORD>",
|
||
NO_STR IP_STR EXTCOMMUNITY_LIST_STR
|
||
"Extended Community list number (expanded)\n"
|
||
"Specify expanded extcommunity-list\n"
|
||
"Extended Community list name\n")
|
||
|
||
ALIAS(no_extcommunity_list_expanded_all,
|
||
no_bgp_extcommunity_list_expanded_all_list_cmd,
|
||
"no bgp extcommunity-list <(100-500)|expanded WORD>",
|
||
NO_STR IP_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);
|
||
}
|
||
if (entry->any)
|
||
vty_out(vty, " %s\n",
|
||
community_direct_str(entry->direct));
|
||
else
|
||
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;
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used");
|
||
}
|
||
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;
|
||
}
|
||
|
||
ALIAS (show_extcommunity_list,
|
||
show_ip_extcommunity_list_cmd,
|
||
"show ip extcommunity-list",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List extended-community list\n")
|
||
|
||
DEFUN (show_extcommunity_list_arg,
|
||
show_bgp_extcommunity_list_arg_cmd,
|
||
"show bgp extcommunity-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
BGP_STR
|
||
"List extended-community list\n"
|
||
"Extcommunity-list number\n"
|
||
"Extcommunity-list name\n")
|
||
{
|
||
int idx_comm_list = 3;
|
||
struct community_list *list;
|
||
int idx = 0;
|
||
|
||
if (argv_find(argv, argc, "ip", &idx)) {
|
||
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
|
||
vty_out(vty, "if you are using this please migrate to the below command.\n");
|
||
vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n");
|
||
zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used");
|
||
}
|
||
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;
|
||
}
|
||
|
||
ALIAS (show_extcommunity_list_arg,
|
||
show_ip_extcommunity_list_arg_cmd,
|
||
"show ip extcommunity-list <(1-500)|WORD>",
|
||
SHOW_STR
|
||
IP_STR
|
||
"List extended-community list\n"
|
||
"Extcommunity-list number\n"
|
||
"Extcommunity-list name\n")
|
||
|
||
/* 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 %s %s\n", list->name,
|
||
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 %s %s\n",
|
||
entry->style == COMMUNITY_LIST_STANDARD
|
||
? "standard"
|
||
: "expanded",
|
||
list->name, 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 %s %s\n",
|
||
list->name, 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 %s %s\n",
|
||
entry->style == EXTCOMMUNITY_LIST_STANDARD
|
||
? "standard"
|
||
: "expanded",
|
||
list->name, 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 %s %s\n",
|
||
list->name, 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 %s %s\n",
|
||
entry->style == LARGE_COMMUNITY_LIST_STANDARD
|
||
? "standard"
|
||
: "expanded",
|
||
list->name, community_direct_str(entry->direct),
|
||
community_list_config_str(entry));
|
||
write++;
|
||
}
|
||
|
||
return write;
|
||
}
|
||
|
||
static struct cmd_node community_list_node = {
|
||
COMMUNITY_LIST_NODE, "", 1 /* Export to vtysh. */
|
||
};
|
||
|
||
static void community_list_vty(void)
|
||
{
|
||
install_node(&community_list_node, community_list_config_write);
|
||
|
||
/* 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);
|
||
install_element(CONFIG_NODE, &ip_community_list_standard_cmd);
|
||
install_element(CONFIG_NODE, &ip_community_list_expanded_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_community_list_standard_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_community_list_standard_all_list_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_community_list_expanded_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_community_list_expanded_all_list_cmd);
|
||
install_element(VIEW_NODE, &show_ip_community_list_cmd);
|
||
install_element(VIEW_NODE, &show_ip_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);
|
||
install_element(CONFIG_NODE, &ip_extcommunity_list_standard_cmd);
|
||
install_element(CONFIG_NODE, &ip_extcommunity_list_name_expanded_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_extcommunity_list_standard_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_extcommunity_list_standard_all_list_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_list_cmd);
|
||
install_element(VIEW_NODE, &show_ip_extcommunity_list_cmd);
|
||
install_element(VIEW_NODE, &show_ip_extcommunity_list_arg_cmd);
|
||
|
||
/* Large Community List */
|
||
install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd);
|
||
install_element(CONFIG_NODE, &bgp_lcommunity_list_standard1_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_standard1_cmd);
|
||
install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd);
|
||
install_element(CONFIG_NODE, &no_bgp_lcommunity_list_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);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd);
|
||
install_element(CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd);
|
||
install_element(CONFIG_NODE,
|
||
&no_ip_lcommunity_list_name_expanded_all_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_lcommunity_list_expanded_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_lcommunity_list_name_standard_cmd);
|
||
install_element(CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_cmd);
|
||
install_element(VIEW_NODE, &show_ip_lcommunity_list_cmd);
|
||
install_element(VIEW_NODE, &show_ip_lcommunity_list_arg_cmd);
|
||
}
|