]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Add JSON output for `show rpki prefix` and other show commands 11304/head
authorDonatas Abraitis <donatas@opensourcerouting.org>
Mon, 30 May 2022 06:05:34 +0000 (09:05 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Mon, 30 May 2022 08:04:12 +0000 (11:04 +0300)
```
spine1-debian-11# sh rpki prefix 192.168.100.1/32
Prefix                                   Prefix Length  Origin-AS
192.168.100.1                               32 -  32        47583
spine1-debian-11# sh rpki prefix 192.168.100.1/32 json
{
  "prefixes":[
    {
      "prefix":"192.168.100.1",
      "prefixLenMin":32,
      "prefixLenMax":32,
      "asn":47583
    }
  ]
}
```

```
spine1-debian-11# sh rpki as-number 47583 json
{
  "prefixes":[
    {
      "prefix":"192.168.100.1",
      "prefixLenMin":32,
      "prefixLenMax":32,
      "asn":47583
    },
    {
      "prefix":"2606:4700:7000::",
      "prefixLenMin":48,
      "prefixLenMax":48,
      "asn":47583
    }
  ],
  "ipv4PrefixCount":1,
  "ipv6PrefixCount":1
}
spine1-debian-11# sh rpki as-number 47583
RPKI/RTR prefix table
Prefix                                   Prefix Length  Origin-AS
192.168.100.1                               32 -  32        47583
2606:4700:7000::                            48 -  48        47583
Number of IPv4 Prefixes: 1
Number of IPv6 Prefixes: 1
```

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_rpki.c
doc/user/rpki.rst

index c28b81a41366e5d63248434f0ffdd8128cade1cb..1c7dc7cb0ae0b01a22136a7c953bac3f41f09904 100644 (file)
@@ -98,13 +98,14 @@ struct rpki_for_each_record_arg {
        struct vty *vty;
        unsigned int *prefix_amount;
        as_t as;
+       json_object *json;
 };
 
 static int start(void);
 static void stop(void);
 static int reset(bool force);
 static struct rtr_mgr_group *get_connected_group(void);
-static void print_prefix_table(struct vty *vty);
+static void print_prefix_table(struct vty *vty, json_object *json);
 static void install_cli_commands(void);
 static int config_write(struct vty *vty);
 static int config_on_exit(struct vty *vty);
@@ -121,7 +122,8 @@ static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
 static struct cache *find_cache(const uint8_t preference);
 static int add_tcp_cache(const char *host, const char *port,
                         const uint8_t preference, const char *bindaddr);
-static void print_record(const struct pfx_record *record, struct vty *vty);
+static void print_record(const struct pfx_record *record, struct vty *vty,
+                        json_object *json);
 static bool is_synchronized(void);
 static bool is_running(void);
 static bool is_stopping(void);
@@ -274,13 +276,27 @@ static struct cache *find_cache(const uint8_t preference)
        return NULL;
 }
 
-static void print_record(const struct pfx_record *record, struct vty *vty)
+static void print_record(const struct pfx_record *record, struct vty *vty,
+                        json_object *json)
 {
        char ip[INET6_ADDRSTRLEN];
+       json_object *json_record = NULL;
 
        lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
-       vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len,
-               record->max_len, record->asn);
+
+       if (!json) {
+               vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len,
+                       record->max_len, record->asn);
+       } else {
+               json_record = json_object_new_object();
+               json_object_string_add(json_record, "prefix", ip);
+               json_object_int_add(json_record, "prefixLenMin",
+                                   record->min_len);
+               json_object_int_add(json_record, "prefixLenMax",
+                                   record->max_len);
+               json_object_int_add(json_record, "asn", record->asn);
+               json_object_array_add(json, json_record);
+       }
 }
 
 static void print_record_by_asn(const struct pfx_record *record, void *data)
@@ -290,7 +306,7 @@ static void print_record_by_asn(const struct pfx_record *record, void *data)
 
        if (record->asn == arg->as) {
                (*arg->prefix_amount)++;
-               print_record(record, vty);
+               print_record(record, vty, arg->json);
        }
 }
 
@@ -301,7 +317,7 @@ static void print_record_cb(const struct pfx_record *record, void *data)
 
        (*arg->prefix_amount)++;
 
-       print_record(record, vty);
+       print_record(record, vty, arg->json);
 }
 
 static struct rtr_mgr_group *get_groups(void)
@@ -653,25 +669,36 @@ static struct rtr_mgr_group *get_connected_group(void)
        return rtr_mgr_get_first_group(rtr_config);
 }
 
