ALL_TESTS="sanitization_test offload_indication_test \
        sanitization_vlan_aware_test offload_indication_vlan_aware_test"
 NUM_NETIFS=2
+: ${TIMEOUT:=20000} # ms
 source $lib_dir/lib.sh
 
 setup_prepare()
 
        bridge fdb append 00:00:00:00:00:00 dev vxlan0 self dst 198.51.100.2
 
-       bridge fdb show brport vxlan0 | grep 00:00:00:00:00:00 \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb 00:00:00:00:00:00 \
+               bridge fdb show brport vxlan0
        check_err $?
 
        bridge fdb del 00:00:00:00:00:00 dev vxlan0 self
        bridge fdb add de:ad:be:ef:13:37 dev vxlan0 self master static \
                dst 198.51.100.2
 
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan0
        check_err $?
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0
        check_err $?
 
        log_test "vxlan entry offload indication - initial state"
        RET=0
 
        bridge fdb del de:ad:be:ef:13:37 dev vxlan0 master
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan0
+       check_err $?
 
        log_test "vxlan entry offload indication - after removal from bridge"
 
        RET=0
 
        bridge fdb add de:ad:be:ef:13:37 dev vxlan0 master static
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan0
        check_err $?
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0
        check_err $?
 
        log_test "vxlan entry offload indication - after re-add to bridge"
        RET=0
 
        bridge fdb del de:ad:be:ef:13:37 dev vxlan0 self
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0
+       check_err $?
 
        log_test "vxlan entry offload indication - after removal from vxlan"
 
        RET=0
 
        bridge fdb add de:ad:be:ef:13:37 dev vxlan0 self dst 198.51.100.2
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan0
        check_err $?
-       bridge fdb show brport vxlan0 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan0
        check_err $?
 
        log_test "vxlan entry offload indication - after re-add to vxlan"
 {
        RET=0
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link set dev vxlan0 down
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link set dev vxlan1 down
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        log_test "vxlan decap route - vxlan device down"
 
        RET=0
 
        ip link set dev vxlan1 up
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link set dev vxlan0 up
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        log_test "vxlan decap route - vxlan device up"
        RET=0
 
        ip address delete 198.51.100.1/32 dev lo
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        ip address add 198.51.100.1/32 dev lo
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        log_test "vxlan decap route - add local route"
        RET=0
 
        ip link set dev $swp1 nomaster
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link set dev $swp2 nomaster
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        ip link set dev $swp1 master br0
        ip link set dev $swp2 master br1
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        log_test "vxlan decap route - local ports enslavement"
        RET=0
 
        ip link del dev br0
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link del dev br1
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        log_test "vxlan decap route - bridge device deletion"
 
        ip link set dev $swp2 master br1
        ip link set dev vxlan0 master br0
        ip link set dev vxlan1 master br1
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link del dev vxlan0
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        ip link del dev vxlan1
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        log_test "vxlan decap route - vxlan device deletion"
 
        local mac=00:11:22:33:44:55
        local zmac=00:00:00:00:00:00
 
-       bridge fdb show dev vxlan0 | grep $mac | grep self | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $mac self \
+               bridge fdb show dev vxlan0
        check_err $?
-       bridge fdb show dev vxlan0 | grep $mac | grep master | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $mac master \
+               bridge fdb show dev vxlan0
        check_err $?
 
-       bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show dev vxlan0
        check_err $?
 }
 
 
        bridge fdb show dev vxlan0 | grep $mac | grep -q self
        check_err $?
-       bridge fdb show dev vxlan0 | grep $mac | grep self | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $mac self \
+               bridge fdb show dev vxlan0
+       check_err $?
 
        bridge fdb show dev vxlan0 | grep $zmac | grep -q self
        check_err $?
-       bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show dev vxlan0
+       check_err $?
 }
 
 check_bridge_fdb_not_offloaded()
 
        bridge fdb show dev vxlan0 | grep $mac | grep -q master
        check_err $?
-       bridge fdb show dev vxlan0 | grep $mac | grep master | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $mac master \
+               bridge fdb show dev vxlan0
+       check_err $?
 }
 
 __offload_indication_join_vxlan_first()
 
        ip link set dev $swp1 master br0
 
-       bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show dev vxlan0
+       check_err $?
 
        ip link set dev vxlan0 master br0
 
