Monitoring via the REST API

flockd supports a REST API to allow monitoring of the Router. The REST API is accessed over HTTP and delivers a JSON payload. The REST API is Read-Only so a connecting client can only query state in the router, never change it. In HTTP terms, by design, only the GET method is supported. The flockc client uses the REST API.

Local Connection within a Router

On router R01 and we use the client to retrieve local state within R01. The JSON is delivered using the REST API via R01's IP loopback address.

flock@R01:~$ flockc ribv4 --prefix
{"ip_net":"0.0.0.0/0","origin":"Kernel","next_hops":[{"intf_id":5,"ip_addr":"192.168.122.1"}]}
{"ip_net":"10.0.1.0/24","origin":"Kernel","next_hops":[{"intf_id":2}]}
{"ip_net":"10.0.2.0/24","origin":"Ospfv2","next_hops":[{"intf_id":2,"ip_addr":"10.0.1.246"}]}
{"ip_net":"10.0.3.0/24","origin":"Kernel","next_hops":[{"intf_id":4}]}
{"ip_net":"10.0.4.0/24","origin":"Kernel","next_hops":[{"intf_id":3}]}

Remote Connection from one Router to another

From R01 we can view information on another router using the REST API. The JSON is delivered via HTTP. The command is the same, except we append the host name / IP Address of the target router.

flock@R01:~$ flockc ribv4 --prefix --host R02
{"ip_net":"0.0.0.0/0","origin":"Ospfv2","next_hops":[{"intf_id":2,"ip_addr":"10.0.1.168"}]}
{"ip_net":"10.0.1.0/24","origin":"Kernel","next_hops":[{"intf_id":2}]}
{"ip_net":"10.0.2.0/24","origin":"Kernel","next_hops":[{"intf_id":3}]}
{"ip_net":"10.0.3.0/24","origin":"Kernel","next_hops":[{"intf_id":4}]}
{"ip_net":"10.0.4.0/24","origin":"Ospfv2","next_hops":[{"intf_id":2,"ip_addr":"10.0.1.168"}]}

Remote Connection from Host to any Router

Now moving to a host H01. We can install only flockc, and we can monitor all routers, without running flockd. NB: This is the flockc package being installed, which only includes the client, not the flockd package which includes the client and the daemon.

flock@H01# dpkg -i flockc_20.4.x_amd64.deb
flock@H01:~$ flockc ribv4 --prefix --host R01
{"ip_net":"0.0.0.0/0","origin":"Kernel","next_hops":[{"intf_id":5,"ip_addr":"192.168.122.1"}]}
...
flock@H01:~$ flockc ribv4 --prefix --host R02
{"ip_net":"0.0.0.0/0","origin":"Ospfv2","next_hops":[{"intf_id":2,"ip_addr":"10.0.1.168"}]}
...

3rd Party Clients

Since the REST API is simply a JSON payload inside HTTP, there are many ways to connect. The Host Operating System can be your choice of Linux, Windows, Mac, Redox, etc. The HTTP client application can be any one that the Operating System supports. For instance, the venerable curl will run on all the above Operating Systems.

To use curl you just need to know the URL to connect to. If you run flockc with the --show-url option, then the URL associated with that command will be displayed rather than connected to.

flock@H01:~$ flockc ribv4 --prefix --host R01 --show-url
http://R01:8000/ribv4/prefix?ipv4_net=*/sort/json-lines
flock@H01:~$

you@your-host:~$ curl -s -X GET "http://R01:8000/ribv4/prefix?ipv4_net=*/sort/json-lines"
{"ip_net":"0.0.0.0/0","origin":"Kernel","next_hops":[{"intf_id":5,"ip_addr":"192.168.122.1"}]}
...

You can then use the language of your choice to consume and manipulate the JSON information. When feeding into a program we want vanilla JSON (rather than the default of JSON with extra line breaks), so we include the --json option to discover the URL.

flock@H01:~$ flockc ribv4 --prefix --json --host R01 --show-url
http://R01:8000/ribv4/prefix?ipv4_net=*/sort/json
flock@H01:~$