-static void print_prefix_table_by_asn(struct vty *vty, as_t as)
+static void print_prefix_table_by_asn(struct vty *vty, as_t as,
+                                     json_object *json)
 {
        unsigned int number_of_ipv4_prefixes = 0;
        unsigned int number_of_ipv6_prefixes = 0;
        struct rtr_mgr_group *group = get_connected_group();
        struct rpki_for_each_record_arg arg;
+       json_object *json_records = NULL;
 
        arg.vty = vty;
        arg.as = as;
+       arg.json = NULL;
 
        if (!group) {
-               vty_out(vty, "Cannot find a connected group.\n");
+               if (!json)
+                       vty_out(vty, "Cannot find a connected group.\n");
                return;
        }
 
        struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
 
-       vty_out(vty, "RPKI/RTR prefix table\n");
-       vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS");
+       if (!json) {
+               vty_out(vty, "RPKI/RTR prefix table\n");
+               vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length",
+                       "Origin-AS");
+       } else {
+               json_records = json_object_new_array();
+               json_object_object_add(json, "prefixes", json_records);
+               arg.json = json_records;
+       }
 
        arg.prefix_amount = &number_of_ipv4_prefixes;
        pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
@@ -679,27 +706,51 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as)
        arg.prefix_amount = &number_of_ipv6_prefixes;
        pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
 
-       vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
-       vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
+       if (!json) {
+               vty_out(vty, "Number of IPv4 Prefixes: %u\n",
+                       number_of_ipv4_prefixes);
+               vty_out(vty, "Number of IPv6 Prefixes: %u\n",
+                       number_of_ipv6_prefixes);
+       } else {
+               json_object_int_add(json, "ipv4PrefixCount",
+                                   number_of_ipv4_prefixes);
+               json_object_int_add(json, "ipv6PrefixCount",
+                                   number_of_ipv6_prefixes);
+       }
+
+       if (json)
+               vty_json(vty, json);
 }
 
-static void print_prefix_table(struct vty *vty)
+static void print_prefix_table(struct vty *vty, json_object *json)
 {
        struct rpki_for_each_record_arg arg;
 
        unsigned int number_of_ipv4_prefixes = 0;
        unsigned int number_of_ipv6_prefixes = 0;
        struct rtr_mgr_group *group = get_connected_group();
+       json_object *json_records = NULL;
 
        arg.vty = vty;
+       arg.json = NULL;
 
-       if (!group)
+       if (!group) {
+               if (!json)
+                       vty_out(vty, "Cannot find a connected group.\n");
                return;
+       }
 
        struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
 
-       vty_out(vty, "RPKI/RTR prefix table\n");
-       vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS");
+       if (!json) {
+               vty_out(vty, "RPKI/RTR prefix table\n");
+               vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length",
+                       "Origin-AS");
+       } else {
+               json_records = json_object_new_array();
+               json_object_object_add(json, "prefixes", json_records);
+               arg.json = json_records;
+       }
 
        arg.prefix_amount = &number_of_ipv4_prefixes;
        pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
@@ -707,8 +758,20 @@ static void print_prefix_table(struct vty *vty)
        arg.prefix_amount = &number_of_ipv6_prefixes;
        pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
 
-       vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
-       vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
+       if (!json) {
+               vty_out(vty, "Number of IPv4 Prefixes: %u\n",
+                       number_of_ipv4_prefixes);
+               vty_out(vty, "Number of IPv6 Prefixes: %u\n",
+                       number_of_ipv6_prefixes);
+       } else {
+               json_object_int_add(json, "ipv4PrefixCount",
+                                   number_of_ipv4_prefixes);
+               json_object_int_add(json, "ipv6PrefixCount",
+                                   number_of_ipv6_prefixes);
+       }
+
+       if (json)
+               vty_json(vty, json);
 }
 
 static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
@@ -1187,49 +1250,70 @@ DEFPY (no_rpki_cache,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_rpki_prefix_table,
+DEFPY (show_rpki_prefix_table,
        show_rpki_prefix_table_cmd,
-       "show rpki prefix-table",
+       "show rpki prefix-table [json$uj]",
        SHOW_STR
        RPKI_OUTPUT_STRING
-       "Show validated prefixes which were received from RPKI Cache\n")
+       "Show validated prefixes which were received from RPKI Cache\n"
+       JSON_STR)
 {
-       if (is_synchronized())
-               print_prefix_table(vty);
-       else
-               vty_out(vty, "No connection to RPKI cache server.\n");
+       struct json_object *json = NULL;
+
+       if (!is_synchronized()) {
+               if (!uj)
+                       vty_out(vty, "No connection to RPKI cache server.\n");
+               return CMD_WARNING;
+       }
 
+       if (uj)
+               json = json_object_new_object();
+
+       print_prefix_table(vty, json);
        return CMD_SUCCESS;
 }
 
