forked from Mirror/frr
lib, bgp: add initial support for asdot format
AS number can be defined as an unsigned long number, or two uint16 values separated by a period (.). The possible valus are: - usual 32 bit values : [1;2^32 -1] - <1.65535>.<0.65535> for dot notation - <0.65535>.<0.65535> for dot+ notation. The 0.0 value is forbidden when configuring BGP instances or peer configurations. A new ASN type is added for parsing in the vty. The following commands use that new identifier: - router bgp .. - bgp confederation .. - neighbor <> remote-as <> - neighbor <> local-as <> - clear ip bgp <> - route-map / set as-path <> An asn library is available in lib/ and provides some services: - convert an as string into an as number. - parse an as path list string and extract a number. - convert an as number into a string. Also, the bgp tests forge an as_zero_path, and to do that, an API to relax the possibility to have a 0 as value is specifically called from the tests. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
9eb1199710
commit
8079a4138d
|
@ -1940,6 +1940,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
|
|||
unsigned long *asno)
|
||||
{
|
||||
const char *p = buf;
|
||||
as_t asval;
|
||||
bool found = false;
|
||||
|
||||
/* Skip separators (space for sequences, ',' for sets). */
|
||||
while (isspace((unsigned char)*p) || *p == ',')
|
||||
|
@ -1976,26 +1978,13 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Check actual AS value. */
|
||||
if (isdigit((unsigned char)*p)) {
|
||||
as_t asval;
|
||||
|
||||
*token = as_token_asval;
|
||||
asval = (*p - '0');
|
||||
p++;
|
||||
|
||||
while (isdigit((unsigned char)*p)) {
|
||||
asval *= 10;
|
||||
asval += (*p - '0');
|
||||
p++;
|
||||
}
|
||||
asval = 0;
|
||||
p = asn_str2asn_parse(p, &asval, &found);
|
||||
if (found) {
|
||||
*asno = asval;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* There is no match then return unknown token. */
|
||||
*token = as_token_unknown;
|
||||
p++;
|
||||
*token = as_token_asval;
|
||||
} else
|
||||
*token = as_token_unknown;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -5608,15 +5608,16 @@ DEFUN_YANG (no_set_label_index,
|
|||
|
||||
DEFUN_YANG (set_aspath_prepend_asn,
|
||||
set_aspath_prepend_asn_cmd,
|
||||
"set as-path prepend (1-4294967295)...",
|
||||
"set as-path prepend ASNUM...",
|
||||
SET_STR
|
||||
"Transform BGP AS_PATH attribute\n"
|
||||
"Prepend to the as-path\n"
|
||||
"AS number\n")
|
||||
AS_STR)
|
||||
{
|
||||
int idx_asn = 3;
|
||||
int ret;
|
||||
char *str;
|
||||
struct aspath *aspath;
|
||||
|
||||
str = argv_concat(argv, argc, idx_asn);
|
||||
|
||||
|
@ -5624,6 +5625,12 @@ DEFUN_YANG (set_aspath_prepend_asn,
|
|||
"./set-action[action='frr-bgp-route-map:as-path-prepend']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
|
||||
aspath = route_aspath_compile(str);
|
||||
if (!aspath) {
|
||||
vty_out(vty, "%% Invalid AS path value %s\n", str);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
route_aspath_free(aspath);
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
|
||||
|
@ -5658,16 +5665,22 @@ DEFUN_YANG (set_aspath_prepend_lastas,
|
|||
|
||||
DEFPY_YANG (set_aspath_replace_asn,
|
||||
set_aspath_replace_asn_cmd,
|
||||
"set as-path replace <any|(1-4294967295)>$replace",
|
||||
"set as-path replace <any|ASNUM>$replace",
|
||||
SET_STR
|
||||
"Transform BGP AS_PATH attribute\n"
|
||||
"Replace AS number to local AS number\n"
|
||||
"Replace any AS number to local AS number\n"
|
||||
"Replace a specific AS number to local AS number\n")
|
||||
"Replace a specific AS number in plain or dotted format to local AS number\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
as_t as_value;
|
||||
|
||||
if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) {
|
||||
vty_out(vty, "%% Invalid AS value %s\n", replace);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
|
@ -5678,13 +5691,13 @@ DEFPY_YANG (set_aspath_replace_asn,
|
|||
|
||||
DEFPY_YANG (no_set_aspath_replace_asn,
|
||||
no_set_aspath_replace_asn_cmd,
|
||||
"no set as-path replace [<any|(1-4294967295)>]",
|
||||
"no set as-path replace [<any|ASNUM>]",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Transform BGP AS_PATH attribute\n"
|
||||
"Replace AS number to local AS number\n"
|
||||
"Replace any AS number to local AS number\n"
|
||||
"Replace a specific AS number to local AS number\n")
|
||||
"Replace a specific AS number in plain or dotted format to local AS number\n")
|
||||
{
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
||||
|
@ -5695,12 +5708,12 @@ DEFPY_YANG (no_set_aspath_replace_asn,
|
|||
|
||||
DEFUN_YANG (no_set_aspath_prepend,
|
||||
no_set_aspath_prepend_cmd,
|
||||
"no set as-path prepend [(1-4294967295)]",
|
||||
"no set as-path prepend [ASNUM]",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Transform BGP AS_PATH attribute\n"
|
||||
"Prepend to the as-path\n"
|
||||
"AS number\n")
|
||||
AS_STR)
|
||||
{
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:as-path-prepend']";
|
||||
|
@ -5728,15 +5741,16 @@ DEFUN_YANG (no_set_aspath_prepend_lastas,
|
|||
|
||||
DEFUN_YANG (set_aspath_exclude,
|
||||
set_aspath_exclude_cmd,
|
||||
"set as-path exclude (1-4294967295)...",
|
||||
"set as-path exclude ASNUM...",
|
||||
SET_STR
|
||||
"Transform BGP AS-path attribute\n"
|
||||
"Exclude from the as-path\n"
|
||||
"AS number\n")
|
||||
AS_STR)
|
||||
{
|
||||
int idx_asn = 3;
|
||||
int ret;
|
||||
char *str;
|
||||
struct aspath *aspath;
|
||||
|
||||
str = argv_concat(argv, argc, idx_asn);
|
||||
|
||||
|
@ -5744,6 +5758,12 @@ DEFUN_YANG (set_aspath_exclude,
|
|||
"./set-action[action='frr-bgp-route-map:as-path-exclude']";
|
||||
char xpath_value[XPATH_MAXLEN];
|
||||
|
||||
aspath = route_aspath_compile(str);
|
||||
if (!aspath) {
|
||||
vty_out(vty, "%% Invalid AS path value %s\n", str);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
route_aspath_free(aspath);
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
snprintf(xpath_value, sizeof(xpath_value),
|
||||
"%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
|
||||
|
@ -5755,7 +5775,7 @@ DEFUN_YANG (set_aspath_exclude,
|
|||
|
||||
DEFUN_YANG (no_set_aspath_exclude,
|
||||
no_set_aspath_exclude_cmd,
|
||||
"no set as-path exclude (1-4294967295)...",
|
||||
"no set as-path exclude ASNUM...",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Transform BGP AS_PATH attribute\n"
|
||||
|
@ -6441,11 +6461,11 @@ DEFPY_YANG (no_set_aigp_metric,
|
|||
|
||||
DEFUN_YANG (set_aggregator_as,
|
||||
set_aggregator_as_cmd,
|
||||
"set aggregator as (1-4294967295) A.B.C.D",
|
||||
"set aggregator as ASNUM A.B.C.D",
|
||||
SET_STR
|
||||
"BGP aggregator attribute\n"
|
||||
"AS number of aggregator\n"
|
||||
"AS number\n"
|
||||
AS_STR
|
||||
"IP address of aggregator\n")
|
||||
{
|
||||
int idx_number = 3;
|
||||
|
@ -6454,6 +6474,12 @@ DEFUN_YANG (set_aggregator_as,
|
|||
char xpath_addr[XPATH_MAXLEN];
|
||||
const char *xpath =
|
||||
"./set-action[action='frr-bgp-route-map:aggregator']";
|
||||
as_t as_value;
|
||||
|
||||
if (!asn_str2asn(argv[idx_number]->arg, &as_value)) {
|
||||
vty_out(vty, "%% Invalid AS value %s\n", argv[idx_number]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
|
@ -6476,12 +6502,12 @@ DEFUN_YANG (set_aggregator_as,
|
|||
|
||||
DEFUN_YANG (no_set_aggregator_as,
|
||||
no_set_aggregator_as_cmd,
|
||||
"no set aggregator as [(1-4294967295) A.B.C.D]",
|
||||
"no set aggregator as [ASNUM A.B.C.D]",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"BGP aggregator attribute\n"
|
||||
"AS number of aggregator\n"
|
||||
"AS number\n"
|
||||
AS_STR
|
||||
"IP address of aggregator\n")
|
||||
{
|
||||
const char *xpath =
|
||||
|
|
136
bgpd/bgp_vty.c
136
bgpd/bgp_vty.c
|
@ -39,6 +39,7 @@
|
|||
#include "queue.h"
|
||||
#include "filter.h"
|
||||
#include "frrstr.h"
|
||||
#include "asn.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_attr_evpn.h"
|
||||
|
@ -1237,7 +1238,12 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||
|
||||
/* Clear all neighbors belonging to a specific AS. */
|
||||
if (sort == clear_as) {
|
||||
as_t as = strtoul(arg, NULL, 10);
|
||||
as_t as;
|
||||
|
||||
if (!asn_str2asn(arg, &as)) {
|
||||
vty_out(vty, "%% BGP: No such AS %s\n", arg);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||
if (peer->as != as)
|
||||
|
@ -1475,7 +1481,7 @@ DEFUN (no_auto_summary,
|
|||
/* "router bgp" commands. */
|
||||
DEFUN_NOSH (router_bgp,
|
||||
router_bgp_cmd,
|
||||
"router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]",
|
||||
"router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME]]",
|
||||
ROUTER_STR
|
||||
BGP_STR
|
||||
AS_STR
|
||||
|
@ -1509,7 +1515,11 @@ DEFUN_NOSH (router_bgp,
|
|||
|
||||
// "router bgp X"
|
||||
else {
|
||||
as = strtoul(argv[idx_asn]->arg, NULL, 10);
|
||||
if (!asn_str2asn(argv[idx_asn]->arg, &as)) {
|
||||
vty_out(vty, "%% BGP: No such AS %s\n",
|
||||
argv[idx_asn]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (as == BGP_PRIVATE_AS_MAX || as == BGP_AS4_MAX)
|
||||
vty_out(vty, "Reserved AS used (%u|%u); AS is %u\n",
|
||||
|
@ -1571,7 +1581,7 @@ DEFUN_NOSH (router_bgp,
|
|||
/* "no router bgp" commands. */
|
||||
DEFUN (no_router_bgp,
|
||||
no_router_bgp_cmd,
|
||||
"no router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]",
|
||||
"no router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME]]",
|
||||
NO_STR
|
||||
ROUTER_STR
|
||||
BGP_STR
|
||||
|
@ -1605,8 +1615,11 @@ DEFUN (no_router_bgp,
|
|||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
} else {
|
||||
as = strtoul(argv[idx_asn]->arg, NULL, 10);
|
||||
|
||||
if (!asn_str2asn(argv[idx_asn]->arg, &as)) {
|
||||
vty_out(vty, "%% BGP: No such AS %s\n",
|
||||
argv[idx_asn]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (argc > 4) {
|
||||
name = argv[idx_vrf]->arg;
|
||||
if (strmatch(argv[idx_vrf - 1]->text, "vrf")
|
||||
|
@ -1934,17 +1947,20 @@ DEFPY (no_bgp_send_extra_data,
|
|||
|
||||
DEFUN (bgp_confederation_identifier,
|
||||
bgp_confederation_identifier_cmd,
|
||||
"bgp confederation identifier (1-4294967295)",
|
||||
"bgp confederation identifier ASNUM",
|
||||
BGP_STR
|
||||
"AS confederation parameters\n"
|
||||
"AS number\n"
|
||||
AS_STR
|
||||
"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);
|
||||
if (!asn_str2asn(argv[idx_number]->arg, &as)) {
|
||||
vty_out(vty, "%% BGP: No such AS %s\n", argv[idx_number]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
bgp_confederation_id_set(bgp, as);
|
||||
|
||||
|
@ -1953,11 +1969,11 @@ DEFUN (bgp_confederation_identifier,
|
|||
|
||||
DEFUN (no_bgp_confederation_identifier,
|
||||
no_bgp_confederation_identifier_cmd,
|
||||
"no bgp confederation identifier [(1-4294967295)]",
|
||||
"no bgp confederation identifier [ASNUM]",
|
||||
NO_STR
|
||||
BGP_STR
|
||||
"AS confederation parameters\n"
|
||||
"AS number\n"
|
||||
AS_STR
|
||||
"Set routing domain confederation AS\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
|
@ -1968,7 +1984,7 @@ DEFUN (no_bgp_confederation_identifier,
|
|||
|
||||
DEFUN (bgp_confederation_peers,
|
||||
bgp_confederation_peers_cmd,
|
||||
"bgp confederation peers (1-4294967295)...",
|
||||
"bgp confederation peers ASNUM...",
|
||||
BGP_STR
|
||||
"AS confederation parameters\n"
|
||||
"Peer ASs in BGP confederation\n"
|
||||
|
@ -1980,7 +1996,12 @@ DEFUN (bgp_confederation_peers,
|
|||
int i;
|
||||
|
||||
for (i = idx_asn; i < argc; i++) {
|
||||
as = strtoul(argv[i]->arg, NULL, 10);
|
||||
if (!asn_str2asn(argv[i]->arg, &as)) {
|
||||
vty_out(vty, "%% Invalid confed peer AS value: %s\n",
|
||||
argv[i]->arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
bgp_confederation_peers_add(bgp, as);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
|
@ -1988,7 +2009,7 @@ DEFUN (bgp_confederation_peers,
|
|||
|
||||
DEFUN (no_bgp_confederation_peers,
|
||||
no_bgp_confederation_peers_cmd,
|
||||
"no bgp confederation peers (1-4294967295)...",
|
||||
"no bgp confederation peers ASNUM...",
|
||||
NO_STR
|
||||
BGP_STR
|
||||
"AS confederation parameters\n"
|
||||
|
@ -2001,8 +2022,11 @@ DEFUN (no_bgp_confederation_peers,
|
|||
int i;
|
||||
|
||||
for (i = idx_asn; i < argc; i++) {
|
||||
as = strtoul(argv[i]->arg, NULL, 10);
|
||||
|
||||
if (!asn_str2asn(argv[i]->arg, &as)) {
|
||||
vty_out(vty, "%% Invalid confed peer AS value: %s\n",
|
||||
argv[i]->arg);
|
||||
continue;
|
||||
}
|
||||
bgp_confederation_peers_remove(bgp, as);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
|
@ -4506,11 +4530,13 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
|
|||
} else if (as_str[0] == 'e') {
|
||||
as = 0;
|
||||
as_type = AS_EXTERNAL;
|
||||
} else {
|
||||
/* Get AS number. */
|
||||
as = strtoul(as_str, NULL, 10);
|
||||
}
|
||||
} else if (!asn_str2asn(as_str, &as))
|
||||
as_type = AS_UNSPECIFIED;
|
||||
|
||||
if (as_type == AS_UNSPECIFIED) {
|
||||
vty_out(vty, "%% Invalid peer AS: %s\n", as_str);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
/* If peer is peer group or interface peer, call proper function. */
|
||||
ret = str2sockunion(peer_str, &su);
|
||||
if (ret < 0) {
|
||||
|
@ -4608,7 +4634,7 @@ ALIAS(no_bgp_shutdown, no_bgp_shutdown_msg_cmd,
|
|||
|
||||
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 <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external>",
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Specify a BGP neighbor\n"
|
||||
|
@ -4688,8 +4714,8 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,
|
|||
as_type = AS_EXTERNAL;
|
||||
} else {
|
||||
/* Get AS number. */
|
||||
as = strtoul(as_str, NULL, 10);
|
||||
as_type = AS_SPECIFIED;
|
||||
if (asn_str2asn(as_str, &as))
|
||||
as_type = AS_SPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4801,7 +4827,7 @@ DEFUN (neighbor_interface_config_v6only,
|
|||
|
||||
DEFUN (neighbor_interface_config_remote_as,
|
||||
neighbor_interface_config_remote_as_cmd,
|
||||
"neighbor WORD interface remote-as <(1-4294967295)|internal|external>",
|
||||
"neighbor WORD interface remote-as <ASNUM|internal|external>",
|
||||
NEIGHBOR_STR
|
||||
"Interface name or neighbor tag\n"
|
||||
"Enable BGP on interface\n"
|
||||
|
@ -4818,7 +4844,7 @@ DEFUN (neighbor_interface_config_remote_as,
|
|||
|
||||
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 WORD interface v6only remote-as <ASNUM|internal|external>",
|
||||
NEIGHBOR_STR
|
||||
"Interface name or neighbor tag\n"
|
||||
"Enable BGP with v6 link-local only\n"
|
||||
|
@ -4987,7 +5013,7 @@ DEFUN (no_neighbor_peer_group,
|
|||
|
||||
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 neighbor WORD remote-as <ASNUM|internal|external>",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
"Interface name or neighbor tag\n"
|
||||
|
@ -5020,11 +5046,11 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,
|
|||
|
||||
DEFUN (neighbor_local_as,
|
||||
neighbor_local_as_cmd,
|
||||
"neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295)",
|
||||
"neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM",
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Specify a local-as number\n"
|
||||
"AS number used as local AS\n")
|
||||
"AS number expressed in dotted or plain format used as local AS\n")
|
||||
{
|
||||
int idx_peer = 1;
|
||||
int idx_number = 3;
|
||||
|
@ -5036,18 +5062,23 @@ DEFUN (neighbor_local_as,
|
|||
if (!peer)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
if (!asn_str2asn(argv[idx_number]->arg, &as)) {
|
||||
vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
|
||||
argv[idx_number]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
ret = peer_local_as_set(peer, as, 0, 0);
|
||||
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 <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend",
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Specify a local-as number\n"
|
||||
"AS number used as local AS\n"
|
||||
"AS number expressed in dotted or plain format used as local AS\n"
|
||||
"Do not prepend local-as to updates from ebgp peers\n")
|
||||
{
|
||||
int idx_peer = 1;
|
||||
|
@ -5060,18 +5091,23 @@ DEFUN (neighbor_local_as_no_prepend,
|
|||
if (!peer)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
if (!asn_str2asn(argv[idx_number]->arg, &as)) {
|
||||
vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
|
||||
argv[idx_number]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
ret = peer_local_as_set(peer, as, 1, 0);
|
||||
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 <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as",
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Specify a local-as number\n"
|
||||
"AS number used as local AS\n"
|
||||
"AS number expressed in dotted or plain format used as local AS\n"
|
||||
"Do not prepend local-as to updates from ebgp peers\n"
|
||||
"Do not prepend local-as to updates from ibgp peers\n")
|
||||
{
|
||||
|
@ -5085,19 +5121,24 @@ DEFUN (neighbor_local_as_no_prepend_replace_as,
|
|||
if (!peer)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
as = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
if (!asn_str2asn(argv[idx_number]->arg, &as)) {
|
||||
vty_out(vty, "%% Invalid neighbor local-as value: %s\n",
|
||||
argv[idx_number]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
ret = peer_local_as_set(peer, as, 1, 1);
|
||||
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 neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as]]]",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Specify a local-as number\n"
|
||||
"AS number used as local AS\n"
|
||||
"AS number expressed in dotted or plain format used as local AS\n"
|
||||
"Do not prepend local-as to updates from ebgp peers\n"
|
||||
"Do not prepend local-as to updates from ibgp peers\n")
|
||||
{
|
||||
|
@ -10084,7 +10125,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
|
|||
/* one clear bgp command to rule them all */
|
||||
DEFUN (clear_ip_bgp_all,
|
||||
clear_ip_bgp_all_cmd,
|
||||
"clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
|
||||
"clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
|
||||
CLEAR_STR
|
||||
IP_STR
|
||||
BGP_STR
|
||||
|
@ -10097,7 +10138,7 @@ DEFUN (clear_ip_bgp_all,
|
|||
"BGP IPv4 neighbor to clear\n"
|
||||
"BGP IPv6 neighbor to clear\n"
|
||||
"BGP neighbor on interface to clear\n"
|
||||
"Clear peers with the AS number\n"
|
||||
"Clear peers with the AS number in plain or dotted format\n"
|
||||
"Clear all external peers\n"
|
||||
"Clear all members of peer-group\n"
|
||||
"BGP peer-group name\n"
|
||||
|
@ -10138,7 +10179,7 @@ DEFUN (clear_ip_bgp_all,
|
|||
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> */
|
||||
/* <*|A.B.C.D|X:X::X:X|WORD|ASNUM|external|peer-group PGNAME> */
|
||||
if (argv_find(argv, argc, "*", &idx)) {
|
||||
clr_sort = clear_all;
|
||||
} else if (argv_find(argv, argc, "A.B.C.D", &idx)) {
|
||||
|
@ -10157,7 +10198,7 @@ DEFUN (clear_ip_bgp_all,
|
|||
} 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)) {
|
||||
} else if (argv_find(argv, argc, "ASNUM", &idx)) {
|
||||
clr_sort = clear_as;
|
||||
clr_arg = argv[idx]->arg;
|
||||
} else if (argv_find(argv, argc, "external", &idx)) {
|
||||
|
@ -11827,7 +11868,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
|
|||
DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
|
||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
|
||||
" [" BGP_SAFI_WITH_LABEL_CMD_STR
|
||||
"]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json$uj]",
|
||||
"]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <ASNUM|internal|external>>] [terse] [wide] [json$uj]",
|
||||
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
|
||||
BGP_SAFI_WITH_LABEL_HELP_STR
|
||||
"Display the entries for all address families\n"
|
||||
|
@ -11838,8 +11879,7 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
|
|||
"Neighbor to display information about\n"
|
||||
"Neighbor to display information about\n"
|
||||
"Neighbor on BGP configured interface\n"
|
||||
"Show only the specified remote AS sessions\n"
|
||||
"AS number\n"
|
||||
"Show only the specified remote AS sessions\n" AS_STR
|
||||
"Internal (iBGP) AS sessions\n"
|
||||
"External (eBGP) AS sessions\n"
|
||||
"Shorten the information on BGP instances\n"
|
||||
|
@ -11881,8 +11921,12 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
|
|||
as_type = AS_INTERNAL;
|
||||
else if (argv[idx + 1]->arg[0] == 'e')
|
||||
as_type = AS_EXTERNAL;
|
||||
else
|
||||
as = (as_t)atoi(argv[idx + 1]->arg);
|
||||
else if (!asn_str2asn(argv[idx + 1]->arg, &as)) {
|
||||
vty_out(vty,
|
||||
"%% Invalid neighbor remote-as value: %s\n",
|
||||
argv[idx + 1]->arg);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (argv_find(argv, argc, "terse", &idx))
|
||||
|
|
|
@ -3200,6 +3200,9 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
|||
bgp->as = *as;
|
||||
if (as_pretty)
|
||||
bgp->as_pretty = XSTRDUP(MTYPE_BGP, as_pretty);
|
||||
else
|
||||
bgp->as_pretty = XSTRDUP(MTYPE_BGP, asn_asn2asplain(*as));
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA)) {
|
||||
if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
|
||||
zlog_debug("Creating Default VRF, AS %s",
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "vty.h"
|
||||
#include "srv6.h"
|
||||
#include "iana_afi.h"
|
||||
#include "asn.h"
|
||||
|
||||
/* For union sockunion. */
|
||||
#include "queue.h"
|
||||
|
@ -77,7 +78,6 @@ enum zebra_gr_mode {
|
|||
};
|
||||
|
||||
/* Typedef BGP specific types. */
|
||||
typedef uint32_t as_t;
|
||||
typedef uint16_t as16_t; /* we may still encounter 16 Bit asnums */
|
||||
typedef uint16_t bgp_size_t;
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ by the parser.
|
|||
: RANGE
|
||||
: MAC
|
||||
: MAC_PREFIX
|
||||
: ASNUM
|
||||
selector: "<" `selector_seq_seq` ">" `varname_token`
|
||||
: "{" `selector_seq_seq` "}" `varname_token`
|
||||
: "[" `selector_seq_seq` "]" `varname_token`
|
||||
|
@ -176,27 +177,29 @@ parser, but this is merely a dumb copy job.
|
|||
|
||||
Here is a brief summary of the various token types along with examples.
|
||||
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| Token type | Syntax | Description |
|
||||
+=================+===================+=============================================================+
|
||||
| ``WORD`` | ``show ip bgp`` | Matches itself. In the given example every token is a WORD. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``MAC`` | ``X:X:X:X:X:X`` | Matches a 48-bit mac address. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``MAC_PREFIX`` | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``VARIABLE`` | ``FOOBAR`` | Matches anything. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. |
|
||||
+-----------------+-------------------+-------------------------------------------------------------+
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| Token type | Syntax | Description |
|
||||
+=================+=========================+=======================================================+
|
||||
| ``WORD`` | ``show ip bgp`` | Matches itself. In the example every token is a WORD. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``IPV4`` | ``A.B.C.D`` | Matches an IPv4 address. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``IPV6`` | ``X:X::X:X`` | Matches an IPv6 address. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``IPV4_PREFIX`` | ``A.B.C.D/M`` | Matches an IPv4 prefix in CIDR notation. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``IPV6_PREFIX`` | ``X:X::X:X/M`` | Matches an IPv6 prefix in CIDR notation. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``MAC`` | ``X:X:X:X:X:X`` | Matches a 48-bit mac address. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``MAC_PREFIX`` | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``VARIABLE`` | ``FOOBAR`` | Matches anything. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``RANGE`` | ``(X-Y)`` | Matches numbers in the range X..Y inclusive. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
| ``ASNUM`` | ``<A.B|(1-4294967295>`` | Matches an AS in plain or dot format. |
|
||||
+-----------------+-------------------------+-------------------------------------------------------+
|
||||
|
||||
When presented with user input, the parser will search over all defined
|
||||
commands in the current context to find a match. It is aware of the various
|
||||
|
|
150
lib/asn.c
Normal file
150
lib/asn.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* ASN functions
|
||||
*
|
||||
* Copyright 2022 6WIND
|
||||
*
|
||||
* This program 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 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 "log.h"
|
||||
#include "asn.h"
|
||||
|
||||
static bool relax_as_zero;
|
||||
|
||||
/* converts a string into an Autonomous system number
|
||||
* "1.1" => 65536
|
||||
* "65500" => 65500
|
||||
*/
|
||||
static bool asn_str2asn_internal(const char *asstring, as_t *asn,
|
||||
const char **next, bool *partial)
|
||||
{
|
||||
uint32_t high = 0, low = 0;
|
||||
uint64_t temp_val;
|
||||
const char *p = asstring;
|
||||
bool ret = false;
|
||||
uint32_t digit;
|
||||
|
||||
if (!asstring)
|
||||
goto end;
|
||||
|
||||
if (!isdigit((unsigned char)*p))
|
||||
goto end;
|
||||
|
||||
temp_val = 0;
|
||||
while (isdigit((unsigned char)*p)) {
|
||||
digit = (*p) - '0';
|
||||
temp_val *= 10;
|
||||
temp_val += digit;
|
||||
if (temp_val > UINT32_MAX)
|
||||
/* overflow */
|
||||
goto end;
|
||||
p++;
|
||||
}
|
||||
high = (uint32_t)temp_val;
|
||||
if (*p == '.') { /* dot format */
|
||||
p++;
|
||||
temp_val = 0;
|
||||
if (*p == '\0' && partial) {
|
||||
*partial = true;
|
||||
goto end;
|
||||
}
|
||||
while (isdigit((unsigned char)*p)) {
|
||||
digit = (*p) - '0';
|
||||
temp_val *= 10;
|
||||
temp_val += digit;
|
||||
if (temp_val > UINT16_MAX)
|
||||
/* overflow */
|
||||
goto end;
|
||||
p++;
|
||||
}
|
||||
low = (uint32_t)temp_val;
|
||||
|
||||
if (!next && *p != '\0' && !isdigit((unsigned char)*p))
|
||||
goto end;
|
||||
/* AS <AS4B>.<AS4B> is forbidden */
|
||||
if (high > UINT16_MAX)
|
||||
goto end;
|
||||
/* AS 0.0 is authorised for some case only */
|
||||
if (!relax_as_zero && high == 0 && low == 0) {
|
||||
if (partial)
|
||||
*partial = true;
|
||||
goto end;
|
||||
}
|
||||
if (!asn) {
|
||||
ret = true;
|
||||
goto end;
|
||||
}
|
||||
*asn = (high << 16) + low;
|
||||
ret = true;
|
||||
goto end;
|
||||
}
|
||||
/* AS 0 is forbidden */
|
||||
if (!relax_as_zero && high == 0)
|
||||
goto end;
|
||||
if (!asn) {
|
||||
ret = true;
|
||||
goto end;
|
||||
}
|
||||
*asn = high;
|
||||
ret = true;
|
||||
end:
|
||||
if (next)
|
||||
*next = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool asn_str2asn(const char *asstring, as_t *asn)
|
||||
{
|
||||
return asn_str2asn_internal(asstring, asn, NULL, NULL);
|
||||
}
|
||||
|
||||
const char *asn_asn2asplain(as_t asn)
|
||||
{
|
||||
static char buf[ASN_STRING_MAX_SIZE];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", asn);
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *asn_str2asn_parse(const char *asstring, as_t *asn, bool *found_ptr)
|
||||
{
|
||||
const char *p = NULL;
|
||||
const char **next = &p;
|
||||
bool found;
|
||||
|
||||
found = asn_str2asn_internal(asstring, asn, next, NULL);
|
||||
if (found_ptr)
|
||||
*found_ptr = found;
|
||||
return *next;
|
||||
}
|
||||
|
||||
void asn_relax_as_zero(bool relax)
|
||||
{
|
||||
relax_as_zero = relax;
|
||||
}
|
||||
|
||||
enum match_type asn_str2asn_match(const char *str)
|
||||
{
|
||||
bool found, partial = false;
|
||||
|
||||
found = asn_str2asn_internal(str, NULL, NULL, &partial);
|
||||
if (found && !partial)
|
||||
return exact_match;
|
||||
|
||||
if (partial)
|
||||
return partly_match;
|
||||
|
||||
return no_match;
|
||||
}
|
48
lib/asn.h
Normal file
48
lib/asn.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* AS number structure
|
||||
* Copyright 2022 6WIND
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _FRR_ASN_H
|
||||
#define _FRR_ASN_H
|
||||
|
||||
#include "zebra.h"
|
||||
#include "command_match.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ASN_STRING_MAX_SIZE 12
|
||||
|
||||
typedef uint32_t as_t;
|
||||
|
||||
extern bool asn_str2asn(const char *asstring, as_t *asn);
|
||||
extern const char *asn_asn2asplain(as_t asn);
|
||||
extern const char *asn_str2asn_parse(const char *asstring, as_t *asn,
|
||||
bool *found_ptr);
|
||||
extern enum match_type asn_str2asn_match(const char *str);
|
||||
/* for test */
|
||||
extern void asn_relax_as_zero(bool relax);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FRR_ASN_H */
|
|
@ -71,6 +71,7 @@ const struct message tokennames[] = {
|
|||
item(IPV6_PREFIX_TKN),
|
||||
item(MAC_TKN),
|
||||
item(MAC_PREFIX_TKN),
|
||||
item(ASNUM_TKN),
|
||||
item(FORK_TKN),
|
||||
item(JOIN_TKN),
|
||||
item(START_TKN),
|
||||
|
|
|
@ -403,7 +403,8 @@ struct cmd_node {
|
|||
#define DEBUG_STR "Debugging functions\n"
|
||||
#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
|
||||
#define ROUTER_STR "Enable a routing process\n"
|
||||
#define AS_STR "AS number\n"
|
||||
#define AS_STR \
|
||||
"AS number in plain <1-4294967295> or dotted <0-65535>.<0-65535> format\n"
|
||||
#define MAC_STR "MAC address\n"
|
||||
#define MBGP_STR "MBGP information\n"
|
||||
#define MATCH_STR "Match values from routing table\n"
|
||||
|
|
|
@ -279,6 +279,7 @@ static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb)
|
|||
case END_TKN:
|
||||
case NEG_ONLY_TKN:
|
||||
case WORD_TKN:
|
||||
case ASNUM_TKN:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -548,6 +549,7 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
|
|||
case MAC_PREFIX_TKN:
|
||||
case END_TKN:
|
||||
case VARIABLE_TKN:
|
||||
case ASNUM_TKN:
|
||||
color = "#ffffff";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ enum cmd_token_type {
|
|||
IPV6_PREFIX_TKN, // IPV6 network prefixes
|
||||
MAC_TKN, // Ethernet address
|
||||
MAC_PREFIX_TKN, // Ethernet address w/ CIDR mask
|
||||
ASNUM_TKN, // AS dot format
|
||||
|
||||
/* plumbing types */
|
||||
FORK_TKN, // marks subgraph beginning
|
||||
|
|
|
@ -54,6 +54,7 @@ VARIABLE [A-Z][-_A-Z:0-9]+
|
|||
WORD (\-|\+)?[a-zA-Z0-9\*][-+_a-zA-Z0-9\*]*
|
||||
NUMBER (\-|\+)?[0-9]{1,20}
|
||||
RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
|
||||
ASNUM ASNUM
|
||||
|
||||
/* yytext shall be a pointer */
|
||||
%pointer
|
||||
|
@ -73,6 +74,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
|
|||
%}
|
||||
|
||||
[ \t]+ LOC_STEP /* ignore whitespace */;
|
||||
{ASNUM} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return ASNUM;}
|
||||
{IPV4} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4;}
|
||||
{IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4_PREFIX;}
|
||||
{IPV6} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV6;}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "command_match.h"
|
||||
#include "memory.h"
|
||||
#include "asn.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack");
|
||||
|
||||
|
@ -556,6 +557,7 @@ static enum match_type min_match_level(enum cmd_token_type type)
|
|||
case END_TKN:
|
||||
case NEG_ONLY_TKN:
|
||||
case VARIABLE_TKN:
|
||||
case ASNUM_TKN:
|
||||
return exact_match;
|
||||
}
|
||||
|
||||
|
@ -579,6 +581,7 @@ static int score_precedence(enum cmd_token_type type)
|
|||
case IPV6_PREFIX_TKN:
|
||||
case MAC_TKN:
|
||||
case MAC_PREFIX_TKN:
|
||||
case ASNUM_TKN:
|
||||
case RANGE_TKN:
|
||||
return 2;
|
||||
case WORD_TKN:
|
||||
|
@ -713,6 +716,8 @@ static enum match_type match_token(struct cmd_token *token, char *input_token)
|
|||
return match_mac(input_token, false);
|
||||
case MAC_PREFIX_TKN:
|
||||
return match_mac(input_token, true);
|
||||
case ASNUM_TKN:
|
||||
return asn_str2asn_match(input_token);
|
||||
case END_TKN:
|
||||
case FORK_TKN:
|
||||
case JOIN_TKN:
|
||||
|
@ -855,7 +860,6 @@ static enum match_type match_ipv4_prefix(const char *str)
|
|||
return exact_match;
|
||||
}
|
||||
|
||||
|
||||
#define IPV6_ADDR_STR "0123456789abcdefABCDEF:."
|
||||
#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:./"
|
||||
#define STATE_START 1
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
%token <string> RANGE
|
||||
%token <string> MAC
|
||||
%token <string> MAC_PREFIX
|
||||
%token <string> ASNUM
|
||||
|
||||
/* special syntax, value is irrelevant */
|
||||
%token <string> EXCL_BRACKET
|
||||
|
@ -293,6 +294,11 @@ placeholder_token_real:
|
|||
$$ = new_token_node (ctx, MAC_PREFIX_TKN, $1, doc_next(ctx));
|
||||
XFREE (MTYPE_LEX, $1);
|
||||
}
|
||||
| ASNUM
|
||||
{
|
||||
$$ = new_token_node (ctx, ASNUM_TKN, $1, doc_next(ctx));
|
||||
XFREE (MTYPE_LEX, $1);
|
||||
}
|
||||
|
||||
placeholder_token:
|
||||
placeholder_token_real varname_token
|
||||
|
|
|
@ -214,6 +214,7 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,
|
|||
item(IPV6_PREFIX_TKN); // IPV6 network prefixes
|
||||
item(MAC_TKN); // MAC address
|
||||
item(MAC_PREFIX_TKN); // MAC address with mask
|
||||
item(ASNUM_TKN); // ASNUM
|
||||
|
||||
/* plumbing types */
|
||||
item(FORK_TKN);
|
||||
|
|
|
@ -9,6 +9,7 @@ lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB) $(UST
|
|||
lib_libfrr_la_SOURCES = \
|
||||
lib/agg_table.c \
|
||||
lib/atomlist.c \
|
||||
lib/asn.c \
|
||||
lib/base64.c \
|
||||
lib/bfd.c \
|
||||
lib/buffer.c \
|
||||
|
@ -160,6 +161,7 @@ clippy_scan += \
|
|||
|
||||
pkginclude_HEADERS += \
|
||||
lib/agg_table.h \
|
||||
lib/asn.h \
|
||||
lib/atomlist.h \
|
||||
lib/base64.h \
|
||||
lib/bfd.h \
|
||||
|
|
|
@ -64,6 +64,12 @@ _fail = (_end == argv[_i]->arg) || (*_end != '\\0');"""
|
|||
)
|
||||
|
||||
|
||||
class AsDotHandler(RenderHandler):
|
||||
argtype = "as_t"
|
||||
decl = Template("as_t $varname = 0;")
|
||||
code = Template("_fail = !asn_str2asn(argv[_i]->arg, &$varname);")
|
||||
|
||||
|
||||
# A.B.C.D/M (prefix_ipv4) and
|
||||
# X:X::X:X/M (prefix_ipv6) are "compatible" and can merge into a
|
||||
# struct prefix:
|
||||
|
@ -165,6 +171,7 @@ handlers = {
|
|||
"IPV6_PREFIX_TKN": Prefix6Handler,
|
||||
"MAC_TKN": PrefixEthHandler,
|
||||
"MAC_PREFIX_TKN": PrefixEthHandler,
|
||||
"ASNUM_TKN": AsDotHandler,
|
||||
}
|
||||
|
||||
# core template invoked for each occurence of DEFPY.
|
||||
|
|
|
@ -924,7 +924,9 @@ static int validate(struct aspath *as, const struct test_spec *sp)
|
|||
bytes4 = aspath_put(s, as, 1);
|
||||
as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
|
||||
|
||||
asn_relax_as_zero(true);
|
||||
asstr = aspath_str2aspath(sp->shouldbe);
|
||||
asn_relax_as_zero(false);
|
||||
|
||||
asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout));
|
||||
|
||||
|
|
|
@ -1688,7 +1688,7 @@ DEFUNSH(VTYSH_ZEBRA, srv6_locator, srv6_locator_cmd,
|
|||
|
||||
#ifdef HAVE_BGPD
|
||||
DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
|
||||
"router bgp [(1-4294967295) [<view|vrf> VIEWVRFNAME]]",
|
||||
"router bgp [ASNUM [<view|vrf> VIEWVRFNAME]]",
|
||||
ROUTER_STR BGP_STR AS_STR
|
||||
"BGP view\nBGP VRF\n"
|
||||
"View/VRF name\n")
|
||||
|
|
Loading…
Reference in a new issue