]> git.puffer.fish Git - matthieu/frr.git/commitdiff
Key changes:
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 12 Jun 2015 14:59:11 +0000 (07:59 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 12 Jun 2015 14:59:11 +0000 (07:59 -0700)
- The aspath and community structures now have a json_object where we
  store the json representation.  This is updated at the same time
  the "str" for aspath/community are updated.  We do this so that we
  do not have to compute the json rep
- Added a small wrappper to libjson0, the wrapper lives in quagga's lib/json.[ch].
- Added more structure to the json output.  Sample output:

show ip bgp summary json
------------------------
BGP router identifier 10.0.0.1, local AS number 10
BGP table version 2400
RIB entries 4799, using 562 KiB of memory
Peers 17, using 284 KiB of memory
Peer groups 4, using 224 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
1.1.1.1         4    10       0       0        0    0    0 never    Active
10.0.0.2        4    10     104       7        0    0    0 00:02:29      600
10.0.0.3        4    10     104       7        0    0    0 00:02:29      600
10.0.0.4        4    10     204       7        0    0    0 00:02:29     1200
20.1.1.6        4    20     406     210        0    0    0 00:02:44      600
20.1.1.7        4    20     406     210        0    0    0 00:02:44      600
40.1.1.2        4    40     406     210        0    0    0 00:02:44      600
40.1.1.6        4    40     406     210        0    0    0 00:02:44      600
40.1.1.10       4    40     406     210        0    0    0 00:02:44      600

Total number of neighbors 9

{
    "as": 10,
    "dynamic-peers": 0,
    "peer-count": 17,
    "peer-group-count": 4,
    "peer-group-memory": 224,
    "peer-memory": 291312,
    "peers": {
        "1.1.1.1": {
            "inq": 0,
            "msgrcvd": 0,
            "msgsent": 0,
            "outq": 0,
            "prefix-advertised-count": 0,
            "prefix-received-count": 0,
            "remote-as": 10,
            "state": "Active",
            "table-version": 0,
            "uptime": "never",
            "version": 4
        },
        "10.0.0.2": {
            "hostname": "r2",
            "inq": 0,
            "msgrcvd": 104,
            "msgsent": 7,
            "outq": 0,
            "prefix-advertised-count": 1200,
            "prefix-received-count": 600,
            "remote-as": 10,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:21",
            "version": 4
        },
        "10.0.0.3": {
            "hostname": "r3",
            "inq": 0,
            "msgrcvd": 104,
            "msgsent": 7,
            "outq": 0,
            "prefix-advertised-count": 1200,
            "prefix-received-count": 600,
            "remote-as": 10,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:21",
            "version": 4
        },
        "10.0.0.4": {
            "hostname": "r4",
            "inq": 0,
            "msgrcvd": 204,
            "msgsent": 7,
            "outq": 0,
            "prefix-advertised-count": 1200,
            "prefix-received-count": 1200,
            "remote-as": 10,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:21",
            "version": 4
        },
        "20.1.1.6": {
            "hostname": "r6",
            "inq": 0,
            "msgrcvd": 406,
            "msgsent": 210,
            "outq": 0,
            "prefix-advertised-count": 2400,
            "prefix-received-count": 600,
            "remote-as": 20,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:36",
            "version": 4
        },
        "20.1.1.7": {
            "hostname": "r7",
            "inq": 0,
            "msgrcvd": 406,
            "msgsent": 210,
            "outq": 0,
            "prefix-advertised-count": 2400,
            "prefix-received-count": 600,
            "remote-as": 20,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:36",
            "version": 4
        },
        "40.1.1.10": {
            "hostname": "r10",
            "inq": 0,
            "msgrcvd": 406,
            "msgsent": 210,
            "outq": 0,
            "prefix-advertised-count": 2400,
            "prefix-received-count": 600,
            "remote-as": 40,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:36",
            "version": 4
        },
        "40.1.1.2": {
            "hostname": "r8",
            "inq": 0,
            "msgrcvd": 406,
            "msgsent": 210,
            "outq": 0,
            "prefix-advertised-count": 2400,
            "prefix-received-count": 600,
            "remote-as": 40,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:36",
            "version": 4
        },
        "40.1.1.6": {
            "hostname": "r9",
            "inq": 0,
            "msgrcvd": 406,
            "msgsent": 210,
            "outq": 0,
            "prefix-advertised-count": 2400,
            "prefix-received-count": 600,
            "remote-as": 40,
            "state": "Established",
            "table-version": 0,
            "uptime": "00:02:36",
            "version": 4
        }
    },
    "rib-count": 4799,
    "rib-memory": 575880,
    "router-id": "10.0.0.1",
    "table-version": 2400,
    "total-peers": 9
}

show ip bgp json
----------------
*>                  40.1.1.2                 0             0 100 200 300 400 500 40 i
*  40.3.88.0/24     40.1.1.6                 0             0 100 200 300 400 500 40 i
*                   40.1.1.10                0             0 100 200 300 400 500 40 i
*>                  40.1.1.2                 0             0 100 200 300 400 500 40 i
*  40.3.89.0/24     40.1.1.6                 0             0 100 200 300 400 500 40 i
*                   40.1.1.10                0             0 100 200 300 400 500 40 i
*>                  40.1.1.2                 0             0 100 200 300 400 500 40 i

        "40.3.88.0/24": [
            {
                "aspath": "100 200 300 400 500 40",
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.6",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            },
            {
                "aspath": "100 200 300 400 500 40",
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.10",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            },
            {
                "aspath": "100 200 300 400 500 40",
                "bestpath": true,
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.2",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            }
        ],
        "40.3.89.0/24": [
            {
                "aspath": "100 200 300 400 500 40",
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.6",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            },
            {
                "aspath": "100 200 300 400 500 40",
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.10",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            },
            {
                "aspath": "100 200 300 400 500 40",
                "bestpath": true,
                "med": 0,
                "nexthops": [
                    {
                        "afi": "ipv4",
                        "ip": "40.1.1.2",
                        "used": true
                    }
                ],
                "origin": "IGP",
                "path-from": "external",
                "valid": true,
                "weight": 0
            }
        ],

show ip bgp x.x.x.x json
------------------------
BGP routing table entry for 40.3.86.0/24
Paths: (3 available, best #3, table Default-IP-Routing-Table)
  Advertised to non peer-group peers:
  10.0.0.2 10.0.0.3 10.0.0.4 20.1.1.6 20.1.1.7 40.1.1.2 40.1.1.6 40.1.1.10
  100 200 300 400 500 40
    40.1.1.6 from 40.1.1.6 (40.0.0.9)
      Origin IGP, metric 0, localpref 100, valid, external
      Community: 1:1 2:2 3:3 4:4 10:10 20:20
      Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66
      Last update: Fri May  8 21:23:41 2015

  100 200 300 400 500 40
    40.1.1.10 from 40.1.1.10 (40.0.0.10)
      Origin IGP, metric 0, localpref 100, valid, external
      Community: 1:1 2:2 3:3 4:4 10:10 20:20
      Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66
      Last update: Fri May  8 21:23:41 2015

  100 200 300 400 500 40
    40.1.1.2 from 40.1.1.2 (40.0.0.8)
      Origin IGP, metric 0, localpref 100, valid, external, best
      Community: 1:1 2:2 3:3 4:4 10:10 20:20
      Extended Community: RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66
      Last update: Fri May  8 21:23:41 2015

{
    "advertised-to": {
        "10.0.0.2": {
            "hostname": "r2"
        },
        "10.0.0.3": {
            "hostname": "r3"
        },
        "10.0.0.4": {
            "hostname": "r4"
        },
        "20.1.1.6": {
            "hostname": "r6"
        },
        "20.1.1.7": {
            "hostname": "r7"
        },
        "40.1.1.10": {
            "hostname": "r10"
        },
        "40.1.1.2": {
            "hostname": "r8"
        },
        "40.1.1.6": {
            "hostname": "r9"
        }
    },
    "paths": [
        {
            "aspath": {
                "length": 6,
                "segments": [
                    {
                        "list": [
                            100,
                            200,
                            300,
                            400,
                            500,
                            40
                        ],
                        "type": "as-sequence"
                    }
                ],
                "string": "100 200 300 400 500 40"
            },
            "community": {
                "list": [
                    "1:1",
                    "2:2",
                    "3:3",
                    "4:4",
                    "10:10",
                    "20:20"
                ],
                "string": "1:1 2:2 3:3 4:4 10:10 20:20"
            },
            "extended-community": {
                "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66"
            },
            "last-update": {
                "epoch": 1431120222,
                "string": "Fri May  8 21:23:42 2015\n"
            },
            "localpref": 100,
            "med": 0,
            "nexthops": [
                {
                    "accessible": true,
                    "afi": "ipv4",
                    "ip": "40.1.1.6",
                    "metric": 0,
                    "used": true
                }
            ],
            "origin": "IGP",
            "peer": {
                "hostname": "r9",
                "peer-id": "40.1.1.6",
                "router-id": "40.0.0.9",
                "type": "external"
            },
            "valid": true
        },
        {
            "aspath": {
                "length": 6,
                "segments": [
                    {
                        "list": [
                            100,
                            200,
                            300,
                            400,
                            500,
                            40
                        ],
                        "type": "as-sequence"
                    }
                ],
                "string": "100 200 300 400 500 40"
            },
            "community": {
                "list": [
                    "1:1",
                    "2:2",
                    "3:3",
                    "4:4",
                    "10:10",
                    "20:20"
                ],
                "string": "1:1 2:2 3:3 4:4 10:10 20:20"
            },
            "extended-community": {
                "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66"
            },
            "last-update": {
                "epoch": 1431120222,
                "string": "Fri May  8 21:23:42 2015\n"
            },
            "localpref": 100,
            "med": 0,
            "nexthops": [
                {
                    "accessible": true,
                    "afi": "ipv4",
                    "ip": "40.1.1.10",
                    "metric": 0,
                    "used": true
                }
            ],
            "origin": "IGP",
            "peer": {
                "hostname": "r10",
                "peer-id": "40.1.1.10",
                "router-id": "40.0.0.10",
                "type": "external"
            },
            "valid": true
        },
        {
            "aspath": {
                "length": 6,
                "segments": [
                    {
                        "list": [
                            100,
                            200,
                            300,
                            400,
                            500,
                            40
                        ],
                        "type": "as-sequence"
                    }
                ],
                "string": "100 200 300 400 500 40"
            },
            "bestpath": {
                "overall": true
            },
            "community": {
                "list": [
                    "1:1",
                    "2:2",
                    "3:3",
                    "4:4",
                    "10:10",
                    "20:20"
                ],
                "string": "1:1 2:2 3:3 4:4 10:10 20:20"
            },
            "extended-community": {
                "string": "RT:100:100 RT:200:200 RT:300:300 RT:400:400 SoO:44:44 SoO:55:55 SoO:66:66"
            },
            "last-update": {
                "epoch": 1431120222,
                "string": "Fri May  8 21:23:42 2015\n"
            },
            "localpref": 100,
            "med": 0,
            "nexthops": [
                {
                    "accessible": true,
                    "afi": "ipv4",
                    "ip": "40.1.1.2",
                    "metric": 0,
                    "used": true
                }
            ],
            "origin": "IGP",
            "peer": {
                "hostname": "r8",
                "peer-id": "40.1.1.2",
                "router-id": "40.0.0.8",
                "type": "external"
            },
            "valid": true
        }
    ],
    "prefix": "40.3.86.0",
    "prefixlen": 24
}

14 files changed:
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_damp.c
bgpd/bgp_damp.h
bgpd/bgp_open.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_vty.c
bgpd/bgpd.c
lib/Makefile.am
lib/json.c [new file with mode: 0644]
lib/json.h [new file with mode: 0644]

index 04ef87d693060cf02f6a84a024abfae20efa752d..a270d8cd763f461458b04ef3fd18af51c9c337c7 100644 (file)
@@ -99,6 +99,14 @@ assegment_data_new (int num)
   return (XMALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
 }
 
+const char *aspath_segment_type_str[] = {
+  "as-invalid",
+  "as-set",
+  "as-sequence",
+  "as-confed-sequence",
+  "as-confed-set"
+};
+
 /* Get a new segment. Note that 0 is an allowed length,
  * and will result in a segment with no allocated data segment.
  * the caller should immediately assign data to the segment, as the segment
@@ -326,6 +334,13 @@ aspath_free (struct aspath *aspath)
     assegment_free_all (aspath->segments);
   if (aspath->str)
     XFREE (MTYPE_AS_STR, aspath->str);
+
+  if (aspath->json)
+    {
+      json_object_free(aspath->json);
+      aspath->json = NULL;
+    }
+
   XFREE (MTYPE_AS_PATH, aspath);
 }
 
@@ -500,10 +515,19 @@ aspath_make_str_count (struct aspath *as)
   int str_size;
   int len = 0;
   char *str_buf;
+  json_object *jaspath_segments = NULL;
+  json_object *jseg = NULL;
+  json_object *jseg_list = NULL;
+
+  as->json = json_object_new_object();
+  jaspath_segments = json_object_new_array();
 
   /* Empty aspath. */
   if (!as->segments)
     {
+      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;
@@ -546,6 +570,8 @@ aspath_make_str_count (struct aspath *as)
             XFREE (MTYPE_AS_STR, str_buf);
             as->str = NULL;
             as->str_len = 0;
+            json_object_free(as->json);
+            as->json = NULL;
             return;
         }
       
@@ -571,15 +597,24 @@ aspath_make_str_count (struct aspath *as)
         len += snprintf (str_buf + len, str_size - len, 
                         "%c", 
                          aspath_delimiter_char (seg->type, AS_SEG_START));
+
+      jseg_list = json_object_new_array();
       
       /* write out the ASNs, with their seperators, bar the last one*/
       for (i = 0; i < seg->length; i++)
         {
+          json_object_array_add(jseg_list, json_object_new_int(seg->as[i]));
+
           len += snprintf (str_buf + len, str_size - len, "%u", seg->as[i]);
           
           if (i < (seg->length - 1))
             len += snprintf (str_buf + len, str_size - len, "%c", seperator);
         }
+
+      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", 
@@ -596,6 +631,9 @@ aspath_make_str_count (struct aspath *as)
   as->str = str_buf;
   as->str_len = len;
 
+  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;
 }
 
@@ -604,6 +642,13 @@ aspath_str_update (struct aspath *as)
 {
   if (as->str)
     XFREE (MTYPE_AS_STR, as->str);
+
+  if (as->json)
+    {
+      json_object_free(as->json);
+      as->json = NULL;
+    }
+
   aspath_make_str_count (as);
 }
 
@@ -637,6 +682,7 @@ 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);
@@ -675,6 +721,7 @@ aspath_hash_alloc (void *arg)
   new->segments = aspath->segments;
   new->str = aspath->str;
   new->str_len = aspath->str_len;
+  new->json = aspath->json;
 
   return new;
 }
@@ -1239,6 +1286,7 @@ aspath_remove_private_asns (struct aspath *aspath)
 
   new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
 
+  new->json = NULL;
   new_seg = NULL;
   last_new_seg = NULL;
   seg = aspath->segments;
@@ -1628,7 +1676,11 @@ aspath_reconcile_as4 ( struct aspath *aspath, struct aspath *as4path)
     }
   
   if (!hops)
-   return aspath_dup (as4path);
+    {
+      newpath = aspath_dup (as4path);
+      aspath_str_update(newpath);
+      return newpath;
+    }
   
   if ( BGP_DEBUG(as4, AS4))
     zlog_debug("[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now",
index ec2df042fd4264c42221f94d8afcd81095651e00..faf3bc8eaf21b86445887df7f7639326c12d6817 100644 (file)
@@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifndef _QUAGGA_BGP_ASPATH_H
 #define _QUAGGA_BGP_ASPATH_H
 
+#include "lib/json.h"
+
 /* AS path segment type.  */
 #define AS_SET                       1
 #define AS_SEQUENCE                  2
@@ -63,6 +65,9 @@ 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;
index f1997bd9ce3e5b988d4cfd56540d8b249ad8a06c..19e4954e163c828db591044bf5bbf7f631dba9dc 100644 (file)
@@ -44,6 +44,13 @@ community_free (struct community *com)
     XFREE (MTYPE_COMMUNITY_VAL, com->val);
   if (com->str)
     XFREE (MTYPE_COMMUNITY_STR, com->str);
+
+  if (com->json)
+    {
+      json_object_free(com->json);
+      com->json = NULL;
+    }
+
   XFREE (MTYPE_COMMUNITY, com);
 }
 
@@ -170,6 +177,7 @@ community_uniq_sort (struct community *com)
     return NULL;
   
   new = community_new ();;
+  new->json = NULL;
   
   for (i = 0; i < com->size; i++)
     {
@@ -194,8 +202,8 @@ community_uniq_sort (struct community *com)
    0xFFFFFF03      "local-AS"
 
    For other values, "AS:VAL" format is used.  */
-static char *
-community_com2str  (struct community *com)
+static void
+set_community_string  (struct community *com)
 {
   int i;
   char *str;
@@ -205,16 +213,25 @@ community_com2str  (struct community *com)
   u_int32_t comval;
   u_int16_t as;
   u_int16_t val;
+  json_object *json_community_list = NULL;
+  json_object *json_string = NULL;
 
   if (!com)
     return NULL;
   
+  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';
-      return str;
+
+      json_object_string_add(com->json, "string", "");
+      json_object_object_add(com->json, "list", json_community_list);
+      com->str = str;
+      return;
     }
 
   /* Memory allocation is time consuming work.  So we calculate
@@ -266,30 +283,42 @@ community_com2str  (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);
          break;
        case COMMUNITY_NO_EXPORT:
          strcpy (pnt, "no-export");
          pnt += strlen ("no-export");
+          json_string = json_object_new_string("no-export");
+          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("no-advertise");
+          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("local-AS");
+          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);
          pnt += strlen (pnt);
          break;
        }
     }
   *pnt = '\0';
 
-  return str;
+  json_object_string_add(com->json, "string", str);
+  json_object_object_add(com->json, "list", json_community_list);
+  com->str = str;
 }
 
 /* Intern communities attribute.  */
@@ -314,7 +343,7 @@ community_intern (struct community *com)
 
   /* Make string.  */
   if (! find->str)
-    find->str = community_com2str (find);
+    set_community_string (find);
 
   return find;
 }
@@ -383,9 +412,9 @@ community_str (struct community *com)
 {
   if (!com)
     return NULL;
-  
+
   if (! com->str)
-    com->str = community_com2str (com);
+    set_community_string (com);
   return com->str;
 }
 
@@ -599,7 +628,10 @@ community_str2com (const char *str)
        case community_token_no_advertise:
        case community_token_local_as:
          if (com == NULL)
-           com = community_new();
+            {
+              com = community_new();
+              com->json = NULL;
+            }
          community_add_val (com, val);
          break;
        case community_token_unknown:
index c73dab3045623fb77849055963e7830813954a93..257f7767b46a0791c9f5c00c0ce9955f55bffccd 100644 (file)
@@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifndef _QUAGGA_BGP_COMMUNITY_H
 #define _QUAGGA_BGP_COMMUNITY_H
 
+#include "lib/json.h"
+
 /* Communities attribute.  */
 struct community 
 {
@@ -33,6 +35,9 @@ struct community
   /* Communities value.  */
   u_int32_t *val;
 
+  /* Communities as a json object */
+  json_object *json;
+
   /* String of community attribute.  This sring is used by vty output
      and expanded community-list for regular expression match.  */
   char *str;
index 6df3911978fe510d7b0823aaae50c4cc7836ca2c..fad3ea3c77621c5e7b33b396a0f590b84fcbf491 100644 (file)
@@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 #include <zebra.h>
 #include <math.h>
-#include <json/json.h>
 
 #include "prefix.h"
 #include "memory.h"
@@ -587,8 +586,6 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
   time_t t_now, t_diff;
   char timebuf[BGP_UPTIME_LEN];
   int penalty;
-  json_object *json_int;
-  json_object *json_string;
 
   if (!binfo->extra)
     return;
@@ -608,20 +605,16 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
 
   if (json_path)
     {
-      json_int = json_object_new_int(penalty);
-      json_object_object_add(json_path, "dampening-penalty", json_int);
-
-      json_int = json_object_new_int(bdi->flap);
-      json_object_object_add(json_path, "dampening-flap-count", json_int);
-
-      json_string = json_object_new_string(peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
-      json_object_object_add(json_path, "dampening-flap-period", json_string);
+      json_object_int_add(json_path, "dampening-penalty", penalty);
+      json_object_int_add(json_path, "dampening-flap-count", bdi->flap);
+      json_object_string_add(json_path, "dampening-flap-period",
+                              peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
           && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
         {
-          json_string = json_object_new_string(bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
-          json_object_object_add(json_path, "dampening-reuse-in", json_string);
+          json_object_string_add(json_path, "dampening-reuse-in",
+                                 bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
         }
     }
   else
index 9d4fcb332dea901ae48029938d18763fe44babf8..31c6c307ad0cd1cc81a330d5fd4baa94e0ed197b 100644 (file)
@@ -21,7 +21,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifndef _QUAGGA_BGP_DAMP_H
 #define _QUAGGA_BGP_DAMP_H
 
-#include <json/json.h>
+#include "lib/json.h"
 
 /* Structure maintained on a per-route basis. */
 struct bgp_damp_info
index 6ef857284e0585c4df5e39c4a16c5ca2eb89dd27..185218f7297e8d072054d00be497d11f163a88b9 100644 (file)
@@ -21,8 +21,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifndef _QUAGGA_BGP_OPEN_H
 #define _QUAGGA_BGP_OPEN_H
 
-#include <json/json.h>
-
 /* Standard header for capability TLV */
 struct capability_header
 {
index e8925011250268c27d24a449e2c59762e93bcab6..bc203d4400b8cd5c0a64aef98db6d750a5a59226 100644 (file)
@@ -19,7 +19,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
 #include <zebra.h>
-#include <json/json.h>
 
 #include "prefix.h"
 #include "linklist.h"
@@ -6509,44 +6508,41 @@ static void
 route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo,
                             json_object *json_path)
 {
-  json_object *json_boolean_true;
-
   if (json_path)
     {
-      json_boolean_true = json_object_new_boolean(1);
 
       /* Route status display. */
       if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
-        json_object_object_add(json_path, "removed", json_boolean_true);
+        json_object_boolean_true_add(json_path, "removed");
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
-        json_object_object_add(json_path, "stale", json_boolean_true);
+        json_object_boolean_true_add(json_path, "stale");
 
       if (binfo->extra && binfo->extra->suppress)
-        json_object_object_add(json_path, "suppressed", json_boolean_true);
+        json_object_boolean_true_add(json_path, "suppressed");
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) &&
                ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
-        json_object_object_add(json_path, "valid", json_boolean_true);
+        json_object_boolean_true_add(json_path, "valid");
 
       /* Selected */
       if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
-        json_object_object_add(json_path, "history", json_boolean_true);
+        json_object_boolean_true_add(json_path, "history");
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
-        json_object_object_add(json_path, "damped", json_boolean_true);
+        json_object_boolean_true_add(json_path, "damped");
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
-        json_object_object_add(json_path, "bestpath", json_boolean_true);
+        json_object_boolean_true_add(json_path, "bestpath");
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH))
-        json_object_object_add(json_path, "multipath", json_boolean_true);
+        json_object_boolean_true_add(json_path, "multipath");
 
       /* Internal route. */
       if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
-        json_object_object_add(json_path, "internal", json_boolean_true);
+        json_object_string_add(json_path, "path-from", "internal");
       else
-        json_object_object_add(json_path, "external", json_boolean_true);
+        json_object_string_add(json_path, "path-from", "external");
 
       return;
     }
@@ -6590,14 +6586,13 @@ route_vty_out (struct vty *vty, struct prefix *p,
                json_object *json_paths)
 {
   struct attr *attr;
-  json_object *json_path;
-  json_object *json_int;
-  json_object *json_string;
+  json_object *json_path = NULL;
+  json_object *json_nexthops = NULL;
+  json_object *json_nexthop_global = NULL;
+  json_object *json_nexthop_ll = NULL;
 
   if (json_paths)
     json_path = json_object_new_object();
-  else
-    json_path = NULL;
 
   /* short status lead text */
   route_vty_short_status_out (vty, binfo, json_path);
@@ -6622,16 +6617,15 @@ route_vty_out (struct vty *vty, struct prefix *p,
        {
           if (json_paths)
             {
+              json_nexthop_global = json_object_new_object();
+
              if (safi == SAFI_MPLS_VPN)
-                {
-                  json_string = json_object_new_string(inet_ntoa (attr->extra->mp_nexthop_global_in));
-                  json_object_object_add(json_path, "nexthop-global", json_string);
-                }
+                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
-                {
-                  json_string = json_object_new_string(inet_ntoa (attr->nexthop));
-                  json_object_object_add(json_path, "nexthop-global", json_string);
-                }
+                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
+
+              json_object_string_add(json_nexthop_global, "afi", "ipv4");
+              json_object_boolean_true_add(json_nexthop_global, "used");
             }
           else
             {
@@ -6652,8 +6646,33 @@ route_vty_out (struct vty *vty, struct prefix *p,
 
           if (json_paths)
             {
-              json_string = json_object_new_string(inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, buf, BUFSIZ));
-              json_object_object_add(json_path, "nexthop-global", json_string);
+              json_nexthop_global = json_object_new_object();
+              json_object_string_add(json_nexthop_global, "ip",
+                                     inet_ntop (AF_INET6,
+                                                &attr->extra->mp_nexthop_global,
+                                                buf, BUFSIZ));
+              json_object_string_add(json_nexthop_global, "afi", "ipv6");
+              json_object_string_add(json_nexthop_global, "scope", "global");
+
+              /* We display both LL & GL if both have been received */
+              if ((attr->extra->mp_nexthop_len == 32) || (binfo->peer->conf_if))
+                {
+                  json_nexthop_ll = json_object_new_object();
+                  json_object_string_add(json_nexthop_ll, "ip",
+                                         inet_ntop (AF_INET6,
+                                                    &attr->extra->mp_nexthop_local,
+                                                    buf, BUFSIZ));
+                  json_object_string_add(json_nexthop_ll, "afi", "ipv6");
+                  json_object_string_add(json_nexthop_ll, "scope", "link-local");
+
+                  if (IPV6_ADDR_CMP (&attr->extra->mp_nexthop_global,
+                                     &attr->extra->mp_nexthop_local) != 0)
+                    json_object_boolean_true_add(json_nexthop_ll, "used");
+                  else
+                    json_object_boolean_true_add(json_nexthop_global, "used");
+                }
+              else
+                json_object_boolean_true_add(json_nexthop_global, "used");
             }
           else
             {
@@ -6672,10 +6691,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
       /* MED/Metric */
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
         if (json_paths)
-          {
-            json_int = json_object_new_int(attr->med);
-            json_object_object_add(json_path, "med", json_int);
-          }
+          json_object_int_add(json_path, "med", attr->med);
         else
          vty_out (vty, "%10u", attr->med);
       else
@@ -6685,10 +6701,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
       /* Local Pref */
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
         if (json_paths)
-          {
-            json_int = json_object_new_int(attr->local_pref);
-            json_object_object_add(json_path, "localpref", json_int);
-          }
+          json_object_int_add(json_path, "localpref", attr->local_pref);
         else
          vty_out (vty, "%7u", attr->local_pref);
       else
@@ -6698,11 +6711,9 @@ route_vty_out (struct vty *vty, struct prefix *p,
       if (json_paths)
         {
           if (attr->extra)
-            json_int = json_object_new_int(attr->extra->weight);
+            json_object_int_add(json_path, "weight", attr->extra->weight);
           else
-            json_int = json_object_new_int(0);
-
-          json_object_object_add(json_path, "weight", json_int);
+            json_object_int_add(json_path, "weight", 0);
         }
       else
         vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
@@ -6711,31 +6722,35 @@ route_vty_out (struct vty *vty, struct prefix *p,
       if (attr->aspath)
         {
           if (json_paths)
-            {
-             if (!attr->aspath->str || !attr->aspath->segments)
-                json_string = json_object_new_string("Local");
-              else
-                json_string = json_object_new_string(attr->aspath->str);
-              json_object_object_add(json_path, "aspath", json_string);
-            }
+            json_object_string_add(json_path, "aspath", attr->aspath->str);
           else
-            {
-              aspath_print_vty (vty, "%s", attr->aspath, " ");
-            }
+            aspath_print_vty (vty, "%s", attr->aspath, " ");
         }
 
       /* Print origin */
       if (json_paths)
-        {
-          json_string = json_object_new_string(bgp_origin_str[attr->origin]);
-          json_object_object_add(json_path, "origin", json_string);
-        }
+        json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]);
       else
         vty_out (vty, "%s", bgp_origin_str[attr->origin]);
     }
 
   if (json_paths)
-    json_object_array_add(json_paths, json_path);
+    {
+      if (json_nexthop_global || json_nexthop_ll)
+        {
+          json_nexthops = json_object_new_array();
+
+          if (json_nexthop_global)
+            json_object_array_add(json_nexthops, json_nexthop_global);
+
+          if (json_nexthop_ll)
+            json_object_array_add(json_nexthops, json_nexthop_ll);
+
+          json_object_object_add(json_path, "nexthops", json_nexthops);
+        }
+
+      json_object_array_add(json_paths, json_path);
+    }
   else
     vty_out (vty, "%s", VTY_NEWLINE);
 }  
@@ -6981,19 +6996,23 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
 #ifdef HAVE_CLOCK_MONOTONIC
   time_t tbuf;
 #endif
-  json_object *json_int;
-  json_object *json_string;
-  json_object *json_path = NULL;
-  json_object *json_boolean_false;
-  json_object *json_boolean_true = NULL;
+  json_object *json_bestpath = NULL;
   json_object *json_cluster_list = NULL;
+  json_object *json_cluster_list_list = NULL;
+  json_object *json_ext_community = NULL;
+  json_object *json_last_update = NULL;
+  json_object *json_nexthop_global = NULL;
+  json_object *json_nexthop_ll = NULL;
+  json_object *json_nexthops = NULL;
+  json_object *json_path = NULL;
+  json_object *json_peer = NULL;
+  json_object *json_string = NULL;
 
   if (json_paths)
     {
       json_path = json_object_new_object();
-      json_boolean_false = json_object_new_boolean(0);
-      json_boolean_true = json_object_new_boolean(1);
-      json_cluster_list = json_object_new_array();
+      json_peer = json_object_new_object();
+      json_nexthop_global = json_object_new_object();
     }
 
   attr = binfo->attr;
@@ -7003,32 +7022,24 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       /* Line1 display AS-path, Aggregator */
       if (attr->aspath)
        {
-          if (!json_paths)
-           vty_out (vty, "  ");
-
-          if (!attr->aspath->segments)
-            {
-              if (json_paths)
-                json_string = json_object_new_string("Local");
-              else
-               vty_out (vty, "Local");
-            }
-         else
+          if (json_paths)
+           {
+            json_object_lock(attr->aspath->json);
+            json_object_object_add(json_path, "aspath", attr->aspath->json);
+           }
+          else
             {
-              if (json_paths)
-                json_string = json_object_new_string(attr->aspath->str);
+              if (attr->aspath->segments)
+                aspath_print_vty (vty, "  %s", attr->aspath, "");
               else
-               aspath_print_vty (vty, "%s", attr->aspath, "");
+                vty_out (vty, "  Local");
             }
-
-            if (json_paths)
-              json_object_object_add(json_path, "aspath", json_string);
        }
 
       if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
         {
           if (json_paths)
-            json_object_object_add(json_path, "removed", json_boolean_true);
+            json_object_boolean_true_add(json_path, "removed");
           else
             vty_out (vty, ", (removed)");
         }
@@ -7036,7 +7047,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
         {
           if (json_paths)
-            json_object_object_add(json_path, "stale", json_boolean_true);
+            json_object_boolean_true_add(json_path, "stale");
           else
            vty_out (vty, ", (stale)");
         }
@@ -7045,10 +7056,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_int = json_object_new_int(attr->extra->aggregator_as);
-              json_string = json_object_new_string(inet_ntoa (attr->extra->aggregator_addr));
-              json_object_object_add(json_path, "aggregator-as", json_int);
-              json_object_object_add(json_path, "aggregator-id", json_string);
+              json_object_int_add(json_path, "aggregator-as", attr->extra->aggregator_as);
+              json_object_string_add(json_path, "aggregator-id", inet_ntoa (attr->extra->aggregator_addr));
             }
           else
             {
@@ -7061,7 +7070,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
         {
           if (json_paths)
-            json_object_object_add(json_path, "rxed-from-rr-client", json_boolean_true);
+            json_object_boolean_true_add(json_path, "rxed-from-rr-client");
           else
            vty_out (vty, ", (Received from a RR-client)");
         }
@@ -7069,7 +7078,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
         {
           if (json_paths)
-            json_object_object_add(json_path, "rxed-from-rs-client", json_boolean_true);
+            json_object_boolean_true_add(json_path, "rxed-from-rs-client");
           else
            vty_out (vty, ", (Received from a RS-client)");
         }
@@ -7077,14 +7086,14 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
         {
           if (json_paths)
-            json_object_object_add(json_path, "dampening-history-entry", json_boolean_true);
+            json_object_boolean_true_add(json_path, "dampening-history-entry");
           else
            vty_out (vty, ", (history entry)");
         }
       else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
         {
           if (json_paths)
-            json_object_object_add(json_path, "dampening-suppressed", json_boolean_true);
+            json_object_boolean_true_add(json_path, "dampening-suppressed");
           else
            vty_out (vty, ", (suppressed due to dampening)");
         }
@@ -7093,26 +7102,27 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         vty_out (vty, "%s", VTY_NEWLINE);
          
       /* Line2 display Next-hop, Neighbor, Router-id */
+      /* Display the nexthop */
       if (p->family == AF_INET
           && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
        {
           if (safi == SAFI_MPLS_VPN)
             {
               if (json_paths)
-                json_string = json_object_new_string(inet_ntoa (attr->extra->mp_nexthop_global_in));
+                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
                vty_out (vty, "    %s", inet_ntoa (attr->extra->mp_nexthop_global_in));
             }
           else
             {
               if (json_paths)
-                json_string = json_object_new_string(inet_ntoa (attr->nexthop));
+                json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
               else
                vty_out (vty, "    %s", inet_ntoa (attr->nexthop));
             }
 
           if (json_paths)
-            json_object_object_add(json_path, "nexthop-global", json_string);
+            json_object_string_add(json_nexthop_global, "afi", "ipv4");
        }
 #ifdef HAVE_IPV6
       else
@@ -7120,9 +7130,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
          assert (attr->extra);
           if (json_paths)
             {
-              json_string = json_object_new_string(inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
-                                                          buf, INET6_ADDRSTRLEN));
-              json_object_object_add(json_path, "nexthop-global", json_string);
+              json_object_string_add(json_nexthop_global, "ip",
+                                     inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
+                                                buf, INET6_ADDRSTRLEN));
+              json_object_string_add(json_nexthop_global, "afi", "ipv6");
+              json_object_string_add(json_nexthop_global, "scope", "global");
             }
           else
             {
@@ -7133,119 +7145,105 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
        }
 #endif /* HAVE_IPV6 */
 
-      if (binfo->peer == bgp->peer_self)
-       {
 
-          if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
+      /* Display the IGP cost or 'inaccessible' */
+      if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
+        {
+          if (json_paths)
+            json_object_boolean_false_add(json_nexthop_global, "accessible");
+          else
+            vty_out (vty, " (inaccessible)");
+        }
+      else
+        {
+          if (binfo->extra && binfo->extra->igpmetric)
             {
               if (json_paths)
-                json_string = json_object_new_string("0.0.0.0");
+                json_object_int_add(json_nexthop_global, "metric", binfo->extra->igpmetric);
               else
-               vty_out (vty, " from 0.0.0.0 ");
+                vty_out (vty, " (metric %u)", binfo->extra->igpmetric);
             }
+
+          /* IGP cost is 0, display this only for json */
           else
             {
               if (json_paths)
-                json_string = json_object_new_string("::");
-              else
-               vty_out (vty, " from :: ");
+                json_object_int_add(json_nexthop_global, "metric", 0);
             }
 
           if (json_paths)
-            {
-              json_object_object_add(json_path, "peer-id", json_string);
-              json_string = json_object_new_string(inet_ntoa(bgp->router_id));
-              json_object_object_add(json_path, "peer-router-id", json_string);
-              json_object_object_add(json_path, "nexthop-global-accessible",
-                                     json_boolean_true);
-            }
-          else
-            {
-             vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
-            }
-       }
-      else
+            json_object_boolean_true_add(json_nexthop_global, "accessible");
+        }
+
+      /* Display peer "from" output */
+      /* This path was originated locally */
+      if (binfo->peer == bgp->peer_self)
        {
-         if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
+
+          if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
             {
               if (json_paths)
-                json_object_object_add(json_path, "nexthop-global-accessible", json_boolean_false);
+                json_object_string_add(json_peer, "peer-id", "0.0.0.0");
               else
-               vty_out (vty, " (inaccessible)");
+               vty_out (vty, " from 0.0.0.0 ");
             }
-         else if (binfo->extra && binfo->extra->igpmetric)
+          else
             {
               if (json_paths)
-                {
-                  json_int = json_object_new_int(binfo->extra->igpmetric);
-                  json_object_object_add(json_path, "nexthop-global-igp-cost", json_int);
-                  json_object_object_add(json_path, "nexthop-global-accessible", json_boolean_true);
-                }
+                json_object_string_add(json_peer, "peer-id", "::");
               else
-                {
-                 vty_out (vty, " (metric %u)", binfo->extra->igpmetric);
-                }
+               vty_out (vty, " from :: ");
             }
 
-          /* IGP cost to nexthop is 0 */
+          if (json_paths)
+            json_object_string_add(json_peer, "router-id", inet_ntoa(bgp->router_id));
           else
-            if (json_paths)
-              json_object_object_add(json_path, "nexthop-global-accessible", json_boolean_true);
+           vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
+       }
+
+      /* We RXed this path from one of our peers */
+      else
+       {
 
           if (json_paths)
             {
-              json_string = json_object_new_string(sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
-              json_object_object_add(json_path, "peer-id", json_string);
-             if (binfo->peer->hostname)
-               {
-                 json_string = json_object_new_string(binfo->peer->hostname);
-                 json_object_object_add(json_path, "peer-hostname", json_string);
-               }
-             if (binfo->peer->domainname)
-               {
-                 json_string = json_object_new_string(binfo->peer->domainname);
-                 json_object_object_add(json_path, "peer-domainname", json_string);
-               }
+              json_object_string_add(json_peer, "peer-id", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
+              json_object_string_add(json_peer, "router-id", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
+
+              if (binfo->peer->hostname)
+                json_object_string_add(json_peer, "hostname", binfo->peer->hostname);
+
+              if (binfo->peer->domainname)
+                json_object_string_add(json_peer, "domainname", binfo->peer->domainname);
+
               if (binfo->peer->conf_if)
-                {
-                  json_string = json_object_new_string(binfo->peer->conf_if);
-                  json_object_object_add(json_path, "peer-interface", json_string);
-                }
+                json_object_string_add(json_peer, "interface", binfo->peer->conf_if);
             }
           else
             {
               if (binfo->peer->conf_if)
-               {
-                 if (binfo->peer->hostname &&
-                     bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
-                   vty_out (vty, " from %s(%s)", binfo->peer->hostname,
-                            binfo->peer->conf_if);
-                 else
-                   vty_out (vty, " from %s", binfo->peer->conf_if);
-               }
+                {
+                  if (binfo->peer->hostname &&
+                      bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+                    vty_out (vty, " from %s(%s)", binfo->peer->hostname,
+                             binfo->peer->conf_if);
+                  else
+                    vty_out (vty, " from %s", binfo->peer->conf_if);
+                }
               else
-               {
-                 if (binfo->peer->hostname &&
-                     bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
-                   vty_out (vty, " from %s(%s)", binfo->peer->hostname,
-                            binfo->peer->host);
-                 else
-                   vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
-               }
-
-             if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
-               vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
-             else
-               vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
-            }
+                {
+                  if (binfo->peer->hostname &&
+                      bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+                    vty_out (vty, " from %s(%s)", binfo->peer->hostname,
+                             binfo->peer->host);
+                  else
+                    vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
+                }
 
-          /* Always encode the peer's router-id in the json output.  We will
-           * include the originator-id later if this is a reflected route.
-           */
-          if (json_paths)
-            {
-              json_string = json_object_new_string(inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
-              json_object_object_add(json_path, "peer-router-id", json_string);
+              if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+                vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
+              else
+                vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
             }
        }
 
@@ -7253,16 +7251,20 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         vty_out (vty, "%s", VTY_NEWLINE);
 
 #ifdef HAVE_IPV6
-      /* display nexthop local */
+      /* display the link-local nexthop */
       if (attr->extra && attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
        {
           if (json_paths)
             {
-              json_string = json_object_new_string(inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
-                                                              buf, INET6_ADDRSTRLEN));
-              json_object_object_add(json_path, "nexthop-local", json_string);
-              json_object_object_add(json_path, "nexthop-local-accessible", json_boolean_true);
-              json_object_object_add(json_path, "nexthop-local-used", json_boolean_true);
+              json_nexthop_ll = json_object_new_object();
+              json_object_string_add(json_nexthop_ll, "ip",
+                                     inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
+                                                buf, INET6_ADDRSTRLEN));
+              json_object_string_add(json_nexthop_ll, "afi", "ipv6");
+              json_object_string_add(json_nexthop_ll, "scope", "link-local");
+
+              json_object_boolean_true_add(json_nexthop_ll, "accessible");
+              json_object_boolean_true_add(json_nexthop_ll, "used");
             }
           else
             {
@@ -7272,152 +7274,108 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
                       VTY_NEWLINE);
             }
        }
+      /* If we do not have a link-local nexthop then we must flag the global as "used" */
+      else
+        {
+          if (json_paths)
+            json_object_boolean_true_add(json_nexthop_global, "used");
+        }
 #endif /* HAVE_IPV6 */
 
       /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */
       if (json_paths)
-        {
-          json_string = json_object_new_string(bgp_origin_long_str[attr->origin]);
-          json_object_object_add(json_path, "origin", json_string);
-        }
+        json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]);
       else
-        {
-          vty_out (vty, "      Origin %s", bgp_origin_long_str[attr->origin]);
-        }
+        vty_out (vty, "      Origin %s", bgp_origin_long_str[attr->origin]);
          
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
         {
           if (json_paths)
-            {
-              json_int = json_object_new_int(attr->med);
-              json_object_object_add(json_path, "med", json_int);
-            }
+            json_object_int_add(json_path, "med", attr->med);
           else
-            {
-             vty_out (vty, ", metric %u", attr->med);
-            }
+           vty_out (vty, ", metric %u", attr->med);
         }
          
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
         {
           if (json_paths)
-            {
-              json_int = json_object_new_int(attr->local_pref);
-              json_object_object_add(json_path, "localpref", json_int);
-            }
+            json_object_int_add(json_path, "localpref", attr->local_pref);
           else
-            {
-             vty_out (vty, ", localpref %u", attr->local_pref);
-            }
+           vty_out (vty, ", localpref %u", attr->local_pref);
         }
       else
         {
           if (json_paths)
-            {
-              json_int = json_object_new_int(bgp->default_local_pref);
-              json_object_object_add(json_path, "localpref", json_int);
-            }
+            json_object_int_add(json_path, "localpref", bgp->default_local_pref);
           else
-            {
-             vty_out (vty, ", localpref %u", bgp->default_local_pref);
-            }
+           vty_out (vty, ", localpref %u", bgp->default_local_pref);
         }
 
       if (attr->extra && attr->extra->weight != 0)
         {
           if (json_paths)
-            {
-              json_int = json_object_new_int(attr->extra->weight);
-              json_object_object_add(json_path, "weight", json_int);
-            }
+            json_object_int_add(json_path, "weight", attr->extra->weight);
           else
-            {
-             vty_out (vty, ", weight %u", attr->extra->weight);
-            }
+           vty_out (vty, ", weight %u", attr->extra->weight);
         }
 
       if (attr->extra && attr->extra->tag != 0)
         {
           if (json_paths)
-            {
-              json_int = json_object_new_int(attr->extra->tag);
-              json_object_object_add(json_path, "tag", json_int);
-            }
+            json_object_int_add(json_path, "tag", attr->extra->tag);
           else
-            {
-              vty_out (vty, ", tag %d", attr->extra->tag);
-            }
+            vty_out (vty, ", tag %d", attr->extra->tag);
         }
        
       if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
         {
           if (json_paths)
-            json_object_object_add(json_path, "valid", json_boolean_false);
+            json_object_boolean_false_add(json_path, "valid");
           else
            vty_out (vty, ", invalid");
         }
       else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
         {
           if (json_paths)
-            json_object_object_add(json_path, "valid", json_boolean_true);
+            json_object_boolean_true_add(json_path, "valid");
           else
            vty_out (vty, ", valid");
         }
 
       if (binfo->peer != bgp->peer_self)
        {
-         if (binfo->peer->as == binfo->peer->local_as)
+          if (binfo->peer->as == binfo->peer->local_as)
             {
               if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
                 {
                   if (json_paths)
-                    {
-                      json_string = json_object_new_string("confed-internal");
-                      json_object_object_add(json_path, "peer-type", json_string);
-                    }
+                    json_object_string_add(json_peer, "type", "confed-internal");
                   else
-                    {
-                      vty_out (vty, ", confed-internal");
-                    }
+                    vty_out (vty, ", confed-internal");
                 }
               else
                 {
                   if (json_paths)
-                    {
-                      json_string = json_object_new_string("internal");
-                      json_object_object_add(json_path, "peer-type", json_string);
-                    }
+                    json_object_string_add(json_peer, "type", "internal");
                   else
-                    {
-                      vty_out (vty, ", internal");
-                    }
+                    vty_out (vty, ", internal");
                 }
             }
-         else
+          else
             {
               if (bgp_confederation_peers_check(bgp, binfo->peer->as))
                 {
                   if (json_paths)
-                    {
-                      json_string = json_object_new_string("confed-external");
-                      json_object_object_add(json_path, "peer-type", json_string);
-                    }
+                    json_object_string_add(json_peer, "type", "confed-external");
                   else
-                    {
-                     vty_out (vty, ", confed-external");
-                    }
+                    vty_out (vty, ", confed-external");
                 }
               else
                 {
                   if (json_paths)
-                    {
-                      json_string = json_object_new_string("external");
-                      json_object_object_add(json_path, "peer-type", json_string);
-                    }
+                    json_object_string_add(json_peer, "type", "external");
                   else
-                    {
-                     vty_out (vty, ", external");
-                    }
+                    vty_out (vty, ", external");
                 }
             }
        }
@@ -7425,8 +7383,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_object_object_add(json_path, "aggregated", json_boolean_true);
-              json_object_object_add(json_path, "local", json_boolean_true);
+              json_object_boolean_true_add(json_path, "aggregated");
+              json_object_boolean_true_add(json_path, "local");
             }
           else
             {
@@ -7436,7 +7394,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       else if (binfo->type != ZEBRA_ROUTE_BGP)
         {
           if (json_paths)
-            json_object_object_add(json_path, "sourced", json_boolean_true);
+            json_object_boolean_true_add(json_path, "sourced");
           else
            vty_out (vty, ", sourced");
         }
@@ -7444,8 +7402,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_object_object_add(json_path, "sourced", json_boolean_true);
-              json_object_object_add(json_path, "local", json_boolean_true);
+              json_object_boolean_true_add(json_path, "sourced");
+              json_object_boolean_true_add(json_path, "local");
             }
           else
             {
@@ -7456,7 +7414,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
         {
           if (json_paths)
-            json_object_object_add(json_path, "atomic-aggregate", json_boolean_true);
+            json_object_boolean_true_add(json_path, "atomic-aggregate");
           else
            vty_out (vty, ", atomic-aggregate");
         }
@@ -7466,7 +7424,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
           bgp_info_mpath_count (binfo)))
         {
           if (json_paths)
-            json_object_object_add(json_path, "multipath", json_boolean_true);
+            json_object_boolean_true_add(json_path, "multipath");
           else
            vty_out (vty, ", multipath");
         }
@@ -7474,7 +7432,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
         {
           if (json_paths)
-            json_object_object_add(json_path, "bestpath", json_boolean_true);
+            {
+              json_bestpath = json_object_new_object();
+              json_object_boolean_true_add(json_bestpath, "overall");
+              json_object_object_add(json_path, "bestpath", json_bestpath);
+            }
           else
            vty_out (vty, ", best");
         }
@@ -7487,8 +7449,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_string = json_object_new_string(attr->community->str);
-              json_object_object_add(json_path, "community", json_string);
+              json_object_lock(attr->community->json);
+              json_object_object_add(json_path, "community", attr->community->json);
             }
           else
             {
@@ -7502,8 +7464,9 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_string = json_object_new_string(attr->extra->ecommunity->str);
-              json_object_object_add(json_path, "extended-community", json_string);
+              json_ext_community = json_object_new_object();
+              json_object_string_add(json_ext_community, "string", attr->extra->ecommunity->str);
+              json_object_object_add(json_path, "extended-community", json_ext_community);
             }
           else
             {
@@ -7520,15 +7483,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
          if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
             {
               if (json_paths)
-                {
-                  json_string = json_object_new_string(inet_ntoa (attr->extra->originator_id));
-                  json_object_object_add(json_path, "originator-id", json_string);
-                }
+                json_object_string_add(json_path, "originator-id", inet_ntoa (attr->extra->originator_id));
               else
-                {
-                 vty_out (vty, "      Originator: %s",
-                          inet_ntoa (attr->extra->originator_id));
-                }
+               vty_out (vty, "      Originator: %s",
+                        inet_ntoa (attr->extra->originator_id));
             }
 
          if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
@@ -7537,11 +7495,21 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
 
               if (json_paths)
                 {
+                  json_cluster_list = json_object_new_object();
+                  json_cluster_list_list = json_object_new_array();
+
                  for (i = 0; i < attr->extra->cluster->length / 4; i++)
                     {
                       json_string = json_object_new_string(inet_ntoa (attr->extra->cluster->list[i]));
-                      json_object_array_add(json_cluster_list, json_string);
+                      json_object_array_add(json_cluster_list_list, json_string);
                     }
+
+                  /* struct cluster_list does not have "str" variable like
+                   * aspath and community do.  Add this someday if someone
+                   * asks for it.
+                  json_object_string_add(json_cluster_list, "string", attr->extra->cluster->str);
+                   */
+                  json_object_object_add(json_cluster_list, "list", json_cluster_list_list);
                   json_object_object_add(json_path, "cluster-list", json_cluster_list);
                 }
               else
@@ -7568,11 +7536,8 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
         {
           if (json_paths)
             {
-              json_int = json_object_new_int(binfo->addpath_rx_id);
-              json_object_object_add(json_path, "addpath-rx-id", json_int);
-
-              json_int = json_object_new_int(binfo->addpath_tx_id);
-              json_object_object_add(json_path, "addpath-tx-id", json_int);
+              json_object_int_add(json_path, "addpath-rx-id", binfo->addpath_rx_id);
+              json_object_int_add(json_path, "addpath-tx-id", binfo->addpath_tx_id);
             }
           else
             {
@@ -7586,24 +7551,48 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
 #ifdef HAVE_CLOCK_MONOTONIC
       tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
       if (json_paths)
-        json_string = json_object_new_string(ctime(&tbuf));
+        {
+          json_last_update = json_object_new_object();
+          json_object_int_add(json_last_update, "epoch", tbuf);
+          json_object_string_add(json_last_update, "string", ctime(&tbuf));
+          json_object_object_add(json_path, "last-update", json_last_update);
+        }
       else
         vty_out (vty, "      Last update: %s", ctime(&tbuf));
 #else
       if (json_paths)
-        json_string = json_object_new_string(ctime(&binfo->uptime));
+        {
+          json_last_update = json_object_new_object();
+          json_object_int_add(json_last_update, "epoch", tbuf);
+          json_object_string_add(json_last_update, "string", ctime(&binfo->uptime));
+          json_object_object_add(json_path, "last-update", json_last_update);
+        }
       else
         vty_out (vty, "      Last update: %s", ctime(&binfo->uptime));
 #endif /* HAVE_CLOCK_MONOTONIC */
-      if (json_paths)
-        json_object_object_add(json_path, "last-update", json_string);
     }
 
   /* We've constructed the json object for this path, add it to the json
    * array of paths
    */
   if (json_paths)
-    json_object_array_add(json_paths, json_path);
+    {
+      if (json_nexthop_global || json_nexthop_ll)
+        {
+          json_nexthops = json_object_new_array();
+
+          if (json_nexthop_global)
+            json_object_array_add(json_nexthops, json_nexthop_global);
+
+          if (json_nexthop_ll)
+            json_object_array_add(json_nexthops, json_nexthop_ll);
+
+          json_object_object_add(json_path, "nexthops", json_nexthops);
+        }
+
+      json_object_object_add(json_path, "peer", json_peer);
+      json_object_array_add(json_paths, json_path);
+    }
   else
     vty_out (vty, "%s", VTY_NEWLINE);
 }
@@ -7653,21 +7642,15 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router
   struct prefix *p;
   char buf[BUFSIZ];
   char buf2[BUFSIZ];
-  json_object *json;
-  json_object *json_int;
-  json_object *json_paths;
-  json_object *json_routes;
-  json_object *json_string;
+  json_object *json = NULL;
+  json_object *json_paths = NULL;
+  json_object *json_routes = NULL;
 
   if (use_json)
     {
       json = json_object_new_object();
-      json_int = json_object_new_int(table->version);
-      json_object_object_add(json, "table-version", json_int);
-
-      json_string = json_object_new_string(inet_ntoa (*router_id));
-      json_object_object_add(json, "router-id", json_string);
-
+      json_object_int_add(json, "table-version", table->version);
+      json_object_string_add(json, "router-id", inet_ntoa (*router_id));
       json_routes = json_object_new_object();
     }
 
@@ -7889,9 +7872,7 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router
     {
       json_object_object_add(json, "routes", json_routes);
       vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
-
-      // Recursively free all json structures
-      json_object_put(json);
+      json_object_free(json);
     }
   else
     {
@@ -7951,20 +7932,15 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
   int no_advertise = 0;
   int local_as = 0;
   int first = 0;
-  json_object *json_string;
-  json_object *json_int;
   json_object *json_adv_to = NULL;
+  json_object *json_peer = NULL;
 
   p = &rn->p;
 
   if (json)
     {
-      json_string = json_object_new_string(inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN));
-      json_object_object_add(json, "prefix", json_string);
-
-      json_int = json_object_new_int(p->prefixlen);
-      json_object_object_add(json, "prefixlen", json_int);
-      json_adv_to = json_object_new_array();
+      json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN));
+      json_object_int_add(json, "prefixlen", p->prefixlen);
     }
   else
     {
@@ -8027,23 +8003,24 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
        {
           if (json)
             {
+              /* 'advertised-to' is a dictionary of peers we have advertised this
+               * prefix too.  The key is the peer's IP or swpX, the value is the
+               * hostname if we know it and "" if not.
+               */
+              json_peer = json_object_new_object();
+
              if (peer->hostname)
-               {
-                  json_string = json_object_new_string(peer->hostname);
-                  json_object_array_add(json_adv_to, json_string);
+                json_object_string_add(json_peer, "hostname", peer->hostname);
+
+              if (!json_adv_to)
+                json_adv_to = json_object_new_object();
 
-                 /* TODO: Have to add domain name here too */
-               }
               if (peer->conf_if)
-                {
-                  json_string = json_object_new_string(peer->conf_if);
-                  json_object_array_add(json_adv_to, json_string);
-                }
+                json_object_object_add(json_adv_to, peer->conf_if, json_peer);
               else
-                {
-                  json_string = json_object_new_string(sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
-                  json_object_array_add(json_adv_to, json_string);
-                }
+                json_object_object_add(json_adv_to,
+                                       sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN),
+                                       json_peer);
             }
           else
             {
@@ -8101,8 +8078,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
   struct bgp_node *rm;
   struct bgp_info *ri;
   struct bgp_table *table;
-  json_object *json;
-  json_object *json_paths;
+  json_object *json = NULL;
+  json_object *json_paths = NULL;
 
   /* Check IP address argument. */
   ret = str2prefix (ip_str, &match);
@@ -8119,11 +8096,6 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
       json = json_object_new_object();
       json_paths = json_object_new_array();
     }
-  else
-    {
-      json = NULL;
-      json_paths = NULL;
-    }
 
   if (safi == SAFI_MPLS_VPN)
     {
@@ -8202,9 +8174,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
         json_object_object_add(json, "paths", json_paths);
 
       vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
-
-      // Recursively free all json structures
-      json_object_put(json);
+      json_object_free(json);
     }
   else
     {
index 124ac4ea1d8be8e4c3c23b5079289a0fba5b0f2d..865a24d3ff5a0bcc756bcc7ea82b1858ee2997ce 100644 (file)
@@ -21,7 +21,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifndef _QUAGGA_BGP_ROUTE_H
 #define _QUAGGA_BGP_ROUTE_H
 
-#include <json/json.h>
+#include "lib/json.h"
 #include "queue.h"
 #include "bgp_table.h"
 
index e46dfa705bb07adbe2f31282584352c3541edea3..71c9ba1b9419c6a45af1f4e6030bb6893c2ee192 100644 (file)
@@ -8453,11 +8453,8 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
   char timebuf[BGP_UPTIME_LEN], dn_flag[2];
   int len;
   json_object *json = NULL;
-  json_object *json_int = NULL;
-  json_object *json_string = NULL;
   json_object *json_peer = NULL;
   json_object *json_peers = NULL;
-  json_object *json_boolean_true = NULL;
 
   /* Header string for each address family. */
   static char header[] = "Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd";
@@ -8465,8 +8462,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
   if (use_json)
     {
       json = json_object_new_object();
-      json_peers = json_object_new_array();
-      json_boolean_true = json_object_new_boolean(1);
+      json_peers = json_object_new_object();
     }
 
   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
@@ -8484,11 +8480,8 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
               /* Usage summary and header */
               if (use_json)
                 {
-                  json_string = json_object_new_string(inet_ntoa (bgp->router_id));
-                  json_object_object_add(json, "router-id", json_string);
-
-                  json_int = json_object_new_int(bgp->as);
-                  json_object_object_add(json, "as", json_int);
+                  json_object_string_add(json, "router-id", inet_ntoa (bgp->router_id));
+                  json_object_int_add(json, "as", bgp->as);
                 }
               else
                 {
@@ -8501,36 +8494,28 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
                 {
                   if (use_json)
                     {
-                      json_int = json_object_new_int(bgp->v_update_delay);
-                      json_object_object_add(json, "update-delay-limit", json_int);
+                      json_object_int_add(json, "update-delay-limit", bgp->v_update_delay);
 
                       if (bgp->v_update_delay != bgp->v_establish_wait)
-                        {
-                          json_int = json_object_new_int(bgp->v_establish_wait);
-                          json_object_object_add(json, "update-delay-establish-wait", json_int);
-                        }
+                        json_object_int_add(json, "update-delay-establish-wait", bgp->v_establish_wait);
 
                       if (bgp_update_delay_active(bgp))
                         {
-                          json_string = json_object_new_string(bgp->update_delay_begin_time);
-                          json_object_object_add(json, "update-delay-first-neighbor", json_string);
-                          json_object_object_add(json, "update-delay-in-progress", json_boolean_true);
+                          json_object_string_add(json, "update-delay-first-neighbor", bgp->update_delay_begin_time);
+                          json_object_boolean_true_add(json, "update-delay-in-progress");
                         }
                       else
                         {
                           if (bgp->update_delay_over)
                             {
-                              json_string = json_object_new_string(bgp->update_delay_begin_time);
-                              json_object_object_add(json, "update-delay-first-neighbor", json_string);
-
-                              json_string = json_object_new_string(bgp->update_delay_end_time);
-                              json_object_object_add(json, "update-delay-bestpath-resumed", json_string);
-
-                              json_string = json_object_new_string(bgp->update_delay_zebra_resume_time);
-                              json_object_object_add(json, "update-delay-zebra-update-resume", json_string);
-
-                              json_string = json_object_new_string(bgp->update_delay_peers_resume_time);
-                              json_object_object_add(json, "update-delay-peer-update-resume", json_string);
+                              json_object_string_add(json, "update-delay-first-neighbor",
+                                                     bgp->update_delay_begin_time);
+                              json_object_string_add(json, "update-delay-bestpath-resumed",
+                                                     bgp->update_delay_end_time);
+                              json_object_string_add(json, "update-delay-zebra-update-resume",
+                                                     bgp->update_delay_zebra_resume_time);
+                              json_object_string_add(json, "update-delay-peer-update-resume",
+                                                     bgp->update_delay_peers_resume_time);
                             }
                         }
                     }
@@ -8568,43 +8553,34 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
               if (use_json)
                 {
                   if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active)
-                    json_object_object_add(json, "max-med-on-startup", json_boolean_true);
+                    json_object_boolean_true_add(json, "max-med-on-startup");
                   if (bgp->v_maxmed_admin)
-                    json_object_object_add(json, "max-med-administrative", json_boolean_true);
+                    json_object_boolean_true_add(json, "max-med-administrative");
 
-                  json_int = json_object_new_int(bgp_table_version(bgp->rib[afi][safi]));
-                  json_object_object_add(json, "table-version", json_int);
+                  json_object_int_add(json, "table-version", bgp_table_version(bgp->rib[afi][safi]));
 
                   ents = bgp_table_count (bgp->rib[afi][safi]);
-                  json_int = json_object_new_int(ents);
-                  json_object_object_add(json, "rib-count", json_int);
-                  json_int = json_object_new_int(ents * sizeof (struct bgp_node));
-                  json_object_object_add(json, "rib-memory", json_int);
+                  json_object_int_add(json, "rib-count", ents);
+                  json_object_int_add(json, "rib-memory", ents * sizeof (struct bgp_node));
 
                   ents = listcount (bgp->peer);
-                  json_int = json_object_new_int(ents);
-                  json_object_object_add(json, "peer-count", json_int);
-                  json_int = json_object_new_int(ents * sizeof (struct peer));
-                  json_object_object_add(json, "peer-memory", json_int);
+                  json_object_int_add(json, "peer-count", ents);
+                  json_object_int_add(json, "peer-memory", ents * sizeof (struct peer));
 
                   if ((ents = listcount (bgp->rsclient)))
                     {
-                      json_int = json_object_new_int(ents);
-                      json_object_object_add(json, "rsclient-count", json_int);
-                      json_int = json_object_new_int(ents * sizeof (struct peer));
-                      json_object_object_add(json, "rsclient-memory", json_int);
+                      json_object_int_add(json, "rsclient-count", ents);
+                      json_object_int_add(json, "rsclient-memory", ents * sizeof (struct peer));
                     }
 
                   if ((ents = listcount (bgp->group)))
                     {
-                      json_int = json_object_new_int(ents);
-                      json_object_object_add(json, "peer-group-count", json_int);
-                      json_int = json_object_new_int(ents * sizeof (struct peer_group));
-                      json_object_object_add(json, "peer-group-memory", json_int);
+                      json_object_int_add(json, "peer-group-count", ents);
+                      json_object_int_add(json, "peer-group-memory", ents * sizeof (struct peer_group));
                     }
 
                   if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
-                    json_object_object_add(json, "dampening-enabled", json_boolean_true);
+                    json_object_boolean_true_add(json, "dampening-enabled");
                 }
               else
                 {
@@ -8657,69 +8633,48 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
               json_peer = json_object_new_object();
 
               if (peer_dynamic_neighbor(peer))
-                json_object_object_add(json_peer, "dynamic-peer", json_boolean_true);
-
-              json_string = json_object_new_string(peer->host);
-              json_object_object_add(json_peer, "peer-id", json_string);
+                json_object_boolean_true_add(json_peer, "dynamic-peer");
 
              if (peer->hostname)
-               {
-                 json_string = json_object_new_string(peer->hostname);
-                 json_object_object_add(json_peer, "hostname", json_string);
-               }
+                json_object_string_add(json_peer, "hostname", peer->hostname);
 
              if (peer->domainname)
-               {
-                 json_string = json_object_new_string(peer->domainname);
-                 json_object_object_add(json_peer, "domainname", json_string);
-               }
-
-              json_int = json_object_new_int(peer->as);
-              json_object_object_add(json_peer, "remote-as", json_int);
-
-              json_int = json_object_new_int(4);
-              json_object_object_add(json_peer, "version", json_int);
-
-              json_int = json_object_new_int(peer->open_in + peer->update_in + peer->keepalive_in
-                                             + peer->notify_in + peer->refresh_in
-                                             + peer->dynamic_cap_in);
-              json_object_object_add(json_peer, "msgrcvd", json_int);
-
-              json_int = json_object_new_int(peer->open_out + peer->update_out + peer->keepalive_out
-                                             + peer->notify_out + peer->refresh_out
-                                             + peer->dynamic_cap_out);
-              json_object_object_add(json_peer, "msgsent", json_int);
-
-              json_int = json_object_new_int(peer->version[afi][safi]);
-              json_object_object_add(json_peer, "table-version", json_int);
-
-              json_int = json_object_new_int(peer->obuf->count);
-              json_object_object_add(json_peer, "outq", json_int);
-
-              json_int = json_object_new_int(0);
-              json_object_object_add(json_peer, "inq", json_int);
-
-              json_string = json_object_new_string(peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
-              json_object_object_add(json_peer, "uptime", json_string);
-
-              json_int = json_object_new_int(peer->pcount[afi][safi]);
-              json_object_object_add(json_peer, "prefix-received-count", json_int);
-
-              json_int = json_object_new_int(bgp_adj_out_count(peer, afi, safi));
-              json_object_object_add(json_peer, "prefix-advertised-count", json_int);
+                json_object_string_add(json_peer, "domainname", peer->domainname);
+
+              json_object_int_add(json_peer, "remote-as", peer->as);
+              json_object_int_add(json_peer, "version", 4);
+              json_object_int_add(json_peer, "msgrcvd",
+                                  peer->open_in + peer->update_in + peer->keepalive_in
+                                  + peer->notify_in + peer->refresh_in
+                                  + peer->dynamic_cap_in);
+              json_object_int_add(json_peer, "msgsent",
+                                  peer->open_out + peer->update_out + peer->keepalive_out
+                                  + peer->notify_out + peer->refresh_out
+                                  + peer->dynamic_cap_out);
+
+              json_object_int_add(json_peer, "table-version", peer->version[afi][safi]);
+              json_object_int_add(json_peer, "outq", peer->obuf->count);
+              json_object_int_add(json_peer, "inq", 0);
+              json_object_string_add(json_peer, "uptime",
+                                     peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
+              json_object_int_add(json_peer, "prefix-received-count", peer->pcount[afi][safi]);
+              json_object_int_add(json_peer, "prefix-advertised-count", bgp_adj_out_count(peer, afi, safi));
 
               if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
-                json_string = json_object_new_string("Idle (Admin)");
-
+                json_object_string_add(json_peer, "state", "Idle (Admin)");
               else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
-                json_string = json_object_new_string("Idle (PfxCt)");
-
+                json_object_string_add(json_peer, "state", "Idle (PfxCt)");
               else
-                json_string = json_object_new_string(LOOKUP(bgp_status_msg, peer->status));
+                json_object_string_add(json_peer, "state", LOOKUP(bgp_status_msg, peer->status));
 
-              json_object_object_add(json_peer, "state", json_string);
+              if (peer->conf_if)
+                json_object_string_add(json_peer, "id-type", "interface");
+              else if (peer->su.sa.sa_family == AF_INET)
+                json_object_string_add(json_peer, "id-type", "ipv4");
+              else if (peer->su.sa.sa_family == AF_INET6)
+                json_object_string_add(json_peer, "id-type", "ipv6");
 
-              json_object_array_add(json_peers, json_peer);
+              json_object_object_add(json_peers, peer->host, json_peer);
             }
           else
             {
@@ -8756,7 +8711,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
                        0,
                        peer->obuf->count);
 
-              vty_out (vty, "%8s",
+              vty_out (vty, "%-8s",
                        peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
 
               if (peer->status == Established)
@@ -8779,16 +8734,11 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
     {
       json_object_object_add(json, "peers", json_peers);
 
-      json_int = json_object_new_int(count);
-      json_object_object_add(json, "total-peers", json_int);
-
-      json_int = json_object_new_int(dn_count);
-      json_object_object_add(json, "dynamic-peers", json_int);
+      json_object_int_add(json, "total-peers", count);
+      json_object_int_add(json, "dynamic-peers", dn_count);
 
       vty_out (vty, "%s%s", json_object_to_json_string(json), VTY_NEWLINE);
-
-      // Recursively free all json structures
-      json_object_put(json);
+      json_object_free(json);
     }
   else
     {
index ee7b046202974a0804ef17b4ffaee496d714b8c2..ba23f18dd1a7abfa151ab1fae8153cc999c33441 100644 (file)
@@ -5818,7 +5818,7 @@ peer_uptime (time_t uptime2, char *buf, size_t len)
   /* If there is no connection has been done before print `never'. */
   if (uptime2 == 0)
     {
-      snprintf (buf, len, "never   ");
+      snprintf (buf, len, "never");
       return buf;
     }
 
index f64972dd0d3eea4dbb3f1dfcc33f09f2003358af..d32ac1f7ab51dcbdc23fbeb08d52ba26e40aca90 100644 (file)
@@ -12,7 +12,7 @@ libzebra_la_SOURCES = \
        sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
        filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
        zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
-       sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c
+       sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c
 
 BUILT_SOURCES = memtypes.h route_types.h gitversion.h
 
@@ -27,7 +27,7 @@ pkginclude_HEADERS = \
        str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
        plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
        privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
-       workqueue.h route_types.h libospf.h nexthop.h
+       workqueue.h route_types.h libospf.h nexthop.h json.h
 
 EXTRA_DIST = \
        regex.c regex-gnu.h \
diff --git a/lib/json.c b/lib/json.c
new file mode 100644 (file)
index 0000000..07b70e4
--- /dev/null
@@ -0,0 +1,59 @@
+/* json-c wrapper
+ * Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "lib/json.h"
+
+void
+json_object_string_add(struct json_object* obj, const char *key,
+                       const char *s)
+{
+  json_object_object_add(obj, key, json_object_new_string(s));
+}
+
+void
+json_object_int_add(struct json_object* obj, const char *key, int32_t i)
+{
+  json_object_object_add(obj, key, json_object_new_int(i));
+}
+
+void
+json_object_boolean_false_add(struct json_object* obj, const char *key)
+{
+  json_object_object_add(obj, key, json_object_new_boolean(0));
+}
+
+void
+json_object_boolean_true_add(struct json_object* obj, const char *key)
+{
+  json_object_object_add(obj, key, json_object_new_boolean(1));
+}
+
+struct json_object*
+json_object_lock(struct json_object *obj)
+{
+  return json_object_get(obj);
+}
+
+void
+json_object_free(struct json_object *obj)
+{
+  json_object_put(obj);
+}
diff --git a/lib/json.h b/lib/json.h
new file mode 100644 (file)
index 0000000..e9b1976
--- /dev/null
@@ -0,0 +1,38 @@
+/* json-c wrapper
+ * Copyright (C) 2015 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _QUAGGA_JSON_H
+#define _QUAGGA_JSON_H
+
+#include <json/json.h>
+
+extern void json_object_string_add(struct json_object* obj, const char *key,
+                                   const char *s);
+extern void json_object_int_add(struct json_object* obj, const char *key,
+                                int32_t i);
+extern void json_object_boolean_false_add(struct json_object* obj,
+                                          const char *key);
+extern void json_object_boolean_true_add(struct json_object* obj,
+                                         const char *key);
+extern struct json_object* json_object_lock(struct json_object *obj);
+extern void json_object_free(struct json_object *obj);
+
+#endif /* _QUAGGA_JSON_H */