]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Only build json for community when needed
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 17 Nov 2017 01:43:56 +0000 (20:43 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 4 Dec 2017 13:48:15 +0000 (08:48 -0500)
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>
bgpd/bgp_clist.c
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_debug.c
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_vty.c

index 7e0d03869e8db5a80285b242809cc84e7e833c3a..2f111d6d55ab8342cb603d43318e48a27cc76c43 100644 (file)
@@ -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)
index 96ccc9277176c124106283b3d5c00b7efacd87a0..9fe59d2cf39a2244be5f0cf0cd4124050533603c 100644 (file)
@@ -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;
 }
 
index e9195f5528ad06fa4e0cc1f10ebba92aea61f4f3..bcdba9a712339d19784ed4dae5f69e4932808d7a 100644 (file)
@@ -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 *);
index e1d40525e2672e2b208a47517d42e409827e41b4..d66aadb54e3fd329b4fca7d8ca9a950c866d4af8 100644 (file)
@@ -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),
index 9bd0f137e5e51157e9897ed44a629d1caf1ed98e..1bba56dff1f5cd1b09f33b5b7f35775021185f44 100644 (file)
@@ -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);
index b3c6e10013cc526565b59c8e875dcda4c88658da..dde2410236016099a994cf9c37e7102c9acbf2e5 100644 (file)
@@ -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,
index 741afeb17e4715a1e71e6777dc27d6f3cf4c97f1..80bdf5f503dd64f7637a807385f10c600b64d278 100644 (file)
@@ -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;
        }