Skip to content

Commit

Permalink
bgpd: support for json in show bgp ipv4 flowspec commands
Browse files Browse the repository at this point in the history
The json format is returd when requested from the two commands:
- show bgp ipv4 flowspec
- show bgp ipv4 flowspec detail

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed Mar 30, 2018
1 parent e7d78d0 commit d33fc23
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 30 deletions.
2 changes: 1 addition & 1 deletion bgpd/bgp_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -2223,7 +2223,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
bgp_fs_nlri_get_string((unsigned char *)fs->prefix.ptr,
fs->prefix.prefixlen,
return_string,
NLRI_STRING_FORMAT_DEBUG);
NLRI_STRING_FORMAT_DEBUG, NULL);
snprintf(str, size, "FS %s Match{%s}", afi2str(afi),
return_string);
} else
Expand Down
2 changes: 1 addition & 1 deletion bgpd/bgp_flowspec.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
p.u.prefix_flowspec.ptr,
p.u.prefix_flowspec.prefixlen,
return_string,
NLRI_STRING_FORMAT_MIN);
NLRI_STRING_FORMAT_MIN, NULL);
snprintf(ec_string, BGP_FLOWSPEC_NLRI_STRING_MAX,
"EC{none}");
if (attr && attr->ecommunity) {
Expand Down
11 changes: 7 additions & 4 deletions bgpd/bgp_flowspec.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
#ifndef _FRR_BGP_FLOWSPEC_H
#define _FRR_BGP_FLOWSPEC_H

#define NLRI_STRING_FORMAT_LARGE 0
#define NLRI_STRING_FORMAT_DEBUG 1
#define NLRI_STRING_FORMAT_MIN 2
#define NLRI_STRING_FORMAT_LARGE 0
#define NLRI_STRING_FORMAT_DEBUG 1
#define NLRI_STRING_FORMAT_MIN 2
#define NLRI_STRING_FORMAT_JSON 3
#define NLRI_STRING_FORMAT_JSON_SIMPLE 4

#define BGP_FLOWSPEC_NLRI_STRING_MAX 512

Expand All @@ -39,7 +41,8 @@ extern int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
unsigned long *total_cum);

extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char *return_string, int format);
char *return_string, int format,
json_object *json_path);

extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
struct bgp_info *binfo,
Expand Down
3 changes: 2 additions & 1 deletion bgpd/bgp_flowspec_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
enum bgp_flowspec_util_nlri_t {
BGP_FLOWSPEC_VALIDATE_ONLY = 0,
BGP_FLOWSPEC_RETURN_STRING = 1,
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE = 2
BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE = 2,
BGP_FLOWSPEC_RETURN_JSON = 3,
};


Expand Down
108 changes: 88 additions & 20 deletions bgpd/bgp_flowspec_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ static const struct message bgp_flowspec_display_min[] = {

/* Parse FLOWSPEC NLRI*/
void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char *return_string, int format)
char *return_string, int format,
json_object *json_path)
{
uint32_t offset = 0;
int type;
Expand All @@ -90,13 +91,16 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
char extra[2] = "";
char pre_extra[2] = "";
const struct message *bgp_flowspec_display;
enum bgp_flowspec_util_nlri_t type_util;

if (format == NLRI_STRING_FORMAT_LARGE) {
snprintf(pre_extra, sizeof(pre_extra), "\t");
snprintf(extra, sizeof(extra), "\n");
bgp_flowspec_display = bgp_flowspec_display_large;
} else
bgp_flowspec_display = bgp_flowspec_display_min;
/* if needed. type_util can be set to other values */
type_util = BGP_FLOWSPEC_RETURN_STRING;
error = 0;
while (offset < len-1 && error >= 0) {
type = nlri_content[offset];
Expand All @@ -105,12 +109,18 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
case FLOWSPEC_DEST_PREFIX:
case FLOWSPEC_SRC_PREFIX:
ret = bgp_flowspec_ip_address(
BGP_FLOWSPEC_RETURN_STRING,
type_util,
nlri_content+offset,
len - offset,
local_string, &error);
if (ret <= 0)
break;
if (json_path) {
json_object_string_add(json_path,
lookup_msg(bgp_flowspec_display, type, ""),
local_string);
break;
}
FS_STRING_UPDATE(count, ptr, format);
ptr += sprintf(ptr, "%s%s %s%s", pre_extra,
lookup_msg(bgp_flowspec_display, type, ""),
Expand All @@ -122,12 +132,18 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
case FLOWSPEC_SRC_PORT:
case FLOWSPEC_ICMP_TYPE:
case FLOWSPEC_ICMP_CODE:
ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_RETURN_STRING,
ret = bgp_flowspec_op_decode(type_util,
nlri_content+offset,
len - offset,
local_string, &error);
if (ret <= 0)
break;
if (json_path) {
json_object_string_add(json_path,
lookup_msg(bgp_flowspec_display, type, ""),
local_string);
break;
}
FS_STRING_UPDATE(count, ptr, format);
ptr += sprintf(ptr, "%s%s %s%s", pre_extra,
lookup_msg(bgp_flowspec_display,
Expand All @@ -136,12 +152,18 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
break;
case FLOWSPEC_TCP_FLAGS:
ret = bgp_flowspec_tcpflags_decode(
BGP_FLOWSPEC_RETURN_STRING,
type_util,
nlri_content+offset,
len - offset,
local_string, &error);
if (ret <= 0)
break;
if (json_path) {
json_object_string_add(json_path,
lookup_msg(bgp_flowspec_display, type, ""),
local_string);
break;
}
FS_STRING_UPDATE(count, ptr, format);
ptr += sprintf(ptr, "%s%s %s%s", pre_extra,
lookup_msg(bgp_flowspec_display, type, ""),
Expand All @@ -150,12 +172,18 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
case FLOWSPEC_PKT_LEN:
case FLOWSPEC_DSCP:
ret = bgp_flowspec_op_decode(
BGP_FLOWSPEC_RETURN_STRING,
type_util,
nlri_content + offset,
len - offset, local_string,
&error);
if (ret <= 0)
break;
if (json_path) {
json_object_string_add(json_path,
lookup_msg(bgp_flowspec_display, type, ""),
local_string);
break;
}
FS_STRING_UPDATE(count, ptr, format);
ptr += sprintf(ptr, "%s%s %s%s", pre_extra,
lookup_msg(bgp_flowspec_display,
Expand All @@ -164,12 +192,19 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
break;
case FLOWSPEC_FRAGMENT:
ret = bgp_flowspec_fragment_type_decode(
BGP_FLOWSPEC_RETURN_STRING,
type_util,
nlri_content + offset,
len - offset, local_string,
&error);
if (ret <= 0)
break;
if (json_path) {
json_object_string_add(json_path,
lookup_msg(bgp_flowspec_display,
type, ""),
local_string);
break;
}
FS_STRING_UPDATE(count, ptr, format);
ptr += sprintf(ptr, "%s%s %s%s", pre_extra,
lookup_msg(bgp_flowspec_display,
Expand All @@ -191,25 +226,38 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
struct attr *attr;
char return_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
char *s;
json_object *json_nlri_path = NULL;
json_object *json_ecom_path = NULL;
json_object *json_time_path = NULL;
char timebuf[BGP_UPTIME_LEN];

/* Print prefix */
if (p != NULL) {
if (p->family != AF_FLOWSPEC)
return;
if (json_paths) {
if (display == NLRI_STRING_FORMAT_JSON)
json_nlri_path = json_object_new_object();
else
json_nlri_path = json_paths;
}
if (display == NLRI_STRING_FORMAT_LARGE)
vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
binfo->flags);
bgp_fs_nlri_get_string((unsigned char *)
p->u.prefix_flowspec.ptr,
p->u.prefix_flowspec.prefixlen,
return_string,
display);
display,
json_nlri_path);
if (display == NLRI_STRING_FORMAT_LARGE)
vty_out(vty, "%s", return_string);
else if (display == NLRI_STRING_FORMAT_DEBUG)
vty_out(vty, "%s", return_string);
else
else if (display == NLRI_STRING_FORMAT_MIN)
vty_out(vty, " %-30s", return_string);
else if (json_paths && display == NLRI_STRING_FORMAT_JSON)
json_object_array_add(json_paths, json_nlri_path);
}
if (!binfo)
return;
Expand All @@ -222,16 +270,27 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
return;
if (display == NLRI_STRING_FORMAT_LARGE)
vty_out(vty, "\t%s\n", s);
else
else if (display == NLRI_STRING_FORMAT_MIN)
vty_out(vty, "%s", s);
else if (json_paths) {
json_ecom_path = json_object_new_object();
json_object_string_add(json_ecom_path,
"ecomlist", s);
if (display == NLRI_STRING_FORMAT_JSON)
json_object_array_add(json_paths,
json_ecom_path);
}
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
if (display == NLRI_STRING_FORMAT_LARGE) {
char timebuf[BGP_UPTIME_LEN];

vty_out(vty, "\tup for %8s\n",
peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN,
0, NULL));
peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
if (display == NLRI_STRING_FORMAT_LARGE)
vty_out(vty, "\tup for %8s\n", timebuf);
else if (json_paths) {
json_time_path = json_object_new_object();
json_object_string_add(json_time_path,
"time", timebuf);
if (display == NLRI_STRING_FORMAT_JSON)
json_object_array_add(json_paths, json_time_path);
}

}
Expand All @@ -246,26 +305,35 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
struct bgp_node *rn;
unsigned long total_count = 0;
json_object *json_paths = NULL;
int display;
int display = NLRI_STRING_FORMAT_LARGE;

if (type != bgp_show_type_detail)
return CMD_SUCCESS;

display = NLRI_STRING_FORMAT_LARGE;
if (use_json) /* XXX */
return CMD_SUCCESS;
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
if (rn->info == NULL)
continue;
if (use_json) {
json_paths = json_object_new_array();
display = NLRI_STRING_FORMAT_JSON;
}
for (ri = rn->info; ri; ri = ri->next) {
total_count++;
route_vty_out_flowspec(vty, &rn->p,
ri, display,
json_paths);

}
if (use_json) {
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json_paths,
JSON_C_TO_STRING_PRETTY));
json_object_free(json_paths);
json_paths = NULL;
}
}
if (total_count)
if (total_count && !use_json)
vty_out(vty,
"\nDisplayed %ld flowspec entries\n",
total_count);
Expand Down
9 changes: 6 additions & 3 deletions bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -6319,7 +6319,9 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty,
#endif
} else if (p->family == AF_FLOWSPEC) {
route_vty_out_flowspec(vty, p, NULL,
NLRI_STRING_FORMAT_MIN, json);
json ?
NLRI_STRING_FORMAT_JSON_SIMPLE :
NLRI_STRING_FORMAT_MIN, json);
} else {
if (!json)
len = vty_out(
Expand Down Expand Up @@ -6511,9 +6513,10 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
"used");
} else
vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
}
} else if (safi == SAFI_FLOWSPEC) {
/* already done */
/* IPv4 Next Hop */
else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
} else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
if (json_paths) {
json_nexthop_global = json_object_new_object();

Expand Down

0 comments on commit d33fc23

Please sign in to comment.