summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-11-17 02:43:56 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-11-17 15:04:26 +0100
commita69ea8aeac9d6cc5c27c084d02a0ddcd96231e46 (patch)
tree88399c020efd0d768e90865bf2da3cc9f92c149c
parentbgpd: Only create json for aspath if needed (diff)
downloadfrr-a69ea8aeac9d6cc5c27c084d02a0ddcd96231e46.tar.xz
frr-a69ea8aeac9d6cc5c27c084d02a0ddcd96231e46.zip
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 <sharpd@cumulusnetworks.com>
-rw-r--r--bgpd/bgp_clist.c2
-rw-r--r--bgpd/bgp_community.c66
-rw-r--r--bgpd/bgp_community.h2
-rw-r--r--bgpd/bgp_debug.c3
-rw-r--r--bgpd/bgp_route.c3
-rw-r--r--bgpd/bgp_routemap.c2
-rw-r--r--bgpd/bgp_vty.c6
7 files changed, 54 insertions, 30 deletions
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index f3bae9535..72b1098ed 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -438,7 +438,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 b0f00d67d..7c83eaa09 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -169,7 +169,6 @@ struct community *community_uniq_sort(struct community *com)
return NULL;
new = community_new();
- ;
new->json = NULL;
for (i = 0; i < com->size; i++) {
@@ -195,7 +194,7 @@ struct community *community_uniq_sort(struct community *com)
0xFFFF0000 "graceful-shutdown"
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;
@@ -211,16 +210,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;
}
@@ -273,47 +276,61 @@ 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;
case COMMUNITY_GSHUT:
strcpy(pnt, "graceful-shutdown");
pnt += strlen("graceful-shutdown");
- json_string = json_object_new_string("gracefulShutdown");
- json_object_array_add(json_community_list, json_string);
+ if (make_json) {
+ json_string = json_object_new_string("gracefulShutdown");
+ 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;
}
@@ -338,7 +355,7 @@ struct community *community_intern(struct community *com)
/* Make string. */
if (!find->str)
- set_community_string(find);
+ set_community_string(find, false);
return find;
}
@@ -396,13 +413,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 f728debdb..5016f132f 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -63,7 +63,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 6e16d5f45..45ac8e685 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -385,7 +385,8 @@ int bgp_dump_attr(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_EXT_COMMUNITIES)))
snprintf(buf + strlen(buf), size - strlen(buf),
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f0d91c366..ba75da459 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -7885,6 +7885,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
/* 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 45487aa00..cc8cfd550 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3813,7 +3813,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 db19835f8..40f706a64 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -10010,7 +10010,7 @@ static void community_show_all_iterator(struct hash_backet *backet,
com = (struct community *)backet->data;
vty_out(vty, "[%p] (%ld) %s\n", (void *)com, com->refcnt,
- community_str(com));
+ community_str(com, false));
}
/* Show BGP's community internal data. */
@@ -12698,7 +12698,7 @@ static void community_list_show(struct vty *vty, struct community_list *list)
vty_out(vty, " %s %s\n",
community_direct_str(entry->direct),
entry->style == COMMUNITY_LIST_STANDARD
- ? community_str(entry->u.com)
+ ? community_str(entry->u.com, false)
: entry->config);
}
}
@@ -13354,7 +13354,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;
}