I am using check_mk to monitor some networks, and wanted to do something similar to what Cisco's IP SLA does, and what SmokePing does: check for a rough measure of latency, loss, and jitter on a network. As check_mk is Python based, I wanted something in Python, which I could retrofit to act as a check_mk agent.
I found some code at: Route Reflector, which may, in turn, may have had some of its origins at ping.py – Python Implementation of the ping command.
According to the notes in the code, the original code has been through a number of authors and iterations.
My iteration allows:
- a different nagios output (for check_mk)
- provide a source ip address and source description
- rrd code commented out, but can be uncommented for use
Under normal circumstances, when doing a wildcard (default) bind, and a packet is sent to a destination ip address, the source address will be chosen based upon which is 'closest' (from a routing table perspective) to the destination.
In my tests, I need to test network quality from a number of interfaces on the same device. Therefore, I need to set the source of address of the ping. In addition, with the source address set, the packet has to egress that same interface (routing will cause the egress to be out the interface 'closest' to the destination).
The solution, on a linux based platform, is to use policy based routing.
For a policy based routing example on a device with two interfaces:
- local interface eth0: 10.1.1.1/30
- other end: 10.1.1.2/30 (the default gateway for this example)
- local interface eth1: 10.1.2.1/30
- other end: 10.1.2.2/30
- destination host: 10.1.3.1
Linux iproute2 commands to provide the appropriate routing:
ip route add 0/0 via 10.1.1.2 ip route add 0/0 via 10.1.2.2 dev eth1 table 6 ip route add from 10.1.2.1/32 lookup 6 priority 100
A description of the above statements:
- The first default route is the main system default route.
- The second default route is placed into table 6 as a special lookup.
- Then a policy is added meaning that anything from 10.1.2.1/32 uses table 6 for destionation lookup
- Table 6 has the default route out eth1 for sending traffic originating from 10.1.2.1/32
An example ping would be:
/usr/bin/python ~/ping/ping.py -c 20 -t 1 -n int_eth1 -s 10.1.2.1 -d 10.1.3.1
The ping will go out interface eth1 with the policy-based route in place. Without the policy based route in place, the ping will go out eth0.
The code can be found at: Github, rburkholder, ping.py
More info on policy routing:
- jumanjiman / policy-based-routing
- linux-ip.net: IP Routing
- Policy Routing With Linux - Online Edition by Matthew G. Marsh
Other interesting tools:
- github: Python netlink library — Linux network setup and monitoring
- python: Service Function Chaining API for OpenStack Neutron
- Test driving Policy Based Routing on Linux: uses mininet as a test environment
Some other python ping results:
- Another pure python ping implementation using raw socket.
- Pinging with Python
- Ping, Latency, Jitter, and Packet Loss