Skip to content

Commit ba755d3

Browse files
authored
Merge pull request FRRouting#12248 from pguibert6WIND/bgpasdot
lib, bgp: add initial support for asdot format
2 parents 39c664c + 616e9f0 commit ba755d3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+7247
-473
lines changed

bgpd/bgp_aspath.c

+42-39
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,13 @@ static struct assegment *assegment_normalise(struct assegment *head)
287287
return head;
288288
}
289289

290-
static struct aspath *aspath_new(void)
290+
static struct aspath *aspath_new(enum asnotation_mode asnotation)
291291
{
292-
return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
292+
struct aspath *as;
293+
294+
as = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
295+
as->asnotation = asnotation;
296+
return as;
293297
}
294298

295299
/* Free AS path structure. */
@@ -537,8 +541,10 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
537541
*
538542
* This was changed to 10 after the well-known BGP assertion, which
539543
* had hit some parts of the Internet in May of 2009.
544+
* plain format : '4294967295 ' : 10 + 1
545+
* astod format : '65535.65535 ': 11 + 1
540546
*/
541-
#define ASN_STR_LEN (10 + 1)
547+
#define ASN_STR_LEN (11 + 1)
542548
str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1,
543549
ASPATH_STR_DEFAULT_LEN);
544550
str_buf = XMALLOC(MTYPE_AS_STR, str_size);
@@ -569,7 +575,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
569575

570576
/* We might need to increase str_buf, particularly if path has
571577
* differing segments types, our initial guesstimate above will
572-
* have been wrong. Need 10 chars for ASN, a separator each and
578+
* have been wrong. Need 11 chars for ASN, a separator each and
573579
* potentially two segment delimiters, plus a space between each
574580
* segment and trailing zero.
575581
*
@@ -595,12 +601,11 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
595601
/* write out the ASNs, with their separators, bar the last one*/
596602
for (i = 0; i < seg->length; i++) {
597603
if (make_json)
598-
json_object_array_add(
599-
jseg_list,
600-
json_object_new_int64(seg->as[i]));
601-
602-
len += snprintf(str_buf + len, str_size - len, "%u",
603-
seg->as[i]);
604+
asn_asn2json_array(jseg_list, seg->as[i],
605+
as->asnotation);
606+
len += snprintfrr(str_buf + len, str_size - len,
607+
ASN_FORMAT(as->asnotation),
608+
&seg->as[i]);
604609

605610
if (i < (seg->length - 1))
606611
len += snprintf(str_buf + len, str_size - len,
@@ -691,6 +696,7 @@ struct aspath *aspath_dup(struct aspath *aspath)
691696

692697
new->str = XMALLOC(MTYPE_AS_STR, buflen);
693698
new->str_len = aspath->str_len;
699+
new->asnotation = aspath->asnotation;
694700

695701
/* copy the string data */
696702
if (aspath->str_len > 0)
@@ -718,6 +724,7 @@ static void *aspath_hash_alloc(void *arg)
718724
new->str = aspath->str;
719725
new->str_len = aspath->str_len;
720726
new->json = aspath->json;
727+
new->asnotation = aspath->asnotation;
721728

722729
return new;
723730
}
@@ -825,7 +832,8 @@ static int assegments_parse(struct stream *s, size_t length,
825832
826833
On error NULL is returned.
827834
*/
828-
struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
835+
struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit,
836+
enum asnotation_mode asnotation)
829837
{
830838
struct aspath as;
831839
struct aspath *find;
@@ -840,6 +848,7 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
840848
return NULL;
841849

842850
memset(&as, 0, sizeof(as));
851+
as.asnotation = asnotation;
843852
if (assegments_parse(s, length, &as.segments, use32bit) < 0)
844853
return NULL;
845854

@@ -1057,7 +1066,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
10571066
seg = assegment_append_asns(seg, seg1->as, match);
10581067

10591068
if (!aspath) {
1060-
aspath = aspath_new();
1069+
aspath = aspath_new(as1->asnotation);
10611070
aspath->segments = seg;
10621071
} else
10631072
prevseg->next = seg;
@@ -1077,7 +1086,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
10771086
}
10781087

10791088
if (!aspath)
1080-
aspath = aspath_new();
1089+
aspath = aspath_new(as1->asnotation);
10811090

10821091
/* Make as-set using rest of all information. */
10831092
from = match;
@@ -1521,7 +1530,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
15211530
struct assegment *srcseg, *exclseg, *lastseg;
15221531
struct aspath *newpath;
15231532

1524-
newpath = aspath_new();
1533+
newpath = aspath_new(source->asnotation);
15251534
lastseg = NULL;
15261535

15271536
for (srcseg = source->segments; srcseg; srcseg = srcseg->next) {
@@ -1751,7 +1760,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
17511760
newseg = assegment_append_asns(newseg, seg->as, cpasns);
17521761

17531762
if (!newpath) {
1754-
newpath = aspath_new();
1763+
newpath = aspath_new(aspath->asnotation);
17551764
newpath->segments = newseg;
17561765
} else
17571766
prevseg->next = newseg;
@@ -1880,16 +1889,16 @@ static void aspath_segment_add(struct aspath *as, int type)
18801889
as->segments = new;
18811890
}
18821891

1883-
struct aspath *aspath_empty(void)
1892+
struct aspath *aspath_empty(enum asnotation_mode asnotation)
18841893
{
1885-
return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */
1894+
return aspath_parse(NULL, 0, 1, asnotation); /* 32Bit ;-) */
18861895
}
18871896

18881897
struct aspath *aspath_empty_get(void)
18891898
{
18901899
struct aspath *aspath;
18911900

1892-
aspath = aspath_new();
1901+
aspath = aspath_new(bgp_get_asnotation(NULL));
18931902
aspath_make_str_count(aspath, false);
18941903
return aspath;
18951904
}
@@ -1925,6 +1934,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
19251934
unsigned long *asno)
19261935
{
19271936
const char *p = buf;
1937+
as_t asval;
1938+
bool found = false;
19281939

19291940
/* Skip separators (space for sequences, ',' for sets). */
19301941
while (isspace((unsigned char)*p) || *p == ',')
@@ -1961,38 +1972,26 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
19611972
return p;
19621973
}
19631974

