@goldilocks put it in a nutshell in his comment so I will quote it here:
There's no way to do that passively (ie., without sending packets out), and no definitive universal way to do it actively by noting a failure to send, since that is very context dependent (send what where? Eg., Does a failure to connect to google.com:80 indicate the internet is down? And detecting a failure to connect to anything would take a very, very long time). The router can tell when the uplink is gone, but it will not turn off the LAN because of that even if there's only one thing connected.
But you asked (in a reply to this) if there is a way to have a local logic implemented that for example pings google every 2mins and if not reachable, failover?
This is not an easy task and we have to grab deep into the bag of tricks about networking. There are mainly two issues:
1. The eth0 interface must always be up. Otherwise we can't ping if the connection is back again. We can only manage that eth0 is a slave member of bonding or not.
2. It is the nature of bonding that you always have a connection, no matter if eth0 is connected or not. So you can't simply ping from eth0. You will always get a response because the default route is going through interface bond0. So we have to use source routing to see if a connection from interface eth0 (not a slave of bonding at this time) succeeds. This is made with policy routing but details about it are out of scope here. Just take it.
Here is a tested example how I would do it. To simplify things I have eth0 given a static ip address. You have already made a setup as shown in Howto migrate from networking to systemd-networkd with dynamic failover.
First create a new routing table
pingtest with ID 200:
rpi ~$ sudo bash -c 'echo 200 pingtest >> /etc/iproute2/rt_tables'
Then ensure that
/etc/systemd/network/12-bond0-add-eth.network looks like this:
# This makes a default route
Then create a bash script
POLL="120" # polling time in seconds
while true; do
if [[ $(/bin/ip -br link show dev "$IF") == *",SLAVE,UP,"* ]]; then
#echo DEBUG: "$IF" is slave
/bin/ping -Bnq -c3 -w3 "$PING_DEST" &>/dev/null
if [ $? -ne 0 ]; then
/bin/ip link set "$IF" nomaster
/bin/ip link set "$IF" up
echo "$IF" removed from "$BOND", ping to "$PING_DEST" failed
#echo DEBUG: "$IF" is no slave
/bin/ping -Bnq -c3 -w3 -I "$PING_SOURCE" "$PING_DEST" &>/dev/null
if [ $? -eq 0 ]; then
/bin/ip link set "$IF" down
/bin/ip link set "$IF" master "$BOND"
/bin/ip link set "$IF" up
echo "$IF" added to "$BOND", ping to "$PING_DEST" succeeded
For testing you can uncomment the two
echo DEBUG: statements and execute the script from the command line with sudo. Don't forget to make it executable with
chmod +x pingtest.sh. Messages from the script about bond changes you will find in the journal or with
systemctl status pingtest.service (service see below).
To run the script create a service with:
rpi ~$ sudo systemctl --force --full edit pingtest.service
In the empty editor insert these statements, save them and quit the editor:
Description=Pingtest if destination is up
Enable the new service with
rpi ~$ sudo systemctl enable pingtest.service
The routing of this setup looks like this:
rpi ~$ ip route show table main
default via 192.168.50.1 dev bond0 proto dhcp src 192.168.50.205 metric 1024
192.168.50.0/24 dev bond0 proto kernel scope link src 192.168.50.205
192.168.50.0/24 dev eth0 proto kernel scope link src 192.168.50.60
192.168.50.1 dev bond0 proto dhcp scope link src 192.168.50.205 metric 1024
rpi ~$ ip route show table pingtest
default via 192.168.50.1 dev eth0 proto static src 192.168.50.60
rpi ~$ ip rule ls
0: from all lookup local
16384: from 192.168.50.60 lookup pingtest
32766: from all lookup main
32767: from all lookup default