mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge de17bbb188
into 3dd4d417be
This commit is contained in:
commit
7cedd9b975
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
/* 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;
|
||||
str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
|
||||
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 (individual_len + len > str_buf_sz) {
|
||||
str_buf_sz = individual_len + len + 1;
|
||||
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
|
||||
str_buf_sz);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
35
lib/asn.c
35
lib/asn.c
|
@ -128,13 +128,17 @@ 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;
|
||||
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)
|
||||
|
@ -202,23 +206,34 @@ 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))
|
||||
json_object_array_add(jseg_list,
|
||||
json_object_new_int64(asn));
|
||||
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));
|
||||
json_array_string_add(jseg_list, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue