#include "linklist.h"
#include "memory.h"
+#include "command.h"
#include "vector.h"
#include "prefix.h"
#include "vty.h"
#include "libfrr.h"
#include "lib_errors.h"
#include "table.h"
+#include "json.h"
DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map");
DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name");
}
/* show route-map */
-static void vty_show_route_map_entry(struct vty *vty, struct route_map *map)
+static void vty_show_route_map_entry(struct vty *vty, struct route_map *map,
+ json_object *json)
{
struct route_map_index *index;
struct route_map_rule *rule;
-
- vty_out(vty, "route-map: %s Invoked: %" PRIu64 " Optimization: %s Processed Change: %s\n",
- map->name, map->applied - map->applied_clear,
- map->optimization_disabled ? "disabled" : "enabled",
- map->to_be_processed ? "true" : "false");
+ json_object *json_rmap = NULL;
+ json_object *json_rules = NULL;
+
+ if (json) {
+ json_rmap = json_object_new_object();
+ json_object_object_add(json, map->name, json_rmap);
+
+ json_rules = json_object_new_array();
+ json_object_int_add(json_rmap, "invoked",
+ map->applied - map->applied_clear);
+ json_object_boolean_add(json_rmap, "disabledOptimization",
+ map->optimization_disabled);
+ json_object_boolean_add(json_rmap, "processedChange",
+ map->to_be_processed);
+ json_object_object_add(json_rmap, "rules", json_rules);
+ } else {
+ vty_out(vty,
+ "route-map: %s Invoked: %" PRIu64
+ " Optimization: %s Processed Change: %s\n",
+ map->name, map->applied - map->applied_clear,
+ map->optimization_disabled ? "disabled" : "enabled",
+ map->to_be_processed ? "true" : "false");
+ }
for (index = map->head; index; index = index->next) {
- vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n",
- route_map_type_str(index->type), index->pref,
- index->applied - index->applied_clear);
-
- /* Description */
- if (index->description)
- vty_out(vty, " Description:\n %s\n",
- index->description);
-
- /* Match clauses */
- vty_out(vty, " Match clauses:\n");
- for (rule = index->match_list.head; rule; rule = rule->next)
- vty_out(vty, " %s %s\n", rule->cmd->str,
- rule->rule_str);
-
- vty_out(vty, " Set clauses:\n");
- for (rule = index->set_list.head; rule; rule = rule->next)
- vty_out(vty, " %s %s\n", rule->cmd->str,
- rule->rule_str);
-
- /* Call clause */
- vty_out(vty, " Call clause:\n");
- if (index->nextrm)
- vty_out(vty, " Call %s\n", index->nextrm);
-
- /* Exit Policy */
- vty_out(vty, " Action:\n");
- if (index->exitpolicy == RMAP_GOTO)
- vty_out(vty, " Goto %d\n", index->nextpref);
- else if (index->exitpolicy == RMAP_NEXT)
- vty_out(vty, " Continue to next entry\n");
- else if (index->exitpolicy == RMAP_EXIT)
- vty_out(vty, " Exit routemap\n");
+ if (json) {
+ json_object *json_rule;
+ json_object *json_matches;
+ json_object *json_sets;
+ char action[BUFSIZ] = {};
+
+ json_rule = json_object_new_object();
+ json_object_array_add(json_rules, json_rule);
+
+ json_object_int_add(json_rule, "sequenceNumber",
+ index->pref);
+ json_object_string_add(json_rule, "type",
+ route_map_type_str(index->type));
+ json_object_int_add(json_rule, "invoked",
+ index->applied
+ - index->applied_clear);
+
+ /* Description */
+ if (index->description)
+ json_object_string_add(json_rule, "description",
+ index->description);
+
+ /* Match clauses */
+ json_matches = json_object_new_array();
+ json_object_object_add(json_rule, "matchClauses",
+ json_matches);
+ for (rule = index->match_list.head; rule;
+ rule = rule->next) {
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "%s %s",
+ rule->cmd->str, rule->rule_str);
+ json_array_string_add(json_matches, buf);
+ }
+
+ /* Set clauses */
+ json_sets = json_object_new_array();
+ json_object_object_add(json_rule, "setClauses",
+ json_sets);
+ for (rule = index->set_list.head; rule;
+ rule = rule->next) {
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "%s %s",
+ rule->cmd->str, rule->rule_str);
+ json_array_string_add(json_sets, buf);
+ }
+
+ /* Call clause */
+ if (index->nextrm)
+ json_object_string_add(json_rule, "callClause",
+ index->nextrm);
+
+ /* Exit Policy */
+ if (index->exitpolicy == RMAP_GOTO)
+ snprintf(action, sizeof(action), "Goto %d",
+ index->nextpref);
+ else if (index->exitpolicy == RMAP_NEXT)
+ snprintf(action, sizeof(action),
+ "Continue to next entry");
+ else if (index->exitpolicy == RMAP_EXIT)
+ snprintf(action, sizeof(action),
+ "Exit routemap");
+ if (action[0] != '\0')
+ json_object_string_add(json_rule, "action",
+ action);
+ } else {
+ vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n",
+ route_map_type_str(index->type), index->pref,
+ index->applied - index->applied_clear);
+
+ /* Description */
+ if (index->description)
+ vty_out(vty, " Description:\n %s\n",
+ index->description);
+
+ /* Match clauses */
+ vty_out(vty, " Match clauses:\n");
+ for (rule = index->match_list.head; rule;
+ rule = rule->next)
+ vty_out(vty, " %s %s\n", rule->cmd->str,
+ rule->rule_str);
+
+ /* Set clauses */
+ vty_out(vty, " Set clauses:\n");
+ for (rule = index->set_list.head; rule;
+ rule = rule->next)
+ vty_out(vty, " %s %s\n", rule->cmd->str,
+ rule->rule_str);
+
+ /* Call clause */
+ vty_out(vty, " Call clause:\n");
+ if (index->nextrm)
+ vty_out(vty, " Call %s\n", index->nextrm);
+
+ /* Exit Policy */
+ vty_out(vty, " Action:\n");
+ if (index->exitpolicy == RMAP_GOTO)
+ vty_out(vty, " Goto %d\n", index->nextpref);
+ else if (index->exitpolicy == RMAP_NEXT)
+ vty_out(vty, " Continue to next entry\n");
+ else if (index->exitpolicy == RMAP_EXIT)
+ vty_out(vty, " Exit routemap\n");
+ }
}
}
return strcmp(m1->name, m2->name);
}
-static int vty_show_route_map(struct vty *vty, const char *name)
+static int vty_show_route_map(struct vty *vty, const char *name, bool use_json)
{
struct route_map *map;
+ json_object *json = NULL;
+ json_object *json_proto = NULL;
- vty_out(vty, "%s:\n", frr_protonameinst);
+ if (use_json) {
+ json = json_object_new_object();
+ json_proto = json_object_new_object();
+ json_object_object_add(json, frr_protonameinst, json_proto);
+ } else
+ vty_out(vty, "%s:\n", frr_protonameinst);
if (name) {
map = route_map_lookup_by_name(name);
if (map) {
- vty_show_route_map_entry(vty, map);
+ vty_show_route_map_entry(vty, map, json_proto);
return CMD_SUCCESS;
- } else {
+ } else if (!use_json) {
vty_out(vty, "%s: 'route-map %s' not found\n",
frr_protonameinst, name);
- return CMD_SUCCESS;
}
} else {
list_sort(maplist, sort_route_map);
for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
- vty_show_route_map_entry(vty, map);
+ vty_show_route_map_entry(vty, map, json_proto);
list_delete(&maplist);
}
+
+ if (use_json) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+
return CMD_SUCCESS;
}
list_sort(maplist, sort_route_map);
for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
- vty_show_route_map_entry(vty, map);
+ vty_show_route_map_entry(vty, map, NULL);
} else {
vty_out(vty, "\n%s: None\n", frr_protonameinst);
}
DEFUN (rmap_show_name,
rmap_show_name_cmd,
- "show route-map [WORD]",
+ "show route-map [WORD] [json]",
SHOW_STR
"route-map information\n"
- "route-map name\n")
+ "route-map name\n"
+ JSON_STR)
{
- int idx_word = 2;
- const char *name = (argc == 3) ? argv[idx_word]->arg : NULL;
- return vty_show_route_map(vty, name);
+ bool uj = use_json(argc, argv);
+ int idx = 0;
+ const char *name = NULL;
+
+ if (argv_find(argv, argc, "WORD", &idx))
+ name = argv[idx]->arg;
+
+ return vty_show_route_map(vty, name, uj);
}
DEFUN (rmap_show_unused,