1964-
/* Check actual AS value. */
1965-
if (isdigit((unsigned char)*p)) {
1966-
as_t asval;
1967-
1968-
*token = as_token_asval;
1969-
asval = (*p - '0');
1970-
p++;
1971-
1972-
while (isdigit((unsigned char)*p)) {
1973-
asval *= 10;
1974-
asval += (*p - '0');
1975-
p++;
1976-
}
1975+
asval = 0;
1976+
p = asn_str2asn_parse(p, &asval, &found);
1977+
if (found) {
19771978
*asno = asval;
1978-
return p;
1979-
}
1980-
1981-
/* There is no match then return unknown token. */
1982-
*token = as_token_unknown;
1983-
p++;
1979+
*token = as_token_asval;
1980+
} else
1981+
*token = as_token_unknown;
19841982
return p;
19851983
}
19861984

1987-
struct aspath *aspath_str2aspath(const char *str)
1985+
struct aspath *aspath_str2aspath(const char *str,
1986+
enum asnotation_mode asnotation)
19881987
{
19891988
enum as_token token = as_token_unknown;
19901989
unsigned short as_type;
19911990
unsigned long asno = 0;
19921991
struct aspath *aspath;
19931992
int needtype;
19941993

1995-
aspath = aspath_new();
1994+
aspath = aspath_new(asnotation);
19961995

19971996
/* We start default type as AS_SEQUENCE. */
19981997
as_type = AS_SEQUENCE;
@@ -2066,6 +2065,10 @@ bool aspath_cmp(const void *arg1, const void *arg2)
20662065
const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;
20672066
const struct assegment *seg2 = ((const struct aspath *)arg2)->segments;
20682067

2068+
if (((const struct aspath *)arg1)->asnotation !=
2069+
((const struct aspath *)arg2)->asnotation)
2070+
return false;
2071+
20692072
while (seg1 || seg2) {
20702073
int i;
20712074
if ((!seg1 && seg2) || (seg1 && !seg2))

bgpd/bgp_aspath.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct aspath {
5757
and AS path regular expression match. */
5858
char *str;
5959
unsigned short str_len;
60+
61+
/* AS notation used by string expression of AS path */
62+
enum asnotation_mode asnotation;
6063
};
6164

6265
#define ASPATH_STR_DEFAULT_LEN 32
@@ -65,7 +68,9 @@ struct aspath {
6568
extern void aspath_init(void);
6669
extern void aspath_finish(void);
6770
extern struct aspath *aspath_parse(struct stream *s, size_t length,
68-
int use32bit);
71+
int use32bit,
72+
enum asnotation_mode asnotation);
73+
6974
extern struct aspath *aspath_dup(struct aspath *aspath);
7075
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
7176
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
@@ -81,9 +86,10 @@ extern bool aspath_cmp_left(const struct aspath *aspath1,
8186
extern bool aspath_cmp_left_confed(const struct aspath *as1,
8287
const struct aspath *as2);
8388
extern struct aspath *aspath_delete_confed_seq(struct aspath *aspath);
84-
extern struct aspath *aspath_empty(void);
89+
extern struct aspath *aspath_empty(enum asnotation_mode asnotation);
8590
extern struct aspath *aspath_empty_get(void);
86-
extern struct aspath *aspath_str2aspath(const char *str);
91+
extern struct aspath *aspath_str2aspath(const char *str,
92+
enum asnotation_mode asnotation);
8793
extern void aspath_str_update(struct aspath *as, bool make_json);
8894
extern void aspath_free(struct aspath *aspath);
8995
extern struct aspath *aspath_intern(struct aspath *aspath);

bgpd/bgp_attr.c

+16-8
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
10541054

10551055
attr->origin = origin;
10561056
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1057-
attr->aspath = aspath_empty();
1057+
attr->aspath = aspath_empty(bgp->asnotation);
10581058
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
10591059
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
10601060
attr->tag = 0;
@@ -1092,7 +1092,7 @@ struct attr *bgp_attr_aggregate_intern(
10921092
if (aspath)
10931093
attr.aspath = aspath_intern(aspath);
10941094
else
1095-
attr.aspath = aspath_empty();
1095+
attr.aspath = aspath_empty(bgp->asnotation);
10961096
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
10971097

10981098
/* Next hop attribute. */
@@ -1590,15 +1590,19 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
15901590
struct attr *const attr = args->attr;
15911591
struct peer *const peer = args->peer;
15921592
const bgp_size_t length = args->length;
1593+
enum asnotation_mode asnotation;
15931594

1595+
asnotation = bgp_get_asnotation(
1596+
args->peer && args->peer->bgp ? args->peer->bgp : NULL);
15941597
/*
15951598
* peer with AS4 => will get 4Byte ASnums
15961599
* otherwise, will get 16 Bit
15971600
*/
1598-
attr->aspath = aspath_parse(
1599-
peer->curr, length,
1600-
CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1601-
&& CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
1601+
attr->aspath =
1602+
aspath_parse(peer->curr, length,
1603+
CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
1604+
CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
1605+
asnotation);
16021606

16031607
/* In case of IBGP, length will be zero. */
16041608
if (!attr->aspath) {
@@ -1614,7 +1618,8 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
16141618
* such messages, conformant BGP speakers SHOULD use the "Treat-as-
16151619
* withdraw" error handling behavior as per [RFC7606].
16161620
*/
1617-
if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1621+
if (peer->bgp && peer->bgp->reject_as_sets &&
1622+
aspath_check_as_sets(attr->aspath)) {
16181623
flog_err(EC_BGP_ATTR_MAL_AS_PATH,
16191624
"AS_SET and AS_CONFED_SET are deprecated from %pBP",
16201625
peer);
@@ -1690,8 +1695,11 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
16901695
struct peer *const peer = args->peer;
16911696
struct attr *const attr = args->attr;
16921697
const bgp_size_t length = args->length;
1698+
enum asnotation_mode asnotation;
1699+
1700+
asnotation = bgp_get_asnotation(peer->bgp);
16931701

1694-
*as4_path = aspath_parse(peer->curr, length, 1);
1702+
*as4_path = aspath_parse(peer->curr, length, 1, asnotation);
16951703

16961704
/* In case of IBGP, length will be zero. */
16971705
if (!*as4_path) {

bgpd/bgp_btoa.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ static void attr_parse(struct stream *s, uint16_t len)
8686
case BGP_ATTR_AS_PATH: {
8787
struct aspath *aspath;
8888

89-
aspath = aspath_parse(s, length, 1);
89+
aspath = aspath_parse(s, length, 1,
90+
bgp_get_asnotation(NULL));
9091
printf("ASPATH: %s\n", aspath->str);
9192
aspath_free(aspath);
9293
} break;

bgpd/bgp_debug.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -2635,6 +2635,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
26352635
char tag_buf[30];
26362636
char overlay_index_buf[INET6_ADDRSTRLEN + 14];
26372637
const struct prefix_evpn *evp;
2638+
int len = 0;
26382639

26392640
/* ' with addpath ID ' 17
26402641
* max strlen of uint32 + 10
@@ -2688,11 +2689,15 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
26882689
}
26892690
}
26902691

2691-
if (prd)
2692-
snprintfrr(str, size, "RD %pRD %pFX%s%s%s %s %s", prd, pu.p,
2692+
if (prd) {
2693+
len += snprintfrr(str + len, size - len, "RD ");
2694+
len += snprintfrr(str + len, size - len,
2695+
BGP_RD_AS_FORMAT(bgp_get_asnotation(NULL)),
2696+
prd);
2697+
snprintfrr(str + len, size - len, " %pFX%s%s%s %s %s", pu.p,
26932698
overlay_index_buf, tag_buf, pathid_buf, afi2str(afi),
26942699
safi2str(safi));
2695-
else if (safi == SAFI_FLOWSPEC) {
2700+
} else if (safi == SAFI_FLOWSPEC) {
26962701
char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
26972702
const struct prefix_fs *fs = pu.fs;
26982703

bgpd/bgp_evpn.c

+12-4
Original file line numberDiff line numberDiff line change
@@ -5923,6 +5923,8 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
59235923
vpn->prd.prefixlen = 64;
59245924
snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, vpn->rd_id);
59255925
(void)str2prefix_rd(buf, &vpn->prd);
5926+
if (vpn->prd_pretty)
5927+
XFREE(MTYPE_BGP, vpn->prd_pretty);
59265928
UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
59275929
}
59285930

@@ -6027,6 +6029,8 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
60276029
bf_release_index(bm->rd_idspace, vpn->rd_id);
60286030
hash_release(bgp->vni_svi_hash, vpn);
60296031
hash_release(bgp->vnihash, vpn);
6032+
if (vpn->prd_pretty)
6033+
XFREE(MTYPE_BGP, vpn->prd_pretty);
60306034
QOBJ_UNREG(vpn);
60316035
XFREE(MTYPE_BGP_EVPN, vpn);
60326036
}
@@ -6238,13 +6242,14 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,
62386242

62396243
ret = bgp_get_vty(&bgp_vrf, &as, vrf_id_to_name(vrf_id),
62406244
vrf_id == VRF_DEFAULT
6241-
? BGP_INSTANCE_TYPE_DEFAULT
6242-
: BGP_INSTANCE_TYPE_VRF);
6245+
? BGP_INSTANCE_TYPE_DEFAULT
6246+
: BGP_INSTANCE_TYPE_VRF,
6247+
NULL, ASNOTATION_UNDEFINED);
62436248
switch (ret) {
62446249
case BGP_ERR_AS_MISMATCH:
62456250
flog_err(EC_BGP_EVPN_AS_MISMATCH,
6246-
"BGP instance is already running; AS is %u",
6247-
as);
6251+
"BGP instance is already running; AS is %s",
6252+
bgp_vrf->as_pretty);
62486253
return -1;
62496254
case BGP_ERR_INSTANCE_MISMATCH:
62506255
flog_err(EC_BGP_EVPN_INSTANCE_MISMATCH,
@@ -6660,6 +6665,9 @@ void bgp_evpn_cleanup(struct bgp *bgp)
66606665
list_delete(&bgp->vrf_import_rtl);
66616666
list_delete(&bgp->vrf_export_rtl);
66626667
list_delete(&bgp->l2vnis);
6668+
6669+
if (bgp->vrf_prd_pretty)
6670+
XFREE(MTYPE_BGP, bgp->vrf_prd_pretty);
66636671
}
66646672

66656673
/*

0 commit comments

Comments
 (0)