summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-06-12 16:59:11 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-06-12 16:59:11 +0200
commitf1aa5d8ac823969694430feec02594c6851e596a (patch)
tree09656cc997f2eecd7bbf1a3b930658993f139edc
parentBGP: bestpath needs to prefer confed-external over confed-internal (diff)
downloadfrr-f1aa5d8ac823969694430feec02594c6851e596a.tar.xz
frr-f1aa5d8ac823969694430feec02594c6851e596a.zip
Key changes:
- 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 }
-rw-r--r--bgpd/bgp_aspath.c54
-rw-r--r--bgpd/bgp_aspath.h5
-rw-r--r--bgpd/bgp_community.c48
-rw-r--r--bgpd/bgp_community.h5
-rw-r--r--bgpd/bgp_damp.c19
-rw-r--r--bgpd/bgp_damp.h2
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_route.c638
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_vty.c176
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/json.c59
-rw-r--r--lib/json.h38
14 files changed, 578 insertions, 476 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 04ef87d69..a270d8cd7 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -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",
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index ec2df042f..faf3bc8ea 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -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;
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index f1997bd9c..19e4954e1 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -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:
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index c73dab304..257f7767b 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -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;
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 6df391197..fad3ea3c7 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -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
diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
index 9d4fcb332..31c6c307a 100644
--- a/bgpd/bgp_damp.h
+++ b/bgpd/bgp_damp.h
@@ -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
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 6ef857284..185218f72 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -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
{
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index e89250112..bc203d440 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -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
{
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 124ac4ea1..865a24d3f 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -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"
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index e46dfa705..71c9ba1b9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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
{
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index ee7b04620..ba23f18dd 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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;
}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f64972dd0..d32ac1f7a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -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
index 000000000..07b70e4f0
--- /dev/null
+++ b/lib/json.c
@@ -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
index 000000000..e9b1976b9
--- /dev/null
+++ b/lib/json.h
@@ -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 */