mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 13:27:53 +00:00
bgpd: aspath list format binds on as-notation format
Each BGP prefix may have an as-path list attached. A forged string is stored in the BGP attribute and shows the as-path list output. Before this commit, the as-path list output was expressed as a list of AS values in plain format. Now, if a given BGP instance uses a specific asnotation, then the output is changed: new output: router bgp 1.1 asnotation dot ! address-family ipv4 unicast network 10.200.0.0/24 route-map rmap network 10.201.0.0/24 route-map rmap redistribute connected route-map rmap exit-address-family exit ! route-map rmap permit 1 set as-path prepend 1.1 5433.55 264564564 exit ubuntu2004# do show bgp ipv4 BGP table version is 2, local router ID is 10.0.2.15, vrf id 0 Default local pref 100, local AS 1.1 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path *> 4.4.4.4/32 0.0.0.0 0 32768 1.1 5433.55 4036.61268 ? *> 10.0.2.0/24 0.0.0.0 0 32768 1.1 5433.55 4036.61268 ? 10.200.0.0/24 0.0.0.0 0 32768 1.1 5433.55 4036.61268 i 10.201.0.0/24 0.0.0.0 0 32768 1.1 5433.55 4036.61268 i The changes include: - the aspath structure has a new field: asnotation type The ashash list will differentiate 2 aspaths using a different asnotation. - 3 new printf extensions display the as number in the wished format: pASP, pASD, pASE for plain, dot, or dot+ format (extended). Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
e55b088399
commit
17571c4ae7
@ -302,9 +302,13 @@ static struct assegment *assegment_normalise(struct assegment *head)
|
|||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct aspath *aspath_new(void)
|
static struct aspath *aspath_new(enum asnotation_mode asnotation)
|
||||||
{
|
{
|
||||||
return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
|
struct aspath *as;
|
||||||
|
|
||||||
|
as = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
|
||||||
|
as->asnotation = asnotation;
|
||||||
|
return as;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free AS path structure. */
|
/* Free AS path structure. */
|
||||||
@ -552,8 +556,10 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
|
|||||||
*
|
*
|
||||||
* This was changed to 10 after the well-known BGP assertion, which
|
* This was changed to 10 after the well-known BGP assertion, which
|
||||||
* had hit some parts of the Internet in May of 2009.
|
* had hit some parts of the Internet in May of 2009.
|
||||||
|
* plain format : '4294967295 ' : 10 + 1
|
||||||
|
* astod format : '65535.65535 ': 11 + 1
|
||||||
*/
|
*/
|
||||||
#define ASN_STR_LEN (10 + 1)
|
#define ASN_STR_LEN (11 + 1)
|
||||||
str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1,
|
str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1,
|
||||||
ASPATH_STR_DEFAULT_LEN);
|
ASPATH_STR_DEFAULT_LEN);
|
||||||
str_buf = XMALLOC(MTYPE_AS_STR, str_size);
|
str_buf = XMALLOC(MTYPE_AS_STR, str_size);
|
||||||
@ -584,7 +590,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
|
|||||||
|
|
||||||
/* We might need to increase str_buf, particularly if path has
|
/* We might need to increase str_buf, particularly if path has
|
||||||
* differing segments types, our initial guesstimate above will
|
* differing segments types, our initial guesstimate above will
|
||||||
* have been wrong. Need 10 chars for ASN, a separator each and
|
* have been wrong. Need 11 chars for ASN, a separator each and
|
||||||
* potentially two segment delimiters, plus a space between each
|
* potentially two segment delimiters, plus a space between each
|
||||||
* segment and trailing zero.
|
* segment and trailing zero.
|
||||||
*
|
*
|
||||||
@ -610,12 +616,11 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
|
|||||||
/* write out the ASNs, with their separators, bar the last one*/
|
/* write out the ASNs, with their separators, bar the last one*/
|
||||||
for (i = 0; i < seg->length; i++) {
|
for (i = 0; i < seg->length; i++) {
|
||||||
if (make_json)
|
if (make_json)
|
||||||
json_object_array_add(
|
asn_asn2json_array(jseg_list, seg->as[i],
|
||||||
jseg_list,
|
as->asnotation);
|
||||||
json_object_new_int64(seg->as[i]));
|
len += snprintfrr(str_buf + len, str_size - len,
|
||||||
|
ASN_FORMAT(as->asnotation),
|
||||||
len += snprintf(str_buf + len, str_size - len, "%u",
|
&seg->as[i]);
|
||||||
seg->as[i]);
|
|
||||||
|
|
||||||
if (i < (seg->length - 1))
|
if (i < (seg->length - 1))
|
||||||
len += snprintf(str_buf + len, str_size - len,
|
len += snprintf(str_buf + len, str_size - len,
|
||||||
@ -706,6 +711,7 @@ struct aspath *aspath_dup(struct aspath *aspath)
|
|||||||
|
|
||||||
new->str = XMALLOC(MTYPE_AS_STR, buflen);
|
new->str = XMALLOC(MTYPE_AS_STR, buflen);
|
||||||
new->str_len = aspath->str_len;
|
new->str_len = aspath->str_len;
|
||||||
|
new->asnotation = aspath->asnotation;
|
||||||
|
|
||||||
/* copy the string data */
|
/* copy the string data */
|
||||||
if (aspath->str_len > 0)
|
if (aspath->str_len > 0)
|
||||||
@ -733,6 +739,7 @@ static void *aspath_hash_alloc(void *arg)
|
|||||||
new->str = aspath->str;
|
new->str = aspath->str;
|
||||||
new->str_len = aspath->str_len;
|
new->str_len = aspath->str_len;
|
||||||
new->json = aspath->json;
|
new->json = aspath->json;
|
||||||
|
new->asnotation = aspath->asnotation;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
@ -840,7 +847,8 @@ static int assegments_parse(struct stream *s, size_t length,
|
|||||||
|
|
||||||
On error NULL is returned.
|
On error NULL is returned.
|
||||||
*/
|
*/
|
||||||
struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
|
struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit,
|
||||||
|
enum asnotation_mode asnotation)
|
||||||
{
|
{
|
||||||
struct aspath as;
|
struct aspath as;
|
||||||
struct aspath *find;
|
struct aspath *find;
|
||||||
@ -855,6 +863,7 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memset(&as, 0, sizeof(as));
|
memset(&as, 0, sizeof(as));
|
||||||
|
as.asnotation = asnotation;
|
||||||
if (assegments_parse(s, length, &as.segments, use32bit) < 0)
|
if (assegments_parse(s, length, &as.segments, use32bit) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -1072,7 +1081,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
|
|||||||
seg = assegment_append_asns(seg, seg1->as, match);
|
seg = assegment_append_asns(seg, seg1->as, match);
|
||||||
|
|
||||||
if (!aspath) {
|
if (!aspath) {
|
||||||
aspath = aspath_new();
|
aspath = aspath_new(as1->asnotation);
|
||||||
aspath->segments = seg;
|
aspath->segments = seg;
|
||||||
} else
|
} else
|
||||||
prevseg->next = seg;
|
prevseg->next = seg;
|
||||||
@ -1092,7 +1101,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!aspath)
|
if (!aspath)
|
||||||
aspath = aspath_new();
|
aspath = aspath_new(as1->asnotation);
|
||||||
|
|
||||||
/* Make as-set using rest of all information. */
|
/* Make as-set using rest of all information. */
|
||||||
from = match;
|
from = match;
|
||||||
@ -1536,7 +1545,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
|
|||||||
struct assegment *srcseg, *exclseg, *lastseg;
|
struct assegment *srcseg, *exclseg, *lastseg;
|
||||||
struct aspath *newpath;
|
struct aspath *newpath;
|
||||||
|
|
||||||
newpath = aspath_new();
|
newpath = aspath_new(source->asnotation);
|
||||||
lastseg = NULL;
|
lastseg = NULL;
|
||||||
|
|
||||||
for (srcseg = source->segments; srcseg; srcseg = srcseg->next) {
|
for (srcseg = source->segments; srcseg; srcseg = srcseg->next) {
|
||||||
@ -1766,7 +1775,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
|
|||||||
newseg = assegment_append_asns(newseg, seg->as, cpasns);
|
newseg = assegment_append_asns(newseg, seg->as, cpasns);
|
||||||
|
|
||||||
if (!newpath) {
|
if (!newpath) {
|
||||||
newpath = aspath_new();
|
newpath = aspath_new(aspath->asnotation);
|
||||||
newpath->segments = newseg;
|
newpath->segments = newseg;
|
||||||
} else
|
} else
|
||||||
prevseg->next = newseg;
|
prevseg->next = newseg;
|
||||||
@ -1895,16 +1904,16 @@ static void aspath_segment_add(struct aspath *as, int type)
|
|||||||
as->segments = new;
|
as->segments = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aspath *aspath_empty(void)
|
struct aspath *aspath_empty(enum asnotation_mode asnotation)
|
||||||
{
|
{
|
||||||
return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */
|
return aspath_parse(NULL, 0, 1, asnotation); /* 32Bit ;-) */
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aspath *aspath_empty_get(void)
|
struct aspath *aspath_empty_get(void)
|
||||||
{
|
{
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
aspath = aspath_new();
|
aspath = aspath_new(bgp_get_asnotation(NULL));
|
||||||
aspath_make_str_count(aspath, false);
|
aspath_make_str_count(aspath, false);
|
||||||
return aspath;
|
return aspath;
|
||||||
}
|
}
|
||||||
@ -1988,7 +1997,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aspath *aspath_str2aspath(const char *str)
|
struct aspath *aspath_str2aspath(const char *str,
|
||||||
|
enum asnotation_mode asnotation)
|
||||||
{
|
{
|
||||||
enum as_token token = as_token_unknown;
|
enum as_token token = as_token_unknown;
|
||||||
unsigned short as_type;
|
unsigned short as_type;
|
||||||
@ -1996,7 +2006,7 @@ struct aspath *aspath_str2aspath(const char *str)
|
|||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
int needtype;
|
int needtype;
|
||||||
|
|
||||||
aspath = aspath_new();
|
aspath = aspath_new(asnotation);
|
||||||
|
|
||||||
/* We start default type as AS_SEQUENCE. */
|
/* We start default type as AS_SEQUENCE. */
|
||||||
as_type = AS_SEQUENCE;
|
as_type = AS_SEQUENCE;
|
||||||
@ -2070,6 +2080,10 @@ bool aspath_cmp(const void *arg1, const void *arg2)
|
|||||||
const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
|
const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
|
||||||
const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
|
const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
|
||||||
|
|
||||||
|
if (((const struct aspath *)arg1)->asnotation !=
|
||||||
|
((const struct aspath *)arg2)->asnotation)
|
||||||
|
return false;
|
||||||
|
|
||||||
while (seg1 || seg2) {
|
while (seg1 || seg2) {
|
||||||
int i;
|
int i;
|
||||||
if ((!seg1 && seg2) || (seg1 && !seg2))
|
if ((!seg1 && seg2) || (seg1 && !seg2))
|
||||||
|
@ -72,6 +72,9 @@ struct aspath {
|
|||||||
and AS path regular expression match. */
|
and AS path regular expression match. */
|
||||||
char *str;
|
char *str;
|
||||||
unsigned short str_len;
|
unsigned short str_len;
|
||||||
|
|
||||||
|
/* AS notation used by string expression of AS path */
|
||||||
|
enum asnotation_mode asnotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASPATH_STR_DEFAULT_LEN 32
|
#define ASPATH_STR_DEFAULT_LEN 32
|
||||||
@ -80,7 +83,9 @@ struct aspath {
|
|||||||
extern void aspath_init(void);
|
extern void aspath_init(void);
|
||||||
extern void aspath_finish(void);
|
extern void aspath_finish(void);
|
||||||
extern struct aspath *aspath_parse(struct stream *s, size_t length,
|
extern struct aspath *aspath_parse(struct stream *s, size_t length,
|
||||||
int use32bit);
|
int use32bit,
|
||||||
|
enum asnotation_mode asnotation);
|
||||||
|
|
||||||
extern struct aspath *aspath_dup(struct aspath *aspath);
|
extern struct aspath *aspath_dup(struct aspath *aspath);
|
||||||
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
|
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
|
||||||
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
|
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
|
||||||
@ -96,9 +101,10 @@ extern bool aspath_cmp_left(const struct aspath *aspath1,
|
|||||||
extern bool aspath_cmp_left_confed(const struct aspath *as1,
|
extern bool aspath_cmp_left_confed(const struct aspath *as1,
|
||||||
const struct aspath *as2);
|
const struct aspath *as2);
|
||||||
extern struct aspath *aspath_delete_confed_seq(struct aspath *aspath);
|
extern struct aspath *aspath_delete_confed_seq(struct aspath *aspath);
|
||||||
extern struct aspath *aspath_empty(void);
|
extern struct aspath *aspath_empty(enum asnotation_mode asnotation);
|
||||||
extern struct aspath *aspath_empty_get(void);
|
extern struct aspath *aspath_empty_get(void);
|
||||||
extern struct aspath *aspath_str2aspath(const char *str);
|
extern struct aspath *aspath_str2aspath(const char *str,
|
||||||
|
enum asnotation_mode asnotation);
|
||||||
extern void aspath_str_update(struct aspath *as, bool make_json);
|
extern void aspath_str_update(struct aspath *as, bool make_json);
|
||||||
extern void aspath_free(struct aspath *aspath);
|
extern void aspath_free(struct aspath *aspath);
|
||||||
extern struct aspath *aspath_intern(struct aspath *aspath);
|
extern struct aspath *aspath_intern(struct aspath *aspath);
|
||||||
|
@ -1069,7 +1069,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
|
|||||||
|
|
||||||
attr->origin = origin;
|
attr->origin = origin;
|
||||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
|
||||||
attr->aspath = aspath_empty();
|
attr->aspath = aspath_empty(bgp->asnotation);
|
||||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
|
||||||
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
|
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
|
||||||
attr->tag = 0;
|
attr->tag = 0;
|
||||||
@ -1107,7 +1107,7 @@ struct attr *bgp_attr_aggregate_intern(
|
|||||||
if (aspath)
|
if (aspath)
|
||||||
attr.aspath = aspath_intern(aspath);
|
attr.aspath = aspath_intern(aspath);
|
||||||
else
|
else
|
||||||
attr.aspath = aspath_empty();
|
attr.aspath = aspath_empty(bgp->asnotation);
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
|
||||||
|
|
||||||
/* Next hop attribute. */
|
/* Next hop attribute. */
|
||||||
@ -1605,15 +1605,19 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
|
|||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
struct peer *const peer = args->peer;
|
struct peer *const peer = args->peer;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
enum asnotation_mode asnotation;
|
||||||
|
|
||||||
|
asnotation = bgp_get_asnotation(
|
||||||
|
args->peer && args->peer->bgp ? args->peer->bgp : NULL);
|
||||||
/*
|
/*
|
||||||
* peer with AS4 => will get 4Byte ASnums
|
* peer with AS4 => will get 4Byte ASnums
|
||||||
* otherwise, will get 16 Bit
|
* otherwise, will get 16 Bit
|
||||||
*/
|
*/
|
||||||
attr->aspath = aspath_parse(
|
attr->aspath =
|
||||||
peer->curr, length,
|
aspath_parse(peer->curr, length,
|
||||||
CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
|
CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
|
||||||
&& CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
|
CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
|
||||||
|
asnotation);
|
||||||
|
|
||||||
/* In case of IBGP, length will be zero. */
|
/* In case of IBGP, length will be zero. */
|
||||||
if (!attr->aspath) {
|
if (!attr->aspath) {
|
||||||
@ -1705,8 +1709,11 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
|
|||||||
struct peer *const peer = args->peer;
|
struct peer *const peer = args->peer;
|
||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
const bgp_size_t length = args->length;
|
const bgp_size_t length = args->length;
|
||||||
|
enum asnotation_mode asnotation;
|
||||||
|
|
||||||
*as4_path = aspath_parse(peer->curr, length, 1);
|
asnotation = bgp_get_asnotation(peer->bgp);
|
||||||
|
|
||||||
|
*as4_path = aspath_parse(peer->curr, length, 1, asnotation);
|
||||||
|
|
||||||
/* In case of IBGP, length will be zero. */
|
/* In case of IBGP, length will be zero. */
|
||||||
if (!*as4_path) {
|
if (!*as4_path) {
|
||||||
|
@ -101,7 +101,8 @@ static void attr_parse(struct stream *s, uint16_t len)
|
|||||||
case BGP_ATTR_AS_PATH: {
|
case BGP_ATTR_AS_PATH: {
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
aspath = aspath_parse(s, length, 1);
|
aspath = aspath_parse(s, length, 1,
|
||||||
|
bgp_get_asnotation(NULL));
|
||||||
printf("ASPATH: %s\n", aspath->str);
|
printf("ASPATH: %s\n", aspath->str);
|
||||||
aspath_free(aspath);
|
aspath_free(aspath);
|
||||||
} break;
|
} break;
|
||||||
|
@ -7246,7 +7246,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Call route map matching and return result. */
|
/* Call route map matching and return result. */
|
||||||
attr.aspath = aspath_empty();
|
attr.aspath = aspath_empty(bgp->asnotation);
|
||||||
rmap_path.peer = bgp->peer_self;
|
rmap_path.peer = bgp->peer_self;
|
||||||
rmap_path.attr = &attr;
|
rmap_path.attr = &attr;
|
||||||
|
|
||||||
@ -7340,9 +7340,12 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
|
|||||||
struct lcommunity *lcomm)
|
struct lcommunity *lcomm)
|
||||||
{
|
{
|
||||||
static struct aspath *ae = NULL;
|
static struct aspath *ae = NULL;
|
||||||
|
enum asnotation_mode asnotation;
|
||||||
|
|
||||||
|
asnotation = bgp_get_asnotation(NULL);
|
||||||
|
|
||||||
if (!ae)
|
if (!ae)
|
||||||
ae = aspath_empty();
|
ae = aspath_empty(asnotation);
|
||||||
|
|
||||||
if (!pi)
|
if (!pi)
|
||||||
return false;
|
return false;
|
||||||
|
@ -228,7 +228,7 @@ static void *route_aspath_compile(const char *arg)
|
|||||||
{
|
{
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
aspath = aspath_str2aspath(arg);
|
aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL));
|
||||||
if (!aspath)
|
if (!aspath)
|
||||||
return NULL;
|
return NULL;
|
||||||
return aspath;
|
return aspath;
|
||||||
|
@ -163,7 +163,8 @@ void lua_decode_attr(lua_State *L, int idx, struct attr *attr)
|
|||||||
attr->nh_ifindex = lua_tointeger(L, -1);
|
attr->nh_ifindex = lua_tointeger(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_getfield(L, idx, "aspath");
|
lua_getfield(L, idx, "aspath");
|
||||||
attr->aspath = aspath_str2aspath(lua_tostring(L, -1));
|
attr->aspath = aspath_str2aspath(lua_tostring(L, -1),
|
||||||
|
bgp_get_asnotation(NULL));
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_getfield(L, idx, "localpref");
|
lua_getfield(L, idx, "localpref");
|
||||||
attr->local_pref = lua_tointeger(L, -1);
|
attr->local_pref = lua_tointeger(L, -1);
|
||||||
|
@ -2060,6 +2060,13 @@ const char *bgp_get_name_by_role(uint8_t role)
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum asnotation_mode bgp_get_asnotation(struct bgp *bgp)
|
||||||
|
{
|
||||||
|
if (!bgp)
|
||||||
|
return ASNOTATION_PLAIN;
|
||||||
|
return bgp->asnotation;
|
||||||
|
}
|
||||||
|
|
||||||
static void peer_group2peer_config_copy_af(struct peer_group *group,
|
static void peer_group2peer_config_copy_af(struct peer_group *group,
|
||||||
struct peer *peer, afi_t afi,
|
struct peer *peer, afi_t afi,
|
||||||
safi_t safi)
|
safi_t safi)
|
||||||
|
@ -2350,6 +2350,7 @@ extern void peer_tx_shutdown_message_unset(struct peer *);
|
|||||||
|
|
||||||
extern void bgp_route_map_update_timer(struct thread *thread);
|
extern void bgp_route_map_update_timer(struct thread *thread);
|
||||||
extern const char *bgp_get_name_by_role(uint8_t role);
|
extern const char *bgp_get_name_by_role(uint8_t role);
|
||||||
|
extern enum asnotation_mode bgp_get_asnotation(struct bgp *bgp);
|
||||||
|
|
||||||
extern void bgp_route_map_terminate(void);
|
extern void bgp_route_map_terminate(void);
|
||||||
|
|
||||||
|
64
lib/asn.c
64
lib/asn.c
@ -118,6 +118,15 @@ static bool asn_str2asn_internal(const char *asstring, as_t *asn,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asn_asn2asdot(as_t asn, char *asstring, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t low, high;
|
||||||
|
|
||||||
|
high = (asn >> 16) & 0xffff;
|
||||||
|
low = asn & 0xffff;
|
||||||
|
snprintf(asstring, len, "%hu.%hu", high, low);
|
||||||
|
}
|
||||||
|
|
||||||
bool asn_str2asn(const char *asstring, as_t *asn)
|
bool asn_str2asn(const char *asstring, as_t *asn)
|
||||||
{
|
{
|
||||||
return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL);
|
return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL);
|
||||||
@ -173,3 +182,58 @@ const char *asn_mode2str(enum asnotation_mode asnotation)
|
|||||||
return lookup_msg(asnotation_mode_msg, asnotation,
|
return lookup_msg(asnotation_mode_msg, asnotation,
|
||||||
"Unrecognized AS notation mode");
|
"Unrecognized AS notation mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void asn_asn2json_array(json_object *jseg_list, as_t asn,
|
||||||
|
enum asnotation_mode asnotation)
|
||||||
|
{
|
||||||
|
static char as_str[ASN_STRING_MAX_SIZE];
|
||||||
|
|
||||||
|
if ((asnotation == ASNOTATION_PLAIN) ||
|
||||||
|
((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
|
||||||
|
json_object_array_add(jseg_list,
|
||||||
|
json_object_new_int64(asn));
|
||||||
|
else {
|
||||||
|
asn_asn2asdot(asn, as_str, sizeof(as_str));
|
||||||
|
json_array_string_add(jseg_list, as_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t printfrr_asnotation(struct fbuf *buf, struct printfrr_eargs *ea,
|
||||||
|
const void *ptr,
|
||||||
|
enum asnotation_mode asnotation)
|
||||||
|
{
|
||||||
|
/* for alignemnt up to 33 chars - %33pASD for instance - */
|
||||||
|
char as_str[ASN_STRING_MAX_SIZE*3];
|
||||||
|
const as_t *asn;
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
return bputs(buf, "(null)");
|
||||||
|
asn = ptr;
|
||||||
|
if ((asnotation == ASNOTATION_PLAIN) ||
|
||||||
|
((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX))
|
||||||
|
snprintf(as_str, sizeof(as_str), "%u", *asn);
|
||||||
|
else
|
||||||
|
asn_asn2asdot(*asn, as_str, sizeof(as_str));
|
||||||
|
return bputs(buf, as_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
printfrr_ext_autoreg_p("ASP", printfrr_asplain);
|
||||||
|
static ssize_t printfrr_asplain(struct fbuf *buf, struct printfrr_eargs *ea,
|
||||||
|
const void *ptr)
|
||||||
|
{
|
||||||
|
return printfrr_asnotation(buf, ea, ptr, ASNOTATION_PLAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
printfrr_ext_autoreg_p("ASD", printfrr_asdot);
|
||||||
|
static ssize_t printfrr_asdot(struct fbuf *buf, struct printfrr_eargs *ea,
|
||||||
|
const void *ptr)
|
||||||
|
{
|
||||||
|
return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
printfrr_ext_autoreg_p("ASE", printfrr_asdotplus);
|
||||||
|
static ssize_t printfrr_asdotplus(struct fbuf *buf, struct printfrr_eargs *ea,
|
||||||
|
const void *ptr)
|
||||||
|
{
|
||||||
|
return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS);
|
||||||
|
}
|
||||||
|
15
lib/asn.h
15
lib/asn.h
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "zebra.h"
|
#include "zebra.h"
|
||||||
#include "command_match.h"
|
#include "command_match.h"
|
||||||
|
#include "json.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -48,6 +49,20 @@ extern enum match_type asn_str2asn_match(const char *str);
|
|||||||
extern bool asn_str2asn_notation(const char *asstring, as_t *asn,
|
extern bool asn_str2asn_notation(const char *asstring, as_t *asn,
|
||||||
enum asnotation_mode *asnotation);
|
enum asnotation_mode *asnotation);
|
||||||
extern const char *asn_mode2str(enum asnotation_mode asnotation);
|
extern const char *asn_mode2str(enum asnotation_mode asnotation);
|
||||||
|
void asn_asn2json_array(json_object *jseg_list, as_t asn,
|
||||||
|
enum asnotation_mode asnotation);
|
||||||
|
/* display AS in appropriate format */
|
||||||
|
#ifdef _FRR_ATTRIBUTE_PRINTFRR
|
||||||
|
#pragma FRR printfrr_ext "%pASP" (as_t *)
|
||||||
|
#pragma FRR printfrr_ext "%pASD" (as_t *)
|
||||||
|
#pragma FRR printfrr_ext "%pASE" (as_t *)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ASN_FORMAT(mode) \
|
||||||
|
((mode == ASNOTATION_DOT) ? "%pASD" : \
|
||||||
|
((mode == ASNOTATION_DOTPLUS) ? "%pASE" : \
|
||||||
|
"%pASP"))
|
||||||
|
|
||||||
/* for test */
|
/* for test */
|
||||||
extern void asn_relax_as_zero(bool relax);
|
extern void asn_relax_as_zero(bool relax);
|
||||||
|
|
||||||
|
@ -880,7 +880,7 @@ static struct aspath *make_aspath(const uint8_t *data, size_t len, int use32bit)
|
|||||||
s = stream_new(len);
|
s = stream_new(len);
|
||||||
stream_put(s, data, len);
|
stream_put(s, data, len);
|
||||||
}
|
}
|
||||||
as = aspath_parse(s, len, use32bit);
|
as = aspath_parse(s, len, use32bit, ASNOTATION_PLAIN);
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
@ -925,7 +925,7 @@ static int validate(struct aspath *as, const struct test_spec *sp)
|
|||||||
as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
|
as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
|
||||||
|
|
||||||
asn_relax_as_zero(true);
|
asn_relax_as_zero(true);
|
||||||
asstr = aspath_str2aspath(sp->shouldbe);
|
asstr = aspath_str2aspath(sp->shouldbe, ASNOTATION_PLAIN);
|
||||||
asn_relax_as_zero(false);
|
asn_relax_as_zero(false);
|
||||||
|
|
||||||
asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout));
|
asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout));
|
||||||
@ -1103,7 +1103,7 @@ static void empty_prepend_test(struct test_segment *t)
|
|||||||
printf("empty prepend %s: %s\n", t->name, t->desc);
|
printf("empty prepend %s: %s\n", t->name, t->desc);
|
||||||
|
|
||||||
asp1 = make_aspath(t->asdata, t->len, 0);
|
asp1 = make_aspath(t->asdata, t->len, 0);
|
||||||
asp2 = aspath_empty();
|
asp2 = aspath_empty(ASNOTATION_PLAIN);
|
||||||
|
|
||||||
ascratch = aspath_dup(asp2);
|
ascratch = aspath_dup(asp2);
|
||||||
aspath_unintern(&asp2);
|
aspath_unintern(&asp2);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "lib/memory.h"
|
#include "lib/memory.h"
|
||||||
#include "lib/prefix.h"
|
#include "lib/prefix.h"
|
||||||
#include "lib/nexthop.h"
|
#include "lib/nexthop.h"
|
||||||
|
#include "lib/asn.h"
|
||||||
|
|
||||||
static int errors;
|
static int errors;
|
||||||
|
|
||||||
@ -158,6 +159,7 @@ int main(int argc, char **argv)
|
|||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
char *p;
|
char *p;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
as_t asn;
|
||||||
|
|
||||||
printcmp("%d %u %d %u", 123, 123, -456, -456);
|
printcmp("%d %u %d %u", 123, 123, -456, -456);
|
||||||
printcmp("%lld %llu %lld %llu", 123LL, 123LL, -456LL, -456LL);
|
printcmp("%lld %llu %lld %llu", 123LL, 123LL, -456LL, -456LL);
|
||||||
@ -405,6 +407,13 @@ int main(int argc, char **argv)
|
|||||||
printchk("-00:09", "%pTSIm", &ts);
|
printchk("-00:09", "%pTSIm", &ts);
|
||||||
printchk("--:--", "%pTVImx", &tv);
|
printchk("--:--", "%pTVImx", &tv);
|
||||||
printchk("--:--", "%pTTImx", &tt);
|
printchk("--:--", "%pTTImx", &tt);
|
||||||
|
/* ASN checks */
|
||||||
|
asn = 65536;
|
||||||
|
printchk("1.0", "%pASD", &asn);
|
||||||
|
asn = 65400;
|
||||||
|
printchk("65400", "%pASP", &asn);
|
||||||
|
printchk("0.65400", "%pASE", &asn);
|
||||||
|
printchk("65400", "%pASD", &asn);
|
||||||
|
|
||||||
return !!errors;
|
return !!errors;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user