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 rib --af ipv4 --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 rib --af ipv4 --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 rib --af ipv4 --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 rib --af ipv4 --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 rib --af ipv4 --prefix --host R01 --show-url
http://R01:8000/rib/af?af_type=ipv4/prefix?ip_net=*/sort/json-lines
flock@H01:~$
you@your-host:~$ curl -s -X GET "http://R01:8000/rib/af?af_type=ipv4/prefix?ip_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 rib --af ipv4 --prefix --json --host R01 --show-url
http://R01:8000/rib/af?af_type=ipv4/prefix?ip_net=*/sort/json
flock@H01:~$
you@your-host:~$ curl -s -X GET "http://R01:8000/rib/af?af_type=ipv4/prefix?ip_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 rib --af ipv4 --prefix --host r02 --json --show-url
http://r02:8000/rib/af?af_type=ipv4/prefix?ip_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/rib/af?af_type=ipv4/prefix?ip_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 rib --af ipv4 --prefix
maps to the URL /rib/af?af_type=ipv4/prefix
Sorting
Append /sort
if you want the output sorted.
/rib/af?af_type=ipv4/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).
/rib/af?af_type=ipv4/prefix/sort/json
Append /json-pretty
if you want JSON pretty printed.
/rib/af?af_type=ipv4/prefix/sort/json-pretty
Append /json-lines
if you want JSON Lines.
/rib/af?af_type=ipv4/prefix/sort/json-lines
Wildcards
In a URL query string a *
is treated as wild. prefix?ip_net=*
will get all IPv4 Networks.
/rib/af?af_type=ipv4/prefix?ip_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 ip_net=10.20.30.0%2F16
. If you do not escape the /
character this URL will not be found ip_net=10.20.30.0/16
. It specifies a URL path ending in /16
which is not what we want.
/rib/af?af_type=ipv4/prefix?ip_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?ip_net=*/json
/bgp/prefix?ip_net=4.3.0.0%2F16/json
# BGP Neighbors
/bgp/as?asn=65056/neigh?ip_addr=10.20.30.42/json
/bgp/as?asn=65056/neigh?ip_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?ip_net=*/json
/ospfv2/prefix-network?ip_net=20.30.0.0%2F16/json
# RIBv4 Overview
/rib/af?af_type=ipv4/json
# RIBv4 Longest path match lookup
/rib/af?af_type=ipv4/lpm?ip_addr=1.2.3.4/json
# RIBv4 Prefixes
/rib/af?af_type=ipv4/prefix?ip_net=*/json
/rib/af?af_type=ipv4/prefix?ip_net=10.20.30.0%2F24/json
/rib/af?af_type=ipv4/prefix?origin=ospfv2/json
# RIBv6 Overview
/ribv6/json
# RIBv6 Longest path match lookup
/ribv6/lpm?ip_addr=fc00::01/json
# RIBv6 Prefixes
/ribv6/prefix?ip_net=*/json
/ribv6/prefix?ip_net=fc00::01%2F64/json
# System Overview
/system/json
# System Interfaces
/system/intf?intf_name=*/json
/system/intf?intf_name=eth0/json