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++) { for (i = 0; i < seg->length; i++) {
if (make_json) if (make_json)
asn_asn2json_array(jseg_list, seg->as[i], asn_asn2json_array(jseg_list, seg->as[i],
as->asnotation); as->asnotation, NULL, false);
len += snprintfrr(str_buf + len, str_size - len, len += snprintfrr(str_buf + len, str_size - len,
ASN_FORMAT(as->asnotation), ASN_FORMAT(as->asnotation),
&seg->as[i]); &seg->as[i]);
@ -673,6 +673,67 @@ void aspath_str_update(struct aspath *as, bool make_json)
aspath_make_str_count(as, 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. */ /* Intern allocated AS path. */
struct aspath *aspath_intern(struct aspath *aspath) 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_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);
extern json_object *aspath_get_json(struct aspath *aspath);
extern void aspath_unintern(struct aspath **aspath); extern void aspath_unintern(struct aspath **aspath);
extern const char *aspath_print(struct aspath *aspath); extern const char *aspath_print(struct aspath *aspath);
extern void aspath_print_vty(struct vty *vty, 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; 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. /* Convert communities attribute to string.
For Well-known communities value, below keyword is used. 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; int i;
char *str; char *str;
int len; int len;
int first;
uint32_t comval; uint32_t comval;
uint16_t as;
uint16_t val;
json_object *json_community_list = NULL; json_object *json_community_list = NULL;
json_object *json_string = NULL;
if (!com) if (!com)
return; return;
@ -278,160 +500,9 @@ static void set_community_string(struct community *com, bool make_json,
/* Allocate memory. */ /* Allocate memory. */
str = XCALLOC(MTYPE_COMMUNITY_STR, len); str = XCALLOC(MTYPE_COMMUNITY_STR, len);
first = 1;
/* Fill in string. */ community_json_list(com, make_json ? json_community_list : NULL, str,
for (i = 0; i < com->size; i++) { len, translate_alias, NULL);
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;
}
}
if (make_json) { if (make_json) {
json_object_string_add(com->json, "string", str); 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); *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) void bgp_aggr_community_remove(void *arg)
{ {
struct community *community = 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_uniq_sort(struct community *com);
extern struct community *community_parse(uint32_t *pnt, unsigned short length); extern struct community *community_parse(uint32_t *pnt, unsigned short length);
extern struct community *community_intern(struct community *com); 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 void community_unintern(struct community **com);
extern char *community_str(struct community *com, bool make_json, extern char *community_str(struct community *com, bool make_json,
bool translate_alias); bool translate_alias);

View file

@ -161,48 +161,33 @@ struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
return lcom1; return lcom1;
} }
static void set_lcommunity_string(struct lcommunity *lcom, bool make_json, /* 3 32-bit integers, 2 colons, and a space */
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) #define LCOMMUNITY_STRLEN (10 * 3 + 2 + 1)
if (!lcom) /* Convert large communities attribute to string and optionally add json objects
return; * into the pased json_community_list string
*/
if (make_json) { static char *lcommunity_json_list(struct lcommunity *lcom,
lcom->json = json_object_new_object(); json_object *json_lcommunity_list,
json_lcommunity_list = json_object_new_array(); bool translate_alias, bool return_buffer,
} struct printbuf *pb)
{
if (lcom->size == 0) { int i, len;
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, 1); const uint8_t *pnt;
uint32_t global, local1, local2;
if (make_json) { char *str_buf = NULL;
json_object_string_add(lcom->json, "string", ""); size_t str_buf_sz = 0;
json_object_object_add(lcom->json, "list", json_object *json_string = NULL;
json_lcommunity_list);
}
lcom->str = str_buf;
return;
}
/* 1 space + lcom->size lcom strings + null terminator */ /* 1 space + lcom->size lcom strings + null terminator */
size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2; if (return_buffer) {
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz); str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
}
len = 0; len = 0;
for (i = 0; i < lcom->size; i++) { for (i = 0; i < lcom->size; i++) {
if (i > 0) if (return_buffer && i > 0)
len = strlcat(str_buf, " ", str_buf_sz); len = strlcat(str_buf, " ", str_buf_sz);
pnt = lcom->val + (i * LCOMMUNITY_SIZE); pnt = lcom->val + (i * LCOMMUNITY_SIZE);
@ -225,20 +210,56 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
const char *com2alias = const char *com2alias =
translate_alias ? bgp_community2alias(lcsb) : lcsb; translate_alias ? bgp_community2alias(lcsb) : lcsb;
size_t individual_len = strlen(com2alias); size_t individual_len = strlen(com2alias);
if (individual_len + len > str_buf_sz) { if (str_buf) {
str_buf_sz = individual_len + len + 1; if (individual_len + len > str_buf_sz) {
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf, str_buf_sz = individual_len + len + 1;
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 (pb)
sprintbuf(pb, "%s\"%s\"", i ? "," : "", com2alias);
if (make_json) { else if (json_lcommunity_list) {
json_string = json_object_new_string(com2alias); json_string = json_object_new_string(com2alias);
json_object_array_add(json_lcommunity_list, json_object_array_add(json_lcommunity_list,
json_string); 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) { if (make_json) {
json_object_string_add(lcom->json, "string", str_buf); 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); *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) void bgp_aggr_lcommunity_remove(void *arg)
{ {
struct lcommunity *lcommunity = 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 *); struct lcommunity *);
extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *); extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
extern struct lcommunity *lcommunity_intern(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 bool lcommunity_cmp(const void *arg1, const void *arg2);
extern void lcommunity_unintern(struct lcommunity **); extern void lcommunity_unintern(struct lcommunity **);
extern unsigned int lcommunity_hash_make(const void *); 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_peer = NULL;
json_object *json_string = NULL; json_object *json_string = NULL;
json_object *json_adv_to = 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; int first = 0;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct peer *peer; 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 */ /* Line1 display AS-path, Aggregator */
if (attr->aspath) { if (attr->aspath) {
if (json_paths) { if (json_paths) {
if (!attr->aspath->json) json_aspath = aspath_get_json(attr->aspath);
aspath_str_update(attr->aspath, true); json_object_object_add(json_path, "aspath", json_aspath);
json_object_lock(attr->aspath->json);
json_object_object_add(json_path, "aspath",
attr->aspath->json);
} else { } else {
if (attr->aspath->segments) if (attr->aspath->segments)
vty_out(vty, " %s", attr->aspath->str); 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 */ /* Line 4 display Community */
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) { if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
if (json_paths) { if (json_paths) {
if (!bgp_attr_get_community(attr)->json) json_community = community_get_json(
community_str(bgp_attr_get_community(attr), bgp_attr_get_community(attr));
true, true); json_object_object_add(json_path, "community",
json_object_lock(bgp_attr_get_community(attr)->json); json_community);
json_object_object_add(
json_path, "community",
bgp_attr_get_community(attr)->json);
} else { } else {
if (!bgp_attr_get_community(attr)->str) if (!bgp_attr_get_community(attr)->str)
community_str(bgp_attr_get_community(attr), true, true); 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 */ /* Line 6 display Large community */
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) { if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (json_paths) { if (json_paths) {
if (!bgp_attr_get_lcommunity(attr)->json) json_lcommunity = lcommunity_get_json(
lcommunity_str(bgp_attr_get_lcommunity(attr), bgp_attr_get_lcommunity(attr));
true, true); json_object_object_add(json_path, "largeCommunity",
json_object_lock(bgp_attr_get_lcommunity(attr)->json); json_lcommunity);
json_object_object_add(
json_path, "largeCommunity",
bgp_attr_get_lcommunity(attr)->json);
} else { } else {
if (!bgp_attr_get_lcommunity(attr)->str) if (!bgp_attr_get_lcommunity(attr)->str)
lcommunity_str(bgp_attr_get_lcommunity(attr), true, true); lcommunity_str(bgp_attr_get_lcommunity(attr), true, true);

View file

@ -128,13 +128,17 @@ 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) static void asn_asn2asdot(as_t asn, char *asstring, size_t len,
bool quotation_mark)
{ {
uint16_t low, high; uint16_t low, high;
high = (asn >> 16) & 0xffff; high = (asn >> 16) & 0xffff;
low = asn & 0xffff; low = asn & 0xffff;
snprintf(asstring, len, "%hu.%hu", high, low); if (quotation_mark)
snprintf(asstring, len, "\"%hu.%hu\"", high, low);
else
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)
@ -202,23 +206,34 @@ void asn_asn2json(json_object *json, const char *attr,
((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX)) ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
json_object_int_add(json, attr, asn); json_object_int_add(json, attr, asn);
else { 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); json_object_string_add(json, attr, as_str);
} }
} }
void asn_asn2json_array(json_object *jseg_list, as_t asn, 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) || if ((asnotation == ASNOTATION_PLAIN) ||
((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX)) ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
json_object_array_add(jseg_list, if (incremental_print) {
json_object_new_int64(asn)); 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 { else {
asn_asn2asdot(asn, as_str, sizeof(as_str)); if (incremental_print) {
json_array_string_add(jseg_list, as_str); 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);
}
} }
} }
@ -229,7 +244,7 @@ char *asn_asn2string(const as_t *asn, char *buf, size_t len,
((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX)) ((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX))
snprintf(buf, len, "%u", *asn); snprintf(buf, len, "%u", *asn);
else else
asn_asn2asdot(*asn, buf, len); asn_asn2asdot(*asn, buf, len, false);
return buf; return buf;
} }

View file

@ -50,7 +50,8 @@ 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, 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, void asn_asn2json(json_object *jseg_list, const char *attr,
as_t asn, enum asnotation_mode asnotation); as_t asn, enum asnotation_mode asnotation);
extern char *asn_asn2string(const as_t *as, char *buf, size_t len, 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 "command.h"
#include "printfrr.h" #include "printfrr.h"
#include <json-c/json.h> #include <json-c/json.h>
#include <json-c/printbuf.h>
/* /*
* FRR style JSON iteration. * FRR style JSON iteration.