FIB recusrion loop checks traverse midchain adjacencies
if a tunnel's destination address is reachable through the tunnel
(see example config belwo) then search for and detect a recursion
loop and don't stack the adjacency. Otherwise this results in a
nasty surprise.
DBGvpp# loop cre
DBGvpp# set int state loop0 up
DBGvpp# set int ip addr loop0 10.0.0.1/24
DBGvpp# create gre tunnel src 10.0.0.1 dst 1.1.1.1
DBGvpp# set int state gre0 up
DBGvpp# set int unnum gre0 use loop0
DBGvpp# ip route 1.1.1.1/32 via gre0
DBGvpp# sh ip fib 1.1.1.1
ipv4-VRF:0, fib_index:0, flow hash:[src dst sport dport proto ] locks:[src:plugin-hi:2, src:default-route:1, ]
1.1.1.1/32 fib:0 index:11 locks:4 <<< this is entry #11
src:CLI refs:1 entry-flags:attached, src-flags:added,contributing,active,
path-list:[14] locks:2 flags:shared,looped, uPRF-list:12 len:1 itfs:[2, ]
path:[14] pl-index:14 ip4 weight=1 pref=0 attached-nexthop: oper-flags:recursive-loop,resolved, cfg-flags:attached,
1.1.1.1 gre0 (p2p)
[@0]: ipv4 via 0.0.0.0 gre0: mtu:9000 4500000000000000fe2fb0cc0a0000010101010100000800
stacked-on entry:11: <<<< and the midchain forwards via entry #11
[@2]: dpo-drop ip4
src:recursive-resolution refs:1 src-flags:added, cover:-1
forwarding: unicast-ip4-chain
[@0]: dpo-load-balance: [proto:ip4 index:13 buckets:1 uRPF:12 to:[0:0]]
[0] [@6]: ipv4 via 0.0.0.0 gre0: mtu:9000 4500000000000000fe2fb0cc0a0000010101010100000800
stacked-on entry:11:
[@2]: dpo-drop ip4
DBGvpp# sh adj 1
[@1] ipv4 via 0.0.0.0 gre0: mtu:9000 4500000000000000fe2fb0cc0a0000010101010100000800
stacked-on entry:11:
[@2]: dpo-drop ip4
flags:midchain-ip-stack midchain-looped <<<<< this is a loop
counts:[0:0]
locks:4
delegates:
children:
{path:14}
Change-Id: I39b82bd1ea439be4611c88b130d40289fa0c1b59
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/test/test_gre.py b/test/test_gre.py
index eed3d8b..dd7b8bc 100644
--- a/test/test_gre.py
+++ b/test/test_gre.py
@@ -867,6 +867,67 @@
route_tun1_dst.add_vpp_config()
route_tun2_dst.add_vpp_config()
+ def test_gre_loop(self):
+ """ GRE tunnel loop Tests """
+
+ #
+ # Create an L3 GRE tunnel.
+ # - set it admin up
+ # - assign an IP Addres
+ #
+ gre_if = VppGreInterface(self,
+ self.pg0.local_ip4,
+ "1.1.1.2")
+ gre_if.add_vpp_config()
+ gre_if.admin_up()
+ gre_if.config_ip4()
+
+ #
+ # add a route to the tunnel's destination that points
+ # through the tunnel, hence forming a loop in the forwarding
+ # graph
+ #
+ route_dst = VppIpRoute(self, "1.1.1.2", 32,
+ [VppRoutePath("0.0.0.0",
+ gre_if.sw_if_index)])
+ route_dst.add_vpp_config()
+
+ #
+ # packets to the tunnels destination should be dropped
+ #
+ tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
+ self.send_and_assert_no_replies(self.pg2, tx)
+
+ self.logger.info(self.vapi.ppcli("sh adj 7"))
+
+ #
+ # break the loop
+ #
+ route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
+ self.pg1.sw_if_index)])
+ route_dst.add_vpp_config()
+
+ rx = self.send_and_expect(self.pg0, tx, self.pg1)
+
+ #
+ # a good route throught the tunnel to check it restacked
+ #
+ route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
+ [VppRoutePath("0.0.0.0",
+ gre_if.sw_if_index)])
+ route_via_tun_2.add_vpp_config()
+
+ tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
+ rx = self.send_and_expect(self.pg0, tx, self.pg1)
+ self.verify_tunneled_4o4(self.pg1, rx, tx,
+ self.pg0.local_ip4, "1.1.1.2")
+
+ #
+ # cleanup
+ #
+ route_via_tun_2.remove_vpp_config()
+ gre_if.remove_vpp_config()
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)