you@your-host:~$ curl -s -X GET "http://R01:8000/ribv4/prefix?ipv4_net=*/sort/json" | python -m json.tool
[
    {
        "ip_net": "0.0.0.0/0",
        "next_hops": [
            {
                "intf_id": 5,
                "ip_addr": "192.168.122.1"
            }
        ],
        "origin": "Kernel"
    },
...

Example: Connecting to the REST API using Python

flock@H01:~$ flockc ribv4 --prefix --host r02 --json --show-url
http://r02:8000/ribv4/prefix?ipv4_net=*/sort/json

you@your-host:~$ python3
Python 3.7.3 (default, Apr  3 2019, 05:39:12)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> r = requests.get('http://r02:8000/ribv4/prefix?ipv4_net=*/sort/json')
>>> r.json()
[{'ip_net': '0.0.0.0/0', 'origin': 'Ospfv2', 'next_hops': [{'intf_id': 2, 'ip_addr': '10.0.1.168'}, {'intf_id': 4, 'ip_addr': '10.0.3.176'}]}, {'ip_net': '10.0.1.0/24', 'origin': 'Kernel', 'next_hops': [{'intf_id': 2}]}, {'ip_net': '192.168.122.0/24', 'origin': 'Ospfv2', 'next_hops': [{'intf_id': 2, 'ip_addr': '10.0.1.168'}, {'intf_id': 4, 'ip_addr': '10.0.3.176'}]}]

Manually Building REST API URL's

The available REST API URL's can be discovered using the flockc --show-url option. They can also be built by following these rules.

The URL's mirror the flockc long options, for example:

flockc ribv4 --prefix maps to the URL /ribv4/prefix

Sorting

Append /sort if you want the output sorted.

/ribv4/prefix/sort

Specify the output JSON format

A json format must be specified at the end of the URL.

Append /json if you want vanilla JSON (no extra line breaks).

/ribv4/prefix/sort/json

Append /json-pretty if you want JSON pretty printed.

/ribv4/prefix/sort/json-pretty

Append /json-lines if you want JSON Lines.

/ribv4/prefix/sort/json-lines

Wildcards

In a URL query string a * is treated as wild. prefix?ipv4_net=* will get all IPv4 Networks.

/ribv4/prefix?ipv4_net=*/sort/json

Escaping the / character

To escape the / character in a URL use %2F (0x2F is the ASCII value for /). So to specify an IPv4 network use ipv4_net=10.20.30.0%2F16. If you do not escape the / character this URL will not be found ipv4_net=10.20.30.0/16. It specifies a URL path ending in /16 which is not what we want.

/ribv4/prefix?ipv4_net=10.20.30.0%2F24/sort/json

Commonly used REST API URL's

# BGP Overview
/bgp/json
# BGP Autonomous System
/bgp/as?asn=*/json
/bgp/as?asn=65073/json
# BGP Prefixes
/bgp/prefix?ipv4_net=*/json
/bgp/prefix?ipv4_net=4.3.0.0%2F16/json
# BGP Neighbors
/bgp/as?asn=65056/neigh?ipv4_addr=10.20.30.42/json
/bgp/as?asn=65056/neigh?ipv4_addr=*/json

# OSPFv2 Overview
/ospfv2/json
# OSPFv2 Autonomous System Link State Database (LSA Type 5)
/ospfv2/lsdb/json
# OSPFv2 Area Overview
/ospfv2/area?area_id=0.0.0.0/json
# OSPFv2 Area Link State Database (LSA Type 1 -> Type 4)
/ospfv2/area?area_id=0.0.0.0/lsdb/json
# OSPFv2 Interfaces
/ospfv2/area?area_id=0.0.0.0/intf?intf_name=*/json
/ospfv2/area?area_id=0.0.0.0/intf?intf_name=eth0/json
# OSPFv2 Neighbors
/ospfv2/area?area_id=0.0.0.0/intf?intf_name=*/neigh?id=5.6.7.8/sort/json
/ospfv2/area?area_id=0.0.0.0/intf?intf_name=eth0/neigh?id=5.6.7.8/sort/json
# OSPFv2 Network Prefixes
/ospfv2/prefix-network?ipv4_net=*/json
/ospfv2/prefix-network?ipv4_net=20.30.0.0%2F16/json

# RIBv4 Overview
/ribv4/json
# RIBv4 Longest path match lookup
/ribv4/lpm?ipv4_addr=1.2.3.4/json
# RIBv4 Prefixes
/ribv4/prefix?ipv4_net=*/json
/ribv4/prefix?ipv4_net=10.20.30.0%2F24/json
/ribv4/prefix?origin=ospfv2/json

# System Overview
/system/json
# System Interfaces
/system/intf?intf_name=*/json
/system/intf?intf_name=eth0/json