Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'show bgp detail' memory improvement #16771

Closed
148 changes: 73 additions & 75 deletions bgpd/bgp_aspath.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,6 @@ void aspath_free(struct aspath *aspath)
assegment_free_all(aspath->segments);
XFREE(MTYPE_AS_STR, aspath->str);

if (aspath->json) {
json_object_free(aspath->json);
aspath->json = NULL;
}

XFREE(MTYPE_AS_PATH, aspath);
}

Expand Down Expand Up @@ -506,29 +501,15 @@ bool aspath_has_as4(struct aspath *aspath)
}

/* Convert aspath structure to string expression. */
static void aspath_make_str_count(struct aspath *as, bool make_json)
static void aspath_make_str_count(struct aspath *as)
{
struct assegment *seg;
int str_size;
int len = 0;
char *str_buf;
json_object *jaspath_segments = NULL;
json_object *jseg = NULL;
json_object *jseg_list = NULL;

if (make_json) {
as->json = json_object_new_object();
jaspath_segments = json_object_new_array();
}

/* Empty aspath. */
if (!as->segments) {
if (make_json) {
json_object_string_add(as->json, "string", "Local");
json_object_object_add(as->json, "segments",
jaspath_segments);
json_object_int_add(as->json, "length", 0);
}
as->str = XMALLOC(MTYPE_AS_STR, 1);
as->str[0] = '\0';
as->str_len = 0;
Expand Down Expand Up @@ -571,8 +552,6 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
XFREE(MTYPE_AS_STR, str_buf);
as->str = NULL;
as->str_len = 0;
json_object_free(as->json);
as->json = NULL;

return;
}
Expand All @@ -599,14 +578,8 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
str_buf + len, str_size - len, "%c",
aspath_delimiter_char(seg->type, AS_SEG_START));

if (make_json)
jseg_list = json_object_new_array();

/* write out the ASNs, with their separators, bar the last one*/
for (i = 0; i < seg->length; i++) {
if (make_json)
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]);
Expand All @@ -616,15 +589,6 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
"%c", separator);
}

if (make_json) {
jseg = json_object_new_object();
json_object_string_add(
jseg, "type",
aspath_segment_type_str[seg->type]);
json_object_object_add(jseg, "list", jseg_list);
json_object_array_add(jaspath_segments, jseg);
}

if (seg->type != AS_SEQUENCE)
len += snprintf(
str_buf + len, str_size - len, "%c",
Expand All @@ -641,27 +605,68 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
as->str = str_buf;
as->str_len = len;

if (make_json) {
json_object_string_add(as->json, "string", str_buf);
json_object_object_add(as->json, "segments", jaspath_segments);
json_object_int_add(as->json, "length", aspath_count_hops(as));
}

return;
}

void aspath_str_update(struct aspath *as, bool make_json)
void aspath_str_update(struct aspath *as)
{
XFREE(MTYPE_AS_STR, as->str);

if (as->json) {
json_object_free(as->json);
as->json = NULL;
aspath_make_str_count(as);
}

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\":[");

aspath_make_str_count(as, make_json);
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));
}

json_object *aspath_get_json(struct aspath *aspath)
{
json_object *json_aspath = NULL;

json_aspath = json_object_new_object();
json_object_set_serializer(json_aspath, aspath_json_string, aspath,
NULL);
return json_aspath;
}
/* Intern allocated AS path. */
struct aspath *aspath_intern(struct aspath *aspath)
{
Expand Down Expand Up @@ -690,7 +695,6 @@ struct aspath *aspath_dup(struct aspath *aspath)
struct aspath *new;

new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));
new->json = NULL;

if (aspath->segments)
new->segments = assegment_dup_all(aspath->segments);
Expand Down Expand Up @@ -727,7 +731,6 @@ static void *aspath_hash_alloc(void *arg)
new->segments = aspath->segments;
new->str = aspath->str;
new->str_len = aspath->str_len;
new->json = aspath->json;
new->asnotation = aspath->asnotation;

return new;
Expand Down Expand Up @@ -864,10 +867,6 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit,
assegment_free_all(as.segments);
/* aspath_key_make() always updates the string */
XFREE(MTYPE_AS_STR, as.str);
if (as.json) {
json_object_free(as.json);
as.json = NULL;
}
}

find->refcnt++;
Expand Down Expand Up @@ -1112,7 +1111,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)
}

assegment_normalise(aspath->segments);
aspath_str_update(aspath, false);
aspath_str_update(aspath);
return aspath;
}

Expand Down Expand Up @@ -1267,7 +1266,7 @@ struct aspath *aspath_replace_regex_asn(struct aspath *aspath,
cur_seg = cur_seg->next;
}

aspath_str_update(new, false);
aspath_str_update(new);
return new;
}

Expand All @@ -1292,7 +1291,7 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
seg = seg->next;
}

aspath_str_update(new, false);
aspath_str_update(new);
return new;
}

Expand All @@ -1314,7 +1313,7 @@ struct aspath *aspath_replace_all_asn(struct aspath *aspath, as_t our_asn)
seg = seg->next;
}

aspath_str_update(new, false);
aspath_str_update(new);
return new;
}

Expand All @@ -1340,7 +1339,7 @@ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn,
seg = seg->next;
}

