summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c54
-rw-r--r--bgpd/bgp_aspath.h12
-rw-r--r--bgpd/bgp_attr.c21
-rw-r--r--bgpd/bgp_btoa.c3
-rw-r--r--bgpd/bgp_route.c7
-rw-r--r--bgpd/bgp_routemap.c2
-rw-r--r--bgpd/bgp_script.c3
-rw-r--r--bgpd/bgpd.c7
-rw-r--r--bgpd/bgpd.h1
-rw-r--r--lib/asn.c64
-rw-r--r--lib/asn.h15
-rw-r--r--tests/bgpd/test_aspath.c6
-rw-r--r--tests/lib/test_printfrr.c9
13 files changed, 166 insertions, 38 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 9f74aa76d..fdfe494e9 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -302,9 +302,13 @@ static struct assegment *assegment_normalise(struct assegment *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. */
@@ -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
* 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,
ASPATH_STR_DEFAULT_LEN);
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
* 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
* 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*/
for (i = 0; i < seg->length; i++) {
if (make_json)
- json_object_array_add(
- jseg_list,
- json_object_new_int64(seg->as[i]));
-
- len += snprintf(str_buf + len, str_size - len, "%u",
- seg->as[i]);
+ asn_asn2json_array(jseg_list, seg->as[i],
+ as->asnotation);
+ len += snprintfrr(str_buf + len, str_size - len,
+ ASN_FORMAT(as->asnotation),
+ &seg->as[i]);
if (i < (seg->length - 1))
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_len = aspath->str_len;
+ new->asnotation = aspath->asnotation;
/* copy the string data */
if (aspath->str_len > 0)
@@ -733,6 +739,7 @@ static void *aspath_hash_alloc(void *arg)
new->str = aspath->str;
new->str_len = aspath->str_len;
new->json = aspath->json;
+ new->asnotation = aspath->asnotation;
return new;
}
@@ -840,7 +847,8 @@ static int assegments_parse(struct stream *s, size_t length,
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 *find;
@@ -855,6 +863,7 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)
return NULL;
memset(&as, 0, sizeof(as));
+ as.asnotation = asnotation;
if (assegments_parse(s, length, &as.segments, use32bit) < 0)
return NULL;
@@ -1072,7 +1081,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
seg = assegment_append_asns(seg, seg1->as, match);
if (!aspath) {
- aspath = aspath_new();
+ aspath = aspath_new(as1->asnotation);
aspath->segments = seg;
} else
prevseg->next = seg;
@@ -1092,7 +1101,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
}
if (!aspath)
- aspath = aspath_new();
+ aspath = aspath_new(as1->asnotation);
/* Make as-set using rest of all information. */
from = match;
@@ -1536,7 +1545,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
struct assegment *srcseg, *exclseg, *lastseg;
struct aspath *newpath;
- newpath = aspath_new();
+ newpath = aspath_new(source->asnotation);
lastseg = NULL;
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);
if (!newpath) {
- newpath = aspath_new();
+ newpath = aspath_new(aspath->asnotation);
newpath->segments = newseg;
} else
prevseg->next = newseg;
@@ -1895,16 +1904,16 @@ static void aspath_segment_add(struct aspath *as, int type)
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;
- aspath = aspath_new();
+ aspath = aspath_new(bgp_get_asnotation(NULL));
aspath_make_str_count(aspath, false);
return aspath;
}
@@ -1988,7 +1997,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,
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;
unsigned short as_type;
@@ -1996,7 +2006,7 @@ struct aspath *aspath_str2aspath(const char *str)
struct aspath *aspath;
int needtype;
- aspath = aspath_new();
+ aspath = aspath_new(asnotation);
/* We start default type as 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 *seg2 = ((const struct aspath *)arg2)->segments;
+ if (((const struct aspath *)arg1)->asnotation !=
+ ((const struct aspath *)arg2)->asnotation)
+ return false;
+
while (seg1 || seg2) {
int i;
if ((!seg1 && seg2) || (seg1 && !seg2))
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index a814d73dd..e0cadef5e 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -72,6 +72,9 @@ struct aspath {
and AS path regular expression match. */
char *str;
unsigned short str_len;
+
+ /* AS notation used by string expression of AS path */
+ enum asnotation_mode asnotation;
};
#define ASPATH_STR_DEFAULT_LEN 32
@@ -80,7 +83,9 @@ struct aspath {
extern void aspath_init(void);
extern void aspath_finish(void);
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_aggregate(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,
const struct aspath *as2);
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_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_free(struct aspath *aspath);
extern struct aspath *aspath_intern(struct aspath *aspath);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 392b55880..eb1b208d9 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1069,7 +1069,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
attr->origin = 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->weight = BGP_ATTR_DEFAULT_WEIGHT;
attr->tag = 0;
@@ -1107,7 +1107,7 @@ struct attr *bgp_attr_aggregate_intern(
if (aspath)
attr.aspath = aspath_intern(aspath);
else
- attr.aspath = aspath_empty();
+ attr.aspath = aspath_empty(bgp->asnotation);
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
/* 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 peer *const peer = args->peer;
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
* otherwise, will get 16 Bit
*/
- attr->aspath = aspath_parse(
- peer->curr, length,
- CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
- && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV));
+ attr->aspath =
+ aspath_parse(peer->curr, length,
+ CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
+ CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
+ asnotation);
/* In case of IBGP, length will be zero. */
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 attr *const attr = args->attr;
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. */
if (!*as4_path) {
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index aa14d99f1..af944593b 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -101,7 +101,8 @@ static void attr_parse(struct stream *s, uint16_t len)
case BGP_ATTR_AS_PATH: {
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);
aspath_free(aspath);
} break;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 23e6195d3..32de9e302 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -7246,7 +7246,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp,
return false;
/* 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.attr = &attr;
@@ -7340,9 +7340,12 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
struct lcommunity *lcomm)
{
static struct aspath *ae = NULL;
+ enum asnotation_mode asnotation;
+
+ asnotation = bgp_get_asnotation(NULL);
if (!ae)
- ae = aspath_empty();
+ ae = aspath_empty(asnotation);
if (!pi)
return false;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index c9da71c6d..87e532efb 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -228,7 +228,7 @@ static void *route_aspath_compile(const char *arg)
{
struct aspath *aspath;
- aspath = aspath_str2aspath(arg);
+ aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL));
if (!aspath)
return NULL;
return aspath;
diff --git a/bgpd/bgp_script.c b/bgpd/bgp_script.c
index bf3e612bf..a6004fc72 100644
--- a/bgpd/bgp_script.c
+++ b/bgpd/bgp_script.c
@@ -163,7 +163,8 @@ void lua_decode_attr(lua_State *L, int idx, struct attr *attr)
attr->nh_ifindex = lua_tointeger(L, -1);
lua_pop(L, 1);
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_getfield(L, idx, "localpref");
attr->local_pref = lua_tointeger(L, -1);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 565cbccee..6b8c17da8 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2060,6 +2060,13 @@ const char *bgp_get_name_by_role(uint8_t role)
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,
struct peer *peer, afi_t afi,
safi_t safi)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 634c4cf1d..aa53e7c30 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -2350,6 +2350,7 @@ extern void peer_tx_shutdown_message_unset(struct peer *);
extern void bgp_route_map_update_timer(struct thread *thread);
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);
diff --git a/lib/asn.c b/lib/asn.c
index 502854ec9..4c37cca1f 100644
--- a/lib/asn.c
+++ b/lib/asn.c
@@ -118,6 +118,15 @@ static bool asn_str2asn_internal(const char *asstring, as_t *asn,
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)
{
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,
"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);
+}
diff --git a/lib/asn.h b/lib/asn.h
index 2884aafd5..902516ef7 100644
--- a/lib/asn.h
+++ b/lib/asn.h
@@ -24,6 +24,7 @@
#include "zebra.h"
#include "command_match.h"
+#include "json.h"
#ifdef __cplusplus
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,
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 */
extern void asn_relax_as_zero(bool relax);
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index 0f6d5b023..8c173ea66 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -880,7 +880,7 @@ static struct aspath *make_aspath(const uint8_t *data, size_t len, int use32bit)
s = stream_new(len);
stream_put(s, data, len);
}
- as = aspath_parse(s, len, use32bit);
+ as = aspath_parse(s, len, use32bit, ASNOTATION_PLAIN);
if (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);
asn_relax_as_zero(true);
- asstr = aspath_str2aspath(sp->shouldbe);
+ asstr = aspath_str2aspath(sp->shouldbe, ASNOTATION_PLAIN);
asn_relax_as_zero(false);
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);
asp1 = make_aspath(t->asdata, t->len, 0);
- asp2 = aspath_empty();
+ asp2 = aspath_empty(ASNOTATION_PLAIN);
ascratch = aspath_dup(asp2);
aspath_unintern(&asp2);
diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c
index 59d08ae82..f9755512a 100644
--- a/tests/lib/test_printfrr.c
+++ b/tests/lib/test_printfrr.c
@@ -25,6 +25,7 @@
#include "lib/memory.h"
#include "lib/prefix.h"
#include "lib/nexthop.h"
+#include "lib/asn.h"
static int errors;
@@ -158,6 +159,7 @@ int main(int argc, char **argv)
struct in_addr ip;
char *p;
char buf[256];
+ as_t asn;
printcmp("%d %u %d %u", 123, 123, -456, -456);
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("--:--", "%pTVImx", &tv);
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;
}