This commit is contained in:
Philippe Guibert 2025-04-29 16:20:41 +00:00 committed by GitHub
commit 7cedd9b975
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 470 additions and 230 deletions

View file

@ -617,7 +617,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
for (i = 0; i < seg->length; i++) {
if (make_json)
asn_asn2json_array(jseg_list, seg->as[i],
as->asnotation);
as->asnotation, NULL, false);
len += snprintfrr(str_buf + len, str_size - len,
ASN_FORMAT(as->asnotation),
&seg->as[i]);
@ -673,6 +673,67 @@ void aspath_str_update(struct aspath *as, bool make_json)
aspath_make_str_count(as, make_json);
}
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
static int aspath_json_string(struct json_object *jso, struct printbuf *pb,
int level, int flags)
{
struct aspath *as;
struct assegment *seg;
int count_seg = 0, i;
char num_str[12];
const char *seg_type;
as = json_object_get_userdata(jso);
assert(as);
seg = as->segments;
if (seg == NULL)
printbuf_strappend(pb, "{\"string\":\"Local\",\"segments\":[");
else {
printbuf_strappend(pb, "{\"string\":\"");
printbuf_memappend(pb, as->str, strlen(as->str));
printbuf_strappend(pb, "\",\"segments\":[");
}
while (seg) {
if (count_seg)
printbuf_strappend(pb, ",");
printbuf_strappend(pb, "{\"type\":\"");
seg_type = aspath_segment_type_str[seg->type];
printbuf_memappend(pb, seg_type, strlen(seg_type));
printbuf_strappend(pb, "\",\"list\":[");
for (i = 0; i < seg->length; i++) {
asn_asn2json_array(NULL, seg->as[i], as->asnotation, pb,
true);
if (i < (seg->length - 1))
printbuf_strappend(pb, ",");
}
printbuf_strappend(pb, "]}");
seg = seg->next;
count_seg++;
}
printbuf_strappend(pb, "],\"length\":");
snprintf(num_str, sizeof(num_str), "%d}", aspath_count_hops(as));
return printbuf_memappend(pb, num_str, strlen(num_str));
}
#endif
json_object *aspath_get_json(struct aspath *aspath)
{
json_object *json_aspath = NULL;
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
json_aspath = json_object_new_object();
json_object_set_serializer(json_aspath, aspath_json_string, aspath,
NULL);
#else
if (!aspath->json)
aspath_str_update(aspath, true);
json_aspath = json_object_lock(aspath->json);
#endif
return json_aspath;
}
/* Intern allocated AS path. */
struct aspath *aspath_intern(struct aspath *aspath)
{

View file

@ -113,6 +113,7 @@ extern struct aspath *aspath_str2aspath(const char *str,
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);
extern json_object *aspath_get_json(struct aspath *aspath);
extern void aspath_unintern(struct aspath **aspath);
extern const char *aspath_print(struct aspath *aspath);
extern void aspath_print_vty(struct vty *vty, struct aspath *aspath);

View file

@ -164,6 +164,232 @@ struct community *community_uniq_sort(struct community *com)
return new;
}
/* Convert communities attribute to string and optionally add json objects
* into the pased json_community_list string
*/
static void community_json_list(struct community *com,
json_object *json_community_list, char *str,
int len, bool translate_alias,
struct printbuf *pb)
{
int i;
int first;
uint32_t comval;
json_object *json_string = NULL;
uint16_t as;
uint16_t val;
char buf[32];
const char *com2alias;
first = 1;
/* Fill in string. */
for (i = 0; i < com->size; i++) {
memcpy(&comval, com_nthval(com, i), sizeof(uint32_t));
comval = ntohl(comval);
if (first)
first = 0;
else
strlcat(str, " ", len);
switch (comval) {
case COMMUNITY_GSHUT:
if (str)
strlcat(str, "graceful-shutdown", len);
if (pb)
sprintbuf(pb, "%s\"gracefulShutdown\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"gracefulShutdown");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ACCEPT_OWN:
if (str)
strlcat(str, "accept-own", len);
if (pb)
sprintbuf(pb, "%s\"acceptOwn\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"acceptown");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_TRANSLATED_v4:
if (str)
strlcat(str, "route-filter-translated-v4", len);
if (pb)
sprintbuf(pb, "%s\"routeFilterTranslateV4\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"routeFilterTranslatedV4");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_v4:
if (str)
strlcat(str, "route-filter-v4", len);
if (pb)
sprintbuf(pb, "%s\"routeFilterV4\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"routeFilterV4");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_TRANSLATED_v6:
if (str)
strlcat(str, "route-filter-translated-v6", len);
if (pb)
sprintbuf(pb, "%s\"routeFilterTranslatedV6\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"routeFilterTranslatedV6");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_v6:
if (str)
strlcat(str, "route-filter-v6", len);
if (pb)
sprintbuf(pb, "%s\"routeFilterV6\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"routeFilterV6");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_LLGR_STALE:
if (str)
strlcat(str, "llgr-stale", len);
if (pb)
sprintbuf(pb, "%s\"llgrStale\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"llgrStale");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_LLGR:
if (str)
strlcat(str, "no-llgr", len);
if (pb)
sprintbuf(pb, "%s\"noLlgr\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"noLlgr");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ACCEPT_OWN_NEXTHOP:
if (str)
strlcat(str, "accept-own-nexthop", len);
if (pb)
sprintbuf(pb, "%s\"acceptownnexthop\"",
i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"acceptownnexthop");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_BLACKHOLE:
if (str)
strlcat(str, "blackhole", len);
if (pb)
sprintbuf(pb, "%s\"blackhole\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string(
"blackhole");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_EXPORT:
if (str)
strlcat(str, "no-export", len);
if (pb)
sprintbuf(pb, "%s\"noExport\"", i ? "," : "");
else if (json_community_list) {
json_string =
json_object_new_string("noExport");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_ADVERTISE:
if (str)
strlcat(str, "no-advertise", len);
if (pb)
sprintbuf(pb, "%s\"noAdvertise\"", i ? "," : "");
else if (json_community_list) {
json_string =
json_object_new_string("noAdvertise");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_LOCAL_AS:
if (str)
strlcat(str, "local-AS", len);
if (pb)
sprintbuf(pb, "%s\"localAs\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string("localAs");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_PEER:
if (str)
strlcat(str, "no-peer", len);
if (pb)
sprintbuf(pb, "%s\"noPeer\"", i ? "," : "");
else if (json_community_list) {
json_string = json_object_new_string("noPeer");
json_object_array_add(json_community_list,
json_string);
}
break;
default:
as = CHECK_FLAG((comval >> 16), 0xFFFF);
val = CHECK_FLAG(comval, 0xFFFF);
snprintf(buf, sizeof(buf), "%u:%d", as, val);
com2alias = translate_alias ? bgp_community2alias(buf)
: buf;
if (str)
strlcat(str, com2alias, len);
if (pb)
sprintbuf(pb, "%s\"%s\"", i ? "," : "",
translate_alias
? bgp_community2alias(buf)
: buf);
else if (json_community_list) {
json_string = json_object_new_string(com2alias);
json_object_array_add(json_community_list,
json_string);
}
break;
}
}
}
/* Convert communities attribute to string.
For Well-known communities value, below keyword is used.
@ -190,12 +416,8 @@ static void set_community_string(struct community *com, bool make_json,
int i;
char *str;
int len;
int first;
uint32_t comval;
uint16_t as;
uint16_t val;
json_object *json_community_list = NULL;
json_object *json_string = NULL;
if (!com)
return;
@ -278,160 +500,9 @@ static void set_community_string(struct community *com, bool make_json,
/* Allocate memory. */
str = XCALLOC(MTYPE_COMMUNITY_STR, len);
first = 1;
/* Fill in string. */
for (i = 0; i < com->size; i++) {
memcpy(&comval, com_nthval(com, i), sizeof(uint32_t));
comval = ntohl(comval);
if (first)
first = 0;
else
strlcat(str, " ", len);
switch (comval) {
case COMMUNITY_GSHUT:
strlcat(str, "graceful-shutdown", len);
if (make_json) {
json_string = json_object_new_string(
"gracefulShutdown");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ACCEPT_OWN:
strlcat(str, "accept-own", len);
if (make_json) {
json_string = json_object_new_string(
"acceptown");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_TRANSLATED_v4:
strlcat(str, "route-filter-translated-v4", len);
if (make_json) {
json_string = json_object_new_string(
"routeFilterTranslatedV4");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_v4:
strlcat(str, "route-filter-v4", len);
if (make_json) {
json_string = json_object_new_string(
"routeFilterV4");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_TRANSLATED_v6:
strlcat(str, "route-filter-translated-v6", len);
if (make_json) {
json_string = json_object_new_string(
"routeFilterTranslatedV6");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ROUTE_FILTER_v6:
strlcat(str, "route-filter-v6", len);
if (make_json) {
json_string = json_object_new_string(
"routeFilterV6");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_LLGR_STALE:
strlcat(str, "llgr-stale", len);
if (make_json) {
json_string = json_object_new_string(
"llgrStale");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_LLGR:
strlcat(str, "no-llgr", len);
if (make_json) {
json_string = json_object_new_string(
"noLlgr");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_ACCEPT_OWN_NEXTHOP:
strlcat(str, "accept-own-nexthop", len);
if (make_json) {
json_string = json_object_new_string(
"acceptownnexthop");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_BLACKHOLE:
strlcat(str, "blackhole", len);
if (make_json) {
json_string = json_object_new_string(
"blackhole");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_EXPORT:
strlcat(str, "no-export", len);
if (make_json) {
json_string =
json_object_new_string("noExport");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_ADVERTISE:
strlcat(str, "no-advertise", len);
if (make_json) {
json_string =
json_object_new_string("noAdvertise");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_LOCAL_AS:
strlcat(str, "local-AS", len);
if (make_json) {
json_string = json_object_new_string("localAs");
json_object_array_add(json_community_list,
json_string);
}
break;
case COMMUNITY_NO_PEER:
strlcat(str, "no-peer", len);
if (make_json) {
json_string = json_object_new_string("noPeer");
json_object_array_add(json_community_list,
json_string);
}
break;
default:
as = CHECK_FLAG((comval >> 16), 0xFFFF);
val = CHECK_FLAG(comval, 0xFFFF);
char buf[32];
snprintf(buf, sizeof(buf), "%u:%d", as, val);
const char *com2alias =
translate_alias ? bgp_community2alias(buf) : buf;
strlcat(str, com2alias, len);
if (make_json) {
json_string = json_object_new_string(com2alias);
json_object_array_add(json_community_list,
json_string);
}
break;
}
}
community_json_list(com, make_json ? json_community_list : NULL, str,
len, translate_alias, NULL);
if (make_json) {
json_object_string_add(com->json, "string", str);
@ -919,6 +990,27 @@ static void bgp_aggr_community_prepare(struct hash_bucket *hb, void *arg)
*aggr_community = community_dup(hb_community);
}
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
static int community_list_json_to_string(struct json_object *jso,
struct printbuf *pb, int level,
int flags)
{
struct community *com;
com = json_object_get_userdata(jso);
assert(com);
if (!com->str)
return 0;
printbuf_strappend(pb, "{\"string\":\"");
printbuf_memappend(pb, com->str, strlen(com->str));
printbuf_strappend(pb, "\",\"list\":[");
community_json_list(com, NULL, NULL, 0, true, pb);
printbuf_strappend(pb, "]}");
return 0;
}
#endif
void bgp_aggr_community_remove(void *arg)
{
struct community *community = arg;
@ -1040,3 +1132,19 @@ void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
}
}
}
json_object *community_get_json(struct community *com)
{
json_object *json_community_list = NULL;
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
json_community_list = json_object_new_object();
json_object_set_serializer(json_community_list,
community_list_json_to_string, com, NULL);
#else
if (!com->json)
community_str(com, true, true);
json_community_list = json_object_lock(com->json);
#endif
return json_community_list;
}

View file

@ -60,6 +60,7 @@ extern void community_free(struct community **comm);
extern struct community *community_uniq_sort(struct community *com);
extern struct community *community_parse(uint32_t *pnt, unsigned short length);
extern struct community *community_intern(struct community *com);
extern json_object *community_get_json(struct community *com);
extern void community_unintern(struct community **com);
extern char *community_str(struct community *com, bool make_json,
bool translate_alias);

View file

@ -161,48 +161,33 @@ struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
return lcom1;
}
static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
bool translate_alias)
{
int i;
int len;
char *str_buf;
const uint8_t *pnt;
uint32_t global, local1, local2;
json_object *json_lcommunity_list = NULL;
json_object *json_string = NULL;
/* 3 32-bit integers, 2 colons, and a space */
#define LCOMMUNITY_STRLEN (10 * 3 + 2 + 1)
if (!lcom)
return;
if (make_json) {
lcom->json = json_object_new_object();
json_lcommunity_list = json_object_new_array();
}
if (lcom->size == 0) {
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, 1);
if (make_json) {
json_object_string_add(lcom->json, "string", "");
json_object_object_add(lcom->json, "list",
json_lcommunity_list);
}
lcom->str = str_buf;
return;
}
/* Convert large communities attribute to string and optionally add json objects
* into the pased json_community_list string
*/
static char *lcommunity_json_list(struct lcommunity *lcom,
json_object *json_lcommunity_list,
bool translate_alias, bool return_buffer,
struct printbuf *pb)
{
int i, len;
const uint8_t *pnt;
uint32_t global, local1, local2;
char *str_buf = NULL;
size_t str_buf_sz = 0;
json_object *json_string = NULL;
/* 1 space + lcom->size lcom strings + null terminator */
size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
if (return_buffer) {
str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
}
len = 0;
for (i = 0; i < lcom->size; i++) {
if (i > 0)
if (return_buffer && i > 0)
len = strlcat(str_buf, " ", str_buf_sz);
pnt = lcom->val + (i * LCOMMUNITY_SIZE);
@ -225,20 +210,56 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
const char *com2alias =
translate_alias ? bgp_community2alias(lcsb) : lcsb;
size_t individual_len = strlen(com2alias);
if (str_buf) {
if (individual_len + len > str_buf_sz) {
str_buf_sz = individual_len + len + 1;
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
str_buf_sz);
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR,
str_buf, str_buf_sz);
}
len = strlcat(str_buf, com2alias, str_buf_sz);
}
len = strlcat(str_buf, com2alias, str_buf_sz);
if (make_json) {
if (pb)
sprintbuf(pb, "%s\"%s\"", i ? "," : "", com2alias);
else if (json_lcommunity_list) {
json_string = json_object_new_string(com2alias);
json_object_array_add(json_lcommunity_list,
json_string);
}
}
return str_buf;
}
static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
bool translate_alias)
{
char *str_buf;
json_object *json_lcommunity_list = NULL;
if (!lcom)
return;
if (make_json) {
lcom->json = json_object_new_object();
json_lcommunity_list = json_object_new_array();
}
if (lcom->size == 0) {
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, 1);
if (make_json) {
json_object_string_add(lcom->json, "string", "");
json_object_object_add(lcom->json, "list",
json_lcommunity_list);
}
lcom->str = str_buf;
return;
}
str_buf = lcommunity_json_list(lcom,
make_json ? json_lcommunity_list : NULL,
translate_alias, true, NULL);
if (make_json) {
json_object_string_add(lcom->json, "string", str_buf);
@ -552,6 +573,26 @@ static void bgp_aggr_lcommunity_prepare(struct hash_bucket *hb, void *arg)
*aggr_lcommunity = lcommunity_dup(hb_lcommunity);
}
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
static int lcommunity_json_to_string(struct json_object *jso,
struct printbuf *pb, int level, int flags)
{
struct lcommunity *lcom;
lcom = json_object_get_userdata(jso);
assert(lcom);
if (!lcom->str)
return 0;
printbuf_strappend(pb, "{\"string\":\"");
printbuf_memappend(pb, lcom->str, strlen(lcom->str));
printbuf_strappend(pb, "\",\"list\":[");
lcommunity_json_list(lcom, NULL, 0, false, pb);
printbuf_strappend(pb, "]}");
return 0;
}
#endif
void bgp_aggr_lcommunity_remove(void *arg)
{
struct lcommunity *lcommunity = arg;
@ -672,3 +713,19 @@ void bgp_remove_lcomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
}
}
}
json_object *lcommunity_get_json(struct lcommunity *lcom)
{
json_object *json_lcommunity = NULL;
#if JSON_C_MINOR_VERSION >= 13 && JSON_C_MAJOR_VERSION >= 0
json_lcommunity = json_object_new_object();
json_object_set_serializer(json_lcommunity, lcommunity_json_to_string,
lcom, NULL);
#else
if (!lcom->json)
lcommunity_str(lcom, true, true);
json_lcommunity = json_object_lock(lcom->json);
#endif
return json_lcommunity;
}

View file

@ -48,6 +48,7 @@ extern struct lcommunity *lcommunity_merge(struct lcommunity *,
struct lcommunity *);
extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
extern struct lcommunity *lcommunity_intern(struct lcommunity *);
extern json_object *lcommunity_get_json(struct lcommunity *lcom);
extern bool lcommunity_cmp(const void *arg1, const void *arg2);
extern void lcommunity_unintern(struct lcommunity **);
extern unsigned int lcommunity_hash_make(const void *);

View file

@ -11253,6 +11253,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_peer = NULL;
json_object *json_string = NULL;
json_object *json_adv_to = NULL;
json_object *json_aspath = NULL;
json_object *json_community = NULL;
json_object *json_lcommunity = NULL;
int first = 0;
struct listnode *node, *nnode;
struct peer *peer;
@ -11394,11 +11397,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Line1 display AS-path, Aggregator */
if (attr->aspath) {
if (json_paths) {
if (!attr->aspath->json)
aspath_str_update(attr->aspath, true);
json_object_lock(attr->aspath->json);
json_object_object_add(json_path, "aspath",
attr->aspath->json);
json_aspath = aspath_get_json(attr->aspath);
json_object_object_add(json_path, "aspath", json_aspath);
} else {
if (attr->aspath->segments)
vty_out(vty, " %s", attr->aspath->str);
@ -11967,13 +11967,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Line 4 display Community */
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
if (json_paths) {
if (!bgp_attr_get_community(attr)->json)
community_str(bgp_attr_get_community(attr),
true, true);
json_object_lock(bgp_attr_get_community(attr)->json);
json_object_object_add(
json_path, "community",
bgp_attr_get_community(attr)->json);
json_community = community_get_json(
bgp_attr_get_community(attr));
json_object_object_add(json_path, "community",
json_community);
} else {
if (!bgp_attr_get_community(attr)->str)
community_str(bgp_attr_get_community(attr), true, true);
@ -12021,13 +12018,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Line 6 display Large community */
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (json_paths) {
if (!bgp_attr_get_lcommunity(attr)->json)
lcommunity_str(bgp_attr_get_lcommunity(attr),
true, true);
json_object_lock(bgp_attr_get_lcommunity(attr)->json);
json_object_object_add(
json_path, "largeCommunity",
bgp_attr_get_lcommunity(attr)->json);
json_lcommunity = lcommunity_get_json(
bgp_attr_get_lcommunity(attr));
json_object_object_add(json_path, "largeCommunity",
json_lcommunity);
} else {
if (!bgp_attr_get_lcommunity(attr)->str)
lcommunity_str(bgp_attr_get_lcommunity(attr), true, true);

View file

@ -128,12 +128,16 @@ 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)
static void asn_asn2asdot(as_t asn, char *asstring, size_t len,
bool quotation_mark)
{
uint16_t low, high;
high = (asn >> 16) & 0xffff;
low = asn & 0xffff;
if (quotation_mark)
snprintf(asstring, len, "\"%hu.%hu\"", high, low);
else
snprintf(asstring, len, "%hu.%hu", high, low);
}
@ -202,25 +206,36 @@ void asn_asn2json(json_object *json, const char *attr,
((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
json_object_int_add(json, attr, asn);
else {
asn_asn2asdot(asn, as_str, sizeof(as_str));
asn_asn2asdot(asn, as_str, sizeof(as_str), false);
json_object_string_add(json, attr, as_str);
}
}
void asn_asn2json_array(json_object *jseg_list, as_t asn,
enum asnotation_mode asnotation)
enum asnotation_mode asnotation, struct printbuf *pb,
bool incremental_print)
{
static char as_str[ASN_STRING_MAX_SIZE];
static char as_str[ASN_STRING_MAX_SIZE + 2];
const char *const_str = as_str;
if ((asnotation == ASNOTATION_PLAIN) ||
((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
if (incremental_print) {
snprintf(as_str, sizeof(as_str), "%u", asn);
printbuf_memappend(pb, const_str, strlen(const_str));
} else
json_object_array_add(jseg_list,
json_object_new_int64(asn));
else {
asn_asn2asdot(asn, as_str, sizeof(as_str));
if (incremental_print) {
asn_asn2asdot(asn, as_str, sizeof(as_str), true);
printbuf_memappend(pb, const_str, strlen(const_str));
} else {
asn_asn2asdot(asn, as_str, sizeof(as_str), false);
json_array_string_add(jseg_list, as_str);
}
}
}
char *asn_asn2string(const as_t *asn, char *buf, size_t len,
enum asnotation_mode asnotation)
@ -229,7 +244,7 @@ char *asn_asn2string(const as_t *asn, char *buf, size_t len,
((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX))
snprintf(buf, len, "%u", *asn);
else
asn_asn2asdot(*asn, buf, len);
asn_asn2asdot(*asn, buf, len, false);
return buf;
}

View file

@ -50,7 +50,8 @@ 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);
enum asnotation_mode asnotation, struct printbuf *pb,
bool incremental_print);
void asn_asn2json(json_object *jseg_list, const char *attr,
as_t asn, enum asnotation_mode asnotation);
extern char *asn_asn2string(const as_t *as, char *buf, size_t len,

View file

@ -13,6 +13,7 @@ extern "C" {
#include "command.h"
#include "printfrr.h"
#include <json-c/json.h>
#include <json-c/printbuf.h>
/*
* FRR style JSON iteration.