From: Donald Sharp Date: Fri, 17 Nov 2017 01:43:56 +0000 (-0500) Subject: bgpd: Only build json for community when needed X-Git-Tag: frr-3.0.3~5 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=c0d638ab2f7f593eebd1c43b44d5d8531035e145;p=matthieu%2Ffrr.git bgpd: Only build json for community when needed Building a communities json object every time is both expensive and memory wasteful. Modify code to only build the json object when needed. Signed-off-by: Donald Sharp --- diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 7e0d03869e..2f111d6d55 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -430,7 +430,7 @@ static int community_regexp_match(struct community *com, regex_t *reg) if (com == NULL || com->size == 0) str = ""; else - str = community_str(com); + str = community_str(com, false); /* Regular expression match. */ if (regexec(reg, str, 0, NULL, 0) == 0) diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index 96ccc92771..9fe59d2cf3 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -168,7 +168,6 @@ struct community *community_uniq_sort(struct community *com) return NULL; new = community_new(); - ; new->json = NULL; for (i = 0; i < com->size; i++) { @@ -193,7 +192,7 @@ struct community *community_uniq_sort(struct community *com) 0xFFFFFF03 "local-AS" For other values, "AS:VAL" format is used. */ -static void set_community_string(struct community *com) +static void set_community_string(struct community *com, bool make_json) { int i; char *str; @@ -209,16 +208,20 @@ static void set_community_string(struct community *com) if (!com) return; - com->json = json_object_new_object(); - json_community_list = json_object_new_array(); + if (make_json) { + com->json = json_object_new_object(); + json_community_list = json_object_new_array(); + } /* When communities attribute is empty. */ if (com->size == 0) { str = XMALLOC(MTYPE_COMMUNITY_STR, 1); str[0] = '\0'; - json_object_string_add(com->json, "string", ""); - json_object_object_add(com->json, "list", json_community_list); + if (make_json) { + json_object_string_add(com->json, "string", ""); + json_object_object_add(com->json, "list", json_community_list); + } com->str = str; return; } @@ -268,41 +271,53 @@ static void set_community_string(struct community *com) case COMMUNITY_INTERNET: strcpy(pnt, "internet"); pnt += strlen("internet"); - json_string = json_object_new_string("internet"); - json_object_array_add(json_community_list, json_string); + if (make_json) { + json_string = json_object_new_string("internet"); + json_object_array_add(json_community_list, json_string); + } break; case COMMUNITY_NO_EXPORT: strcpy(pnt, "no-export"); pnt += strlen("no-export"); - json_string = json_object_new_string("noExport"); - json_object_array_add(json_community_list, json_string); + if (make_json) { + json_string = json_object_new_string("noExport"); + json_object_array_add(json_community_list, json_string); + } break; case COMMUNITY_NO_ADVERTISE: strcpy(pnt, "no-advertise"); pnt += strlen("no-advertise"); - json_string = json_object_new_string("noAdvertise"); - json_object_array_add(json_community_list, json_string); + if (make_json) { + json_string = json_object_new_string("noAdvertise"); + json_object_array_add(json_community_list, json_string); + } break; case COMMUNITY_LOCAL_AS: strcpy(pnt, "local-AS"); pnt += strlen("local-AS"); - json_string = json_object_new_string("localAs"); - json_object_array_add(json_community_list, json_string); + if (make_json) { + json_string = json_object_new_string("localAs"); + json_object_array_add(json_community_list, json_string); + } break; default: as = (comval >> 16) & 0xFFFF; val = comval & 0xFFFF; sprintf(pnt, "%u:%d", as, val); - json_string = json_object_new_string(pnt); - json_object_array_add(json_community_list, json_string); + if (make_json) { + json_string = json_object_new_string(pnt); + json_object_array_add(json_community_list, json_string); + } pnt += strlen(pnt); break; } } *pnt = '\0'; - json_object_string_add(com->json, "string", str); - json_object_object_add(com->json, "list", json_community_list); + if (make_json) { + json_object_string_add(com->json, "string", str); + json_object_object_add(com->json, "list", json_community_list); + } com->str = str; } @@ -327,7 +342,7 @@ struct community *community_intern(struct community *com) /* Make string. */ if (!find->str) - set_community_string(find); + set_community_string(find, false); return find; } @@ -385,13 +400,16 @@ struct community *community_dup(struct community *com) } /* Retrun string representation of communities attribute. */ -char *community_str(struct community *com) +char *community_str(struct community *com, bool make_json) { if (!com) return NULL; + if (make_json && !com->json && com->str) + XFREE(MTYPE_COMMUNITY_STR, com->str); + if (!com->str) - set_community_string(com); + set_community_string(com, make_json); return com->str; } diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index e9195f5528..bcdba9a712 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -62,7 +62,7 @@ extern struct community *community_uniq_sort(struct community *); extern struct community *community_parse(u_int32_t *, u_short); extern struct community *community_intern(struct community *); extern void community_unintern(struct community **); -extern char *community_str(struct community *); +extern char *community_str(struct community *, bool make_json); extern unsigned int community_hash_make(struct community *); extern struct community *community_str2com(const char *); extern int community_match(const struct community *, const struct community *); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index e1d40525e2..d66aadb54e 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -385,7 +385,8 @@ int bgp_dump_attr(struct peer *peer, struct attr *attr, char *buf, size_t size) if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) snprintf(buf + strlen(buf), size - strlen(buf), - ", community %s", community_str(attr->community)); + ", community %s", community_str(attr->community, + false)); if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) snprintf(buf + strlen(buf), size - strlen(buf), diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 9bd0f137e5..1bba56dff1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7418,6 +7418,9 @@ static void route_vty_out_detail(struct vty *vty, struct bgp *bgp, /* Line 4 display Community */ if (attr->community) { if (json_paths) { + if (!attr->community->json) + community_str(attr->community, + true); json_object_lock(attr->community->json); json_object_object_add(json_path, "community", attr->community->json); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index b3c6e10013..dde2410236 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3594,7 +3594,7 @@ DEFUN (set_community, } /* Set communites attribute string. */ - str = community_str(com); + str = community_str(com, false); if (additive) { argstr = XCALLOC(MTYPE_TMP, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 741afeb17e..80bdf5f503 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9530,7 +9530,7 @@ static void community_show_all_iterator(struct hash_backet *backet, com = (struct community *)backet->data; vty_out(vty, "[%p] (%ld) %s%s", (void *)backet, com->refcnt, - community_str(com), VTY_NEWLINE); + community_str(com, false), VTY_NEWLINE); } /* Show BGP's community internal data. */ @@ -11892,8 +11892,8 @@ static void community_list_show(struct vty *vty, struct community_list *list) vty_out(vty, " %s %s%s", community_direct_str(entry->direct), entry->style == COMMUNITY_LIST_STANDARD - ? community_str(entry->u.com) - : entry->config, + ? community_str(entry->u.com, false) + : entry->config, VTY_NEWLINE); } } @@ -12555,7 +12555,7 @@ static const char *community_list_config_str(struct community_entry *entry) str = ""; else { if (entry->style == COMMUNITY_LIST_STANDARD) - str = community_str(entry->u.com); + str = community_str(entry->u.com, false); else str = entry->config; }