aspath_str_update(new, false);
aspath_str_update(new);
return new;
}

Expand All @@ -1358,7 +1357,6 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath, as_t peer_asn)

new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath));

new->json = NULL;
new_seg = NULL;
last_new_seg = NULL;
seg = aspath->segments;
Expand Down Expand Up @@ -1412,7 +1410,7 @@ struct aspath *aspath_remove_private_asns(struct aspath *aspath, as_t peer_asn)
}
if (!aspath->refcnt)
aspath_free(aspath);
aspath_str_update(new, false);
aspath_str_update(new);
return new;
}

Expand Down Expand Up @@ -1468,7 +1466,7 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
if (last)
last->next = as2->segments;
as2->segments = new;
aspath_str_update(as2, false);
aspath_str_update(as2);
return as2;
}

Expand All @@ -1485,7 +1483,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
/* If as2 is empty, only need to dupe as1's chain onto as2 */
if (as2->segments == NULL) {
as2->segments = assegment_dup_all(as1->segments);
aspath_str_update(as2, false);
aspath_str_update(as2);
return as2;
}

Expand All @@ -1505,7 +1503,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)

if (!as2->segments) {
as2->segments = assegment_dup_all(as1->segments);
aspath_str_update(as2, false);
aspath_str_update(as2);
return as2;
}

Expand Down Expand Up @@ -1550,7 +1548,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
/* we've now prepended as1's segment chain to as2, merging
* the inbetween AS_SEQUENCE of seg2 in the process
*/
aspath_str_update(as2, false);
aspath_str_update(as2);
return as2;
} else {
/* AS_SET merge code is needed at here. */
Expand Down Expand Up @@ -1661,7 +1659,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,
lastseg->next = newseg;
lastseg = newseg;
}
aspath_str_update(newpath, false);
aspath_str_update(newpath);
/* We are happy returning even an empty AS_PATH, because the
* administrator
* might expect this very behaviour. There's a mean to avoid this, if
Expand All @@ -1679,7 +1677,7 @@ struct aspath *aspath_filter_exclude_all(struct aspath *source)

newpath = aspath_new(source->asnotation);

aspath_str_update(newpath, false);
aspath_str_update(newpath);
/* We are happy returning even an empty AS_PATH, because the
* administrator
* might expect this very behaviour. There's a mean to avoid this, if
Expand Down Expand Up @@ -1766,7 +1764,7 @@ struct aspath *aspath_filter_exclude_acl(struct aspath *source,
}


aspath_str_update(source, false);
aspath_str_update(source);
/* We are happy returning even an empty AS_PATH, because the
* administrator
* might expect this very behaviour. There's a mean to avoid this, if
Expand Down Expand Up @@ -1804,7 +1802,7 @@ static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno,
aspath->segments = newsegment;
}

aspath_str_update(aspath, false);
aspath_str_update(aspath);
return aspath;
}

Expand Down Expand Up @@ -1895,7 +1893,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,

if (!hops) {
newpath = aspath_dup(as4path);
aspath_str_update(newpath, false);
aspath_str_update(newpath);
return newpath;
}

Expand Down Expand Up @@ -1956,7 +1954,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,
mergedpath = aspath_merge(newpath, aspath_dup(as4path));
aspath_free(newpath);
mergedpath->segments = assegment_normalise(mergedpath->segments);
aspath_str_update(mergedpath, false);
aspath_str_update(mergedpath);

if (BGP_DEBUG(as4, AS4))
zlog_debug("[AS4] result of synthesizing is %s",
Expand Down Expand Up @@ -2028,7 +2026,7 @@ struct aspath *aspath_delete_confed_seq(struct aspath *aspath)
}

if (removed_confed_segment)
aspath_str_update(aspath, false);
aspath_str_update(aspath);

return aspath;
}
Expand Down Expand Up @@ -2079,7 +2077,7 @@ struct aspath *aspath_empty_get(void)
struct aspath *aspath;

aspath = aspath_new(bgp_get_asnotation(NULL));
aspath_make_str_count(aspath, false);
aspath_make_str_count(aspath);
return aspath;
}

Expand Down Expand Up @@ -2220,7 +2218,7 @@ struct aspath *aspath_str2aspath(const char *str,
}
}

aspath_make_str_count(aspath, false);
aspath_make_str_count(aspath);

return aspath;
}
Expand All @@ -2232,7 +2230,7 @@ unsigned int aspath_key_make(const void *p)
unsigned int key = 0;

if (!aspath->str)
aspath_str_update((struct aspath *)aspath, false);
aspath_str_update((struct aspath *)aspath);

key = jhash(aspath->str, aspath->str_len, 2334325);

Expand Down
6 changes: 2 additions & 4 deletions bgpd/bgp_aspath.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ struct aspath {
/* segment data */
struct assegment *segments;

/* AS path as a json object */
json_object *json;

/* String expression of AS path. This string is used by vty output
and AS path regular expression match. */
char *str;
Expand Down Expand Up @@ -109,9 +106,10 @@ extern struct aspath *aspath_empty(enum asnotation_mode asnotation);
extern struct aspath *aspath_empty_get(void);
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_str_update(struct aspath *as);
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);
Expand Down
Loading
Loading