-       bridge fdb show dev vxlan0 | grep $zmac | grep self | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show dev vxlan0
        check_err $?
 
        log_test "offload indication - attach vxlan last"
        ip link set dev $swp1 master br0 &> /dev/null
        check_fail $?
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        log_test "vlan-aware - failed enslavement to bridge due to conflict"
 
        bridge fdb add de:ad:be:ef:13:37 dev vxlan10 self master static \
                dst 198.51.100.2 vlan 10
 
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan10
        check_err $?
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10
        check_err $?
 
        log_test "vxlan entry offload indication - initial state"
        RET=0
 
        bridge fdb del de:ad:be:ef:13:37 dev vxlan10 master vlan 10
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan10
+       check_err $?
 
        log_test "vxlan entry offload indication - after removal from bridge"
 
        RET=0
 
        bridge fdb add de:ad:be:ef:13:37 dev vxlan10 master static vlan 10
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan10
        check_err $?
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10
        check_err $?
 
        log_test "vxlan entry offload indication - after re-add to bridge"
        RET=0
 
        bridge fdb del de:ad:be:ef:13:37 dev vxlan10 self
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10
+       check_err $?
 
        log_test "vxlan entry offload indication - after removal from vxlan"
 
        RET=0
 
        bridge fdb add de:ad:be:ef:13:37 dev vxlan10 self dst 198.51.100.2
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self bridge fdb show brport vxlan10
        check_err $?
-       bridge fdb show brport vxlan10 | grep de:ad:be:ef:13:37 | grep -v self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb \
+               de:ad:be:ef:13:37 self -v bridge fdb show brport vxlan10
        check_err $?
 
        log_test "vxlan entry offload indication - after re-add to vxlan"
 {
        RET=0
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        # Toggle PVID flag on one VxLAN device and make sure route is still
        # marked as offloaded
        bridge vlan add vid 10 dev vxlan10 untagged
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload \
+               ip route show table local 198.51.100.1
        check_err $?
 
        # Toggle PVID flag on second VxLAN device and make sure route is no
        # longer marked as offloaded
        bridge vlan add vid 20 dev vxlan20 untagged
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
-       check_fail $?
+       busywait "$TIMEOUT" not wait_for_offload \
+               ip route show table local 198.51.100.1
+       check_err $?
 
        # Toggle PVID flag back and make sure route is marked as offloaded
        bridge vlan add vid 10 dev vxlan10 pvid untagged
        bridge vlan add vid 20 dev vxlan20 pvid untagged
 
-       ip route show table local | grep 198.51.100.1 | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload ip route show table local 198.51.100.1
        check_err $?
 
        log_test "vxlan decap route - vni map/unmap"
        ip link set dev vxlan0 master br0
        bridge vlan add dev vxlan0 vid 10 pvid untagged
 
-       bridge fdb show brport vxlan0 | grep $zmac | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show brport vxlan0
        check_err $? "vxlan tunnel not offloaded when should"
 
        # Configure a VLAN interface and make sure tunnel is offloaded
        ip link add link br0 name br10 up type vlan id 10
        sysctl_set net.ipv6.conf.br10.disable_ipv6 0
        ip -6 address add 2001:db8:1::1/64 dev br10
-       bridge fdb show brport vxlan0 | grep $zmac | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show brport vxlan0
        check_err $? "vxlan tunnel not offloaded when should"
 
        # Unlink the VXLAN device, make sure tunnel is no longer offloaded,
        # then add it back to the bridge and make sure it is offloaded
        ip link set dev vxlan0 nomaster
-       bridge fdb show brport vxlan0 | grep $zmac | grep self \
-               | grep -q offload
-       check_fail $? "vxlan tunnel offloaded after unlinked from bridge"
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show brport vxlan0
+       check_err $? "vxlan tunnel offloaded after unlinked from bridge"
 
        ip link set dev vxlan0 master br0
-       bridge fdb show brport vxlan0 | grep $zmac | grep self \
-               | grep -q offload
-       check_fail $? "vxlan tunnel offloaded despite no matching vid"
+       busywait "$TIMEOUT" not wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show brport vxlan0
+       check_err $? "vxlan tunnel offloaded despite no matching vid"
 
        bridge vlan add dev vxlan0 vid 10 pvid untagged
-       bridge fdb show brport vxlan0 | grep $zmac | grep self \
-               | grep -q offload
+       busywait "$TIMEOUT" wait_for_offload grep_bridge_fdb $zmac self \
+               bridge fdb show brport vxlan0
        check_err $? "vxlan tunnel not offloaded after adding vid"
 
        log_test "vxlan - l3 vni"