-DEFPY (show_rpki_as_number, show_rpki_as_number_cmd,
-      "show rpki as-number (1-4294967295)$by_asn",
-      SHOW_STR RPKI_OUTPUT_STRING
-      "Lookup by ASN in prefix table\n"
-      "AS Number\n")
+DEFPY (show_rpki_as_number,
+       show_rpki_as_number_cmd,
+       "show rpki as-number (1-4294967295)$by_asn [json$uj]",
+       SHOW_STR
+       RPKI_OUTPUT_STRING
+       "Lookup by ASN in prefix table\n"
+       "AS Number\n"
+       JSON_STR)
 {
+       struct json_object *json = NULL;
+
        if (!is_synchronized()) {
-               vty_out(vty, "No Connection to RPKI cache server.\n");
+               if (!uj)
+                       vty_out(vty, "No Connection to RPKI cache server.\n");
                return CMD_WARNING;
        }
 
-       print_prefix_table_by_asn(vty, by_asn);
+       if (uj)
+               json = json_object_new_object();
+
+       print_prefix_table_by_asn(vty, by_asn, json);
        return CMD_SUCCESS;
 }
 
 DEFPY (show_rpki_prefix,
        show_rpki_prefix_cmd,
-       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
+       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]",
        SHOW_STR
        RPKI_OUTPUT_STRING
        "Lookup IP prefix and optionally ASN in prefix table\n"
        "IPv4 prefix\n"
        "IPv6 prefix\n"
-       "AS Number\n")
+       "AS Number\n"
+       JSON_STR)
 {
+       json_object *json = NULL;
+       json_object *json_records = NULL;
 
        if (!is_synchronized()) {
-               vty_out(vty, "No Connection to RPKI cache server.\n");
+               if (!uj)
+                       vty_out(vty, "No Connection to RPKI cache server.\n");
                return CMD_WARNING;
        }
 
@@ -1241,7 +1325,8 @@ DEFPY (show_rpki_prefix,
        memcpy(addr_str, prefix_str, addr_len);
 
        if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
-               vty_out(vty, "Invalid IP prefix\n");
+               if (!json)
+                       vty_out(vty, "Invalid IP prefix\n");
                return CMD_WARNING;
        }
 
@@ -1252,21 +1337,35 @@ DEFPY (show_rpki_prefix,
        if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
                                 asn, &addr, prefix->prefixlen, &result)
            != PFX_SUCCESS) {
-               vty_out(vty, "Prefix lookup failed\n");
+               if (!json)
+                       vty_out(vty, "Prefix lookup failed\n");
                return CMD_WARNING;
        }
 
-       vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS");
+       if (uj)
+               json = json_object_new_object();
+
+       if (!json) {
+               vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length",
+                       "Origin-AS");
+       } else {
+               json_records = json_object_new_array();
+               json_object_object_add(json, "prefixes", json_records);
+       }
+
        for (size_t i = 0; i < match_count; ++i) {
                const struct pfx_record *record = &matches[i];
 
                if (record->max_len >= prefix->prefixlen
                    && ((asn != 0 && (uint32_t)asn == record->asn)
                        || asn == 0)) {
-                       print_record(&matches[i], vty);
+                       print_record(&matches[i], vty, json_records);
                }
        }
 
+       if (json)
+               vty_json(vty, json);
+
        return CMD_SUCCESS;
 }
 
index ece788d9e3c42a7c0d96b4c6c00a7fb2321cecb7..e5bd59d9cb25652fc5c09c57300efe0f3a9d79ff 100644 (file)
@@ -200,17 +200,17 @@ Debugging
 Displaying RPKI
 ---------------
 
-.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)]
+.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [json]
 
    Display validated prefixes received from the cache servers filtered
    by the specified prefix.
 
-.. clicmd:: show rpki as-number ASN
+.. clicmd:: show rpki as-number ASN [json]
 
    Display validated prefixes received from the cache servers filtered
    by ASN.
 
-.. clicmd:: show rpki prefix-table
+.. clicmd:: show rpki prefix-table [json]
 
    Display all validated prefix to origin AS mappings/records which have been
    received from the cache servers and stored in the router. Based on this data,