The reason most GRE tunnels exist is to carry a routing protocol. Plain static routes do not need GRE, and the public internet that you would want to send routing-protocol traffic over does not natively forward multicast. GRE bridges the gap: it lets OSPF, EIGRP, and BGP form neighbor relationships across paths that would otherwise be hostile to them. This article is the practical walkthrough of running each of the three big routing protocols across a GRE tunnel on Cisco IOS XE, the recursive-routing trap that catches every newcomer, and the design decisions that matter at scale.
Part of the PingLabz GRE Tunnels cluster. If you have not built a GRE tunnel yet, start at the config lab. For BGP, OSPF, or EIGRP fundamentals, see the BGP pillar, OSPF pillar, and EIGRP pillar.
Why Routing Protocols Need GRE
The two routing-protocol behaviors that drive the need for GRE are multicast hellos and protocol field numbers.
- OSPF sends Hello packets to multicast 224.0.0.5 and 224.0.0.6. The public internet does not forward multicast.
- EIGRP sends Hello packets to multicast 224.0.0.10. Same problem.
- BGP uses unicast TCP sessions. BGP itself does not need GRE - you can run iBGP or eBGP over plain IPsec or even plain internet routing - but if your overall design uses GRE tunnels, BGP rides them too.
Wrapping the routing protocol in GRE turns its multicast Hello into a unicast IP packet. The internet (or any IP underlay) is happy to deliver unicast IP. The two routers see each other as if directly connected on a point-to-point link, and the routing protocol forms a neighbor.
The Recursive Routing Trap
Before any specific protocol config, understand this single failure mode that affects all of them. It is the most common GRE-over-routing-protocol problem in production.
The setup: R1 has a tunnel destination of 203.0.113.1 (R2's underlay IP). R1 learns a route to 203.0.113.1 through the underlay (via BGP from the ISP, say). The tunnel comes up. R1 starts running OSPF over the tunnel. OSPF distributes routes, including, accidentally, a route to 203.0.113.1 itself if R2 advertises its underlay /32 into OSPF.
Now R1 has two routes to 203.0.113.1: the underlay one (correct) and the OSPF one (advertising "next-hop is 10.0.0.2 via Tunnel0"). The OSPF route has a lower administrative distance than iBGP/static-from-ISP, so it wins. R1 now thinks the way to reach R2's underlay IP is through Tunnel0. But Tunnel0's destination is R2's underlay IP. The tunnel cannot encapsulate packets to itself. The tunnel goes down. The OSPF neighbor dies. The OSPF route disappears. R1 falls back to the underlay route. The tunnel comes up. The cycle repeats.
The IOS XE error you see in the log is unmistakable:
%TUN-5-RECURDOWN: Tunnel0 temporarily disabled due to recursive routingThe fix is to make sure the routing protocol running across the tunnel does not learn a route to the tunnel destination IP. Two ways to do that:
Static route to the tunnel destination through the underlay. A static route has lower administrative distance than dynamic routes (1 vs 110 for OSPF, 90/170 for EIGRP, 200 for iBGP). It will always win.
R1(config)# ip route 203.0.113.1 255.255.255.255 198.51.100.2Distribute-list out the underlay IP. If you cannot use a static route (perhaps the underlay routing is fully dynamic), prevent the tunnel-side routing protocol from advertising or accepting the underlay subnet.
R1(config)# ip prefix-list NO-UNDERLAY seq 10 deny 203.0.113.0/24 le 32
R1(config)# ip prefix-list NO-UNDERLAY seq 20 permit 0.0.0.0/0 le 32
R1(config)# router ospf 1
R1(config-router)# distribute-list prefix NO-UNDERLAY inThe static-route fix is simpler and more bulletproof. Use it unless you have a specific reason not to.
OSPF over GRE
Most common case. OSPF on a tunnel interface forms a point-to-point adjacency by default with the OSPF network type "POINT_TO_POINT," which is fine for two-router GRE tunnels. For mGRE / DMVPN you would change the network type, but for standard GRE, defaults work.
R1(config)# router ospf 1
R1(config-router)# router-id 1.1.1.1
R1(config-router)# network 10.0.0.0 0.0.0.3 area 0
R1(config-router)# network 192.168.1.0 0.0.0.255 area 0
R1(config-router)# passive-interface GigabitEthernet2
R2(config)# router ospf 1
R2(config-router)# router-id 2.2.2.2
R2(config-router)# network 10.0.0.0 0.0.0.3 area 0
R2(config-router)# network 192.168.2.0 0.0.0.255 area 0
R2(config-router)# passive-interface GigabitEthernet2Verification:
R1# show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
2.2.2.2 0 FULL/ - 00:00:39 10.0.0.2 Tunnel0
R1# show ip ospf interface Tunnel0
Tunnel0 is up, line protocol is up
Internet Address 10.0.0.1/30, Area 0
Process ID 1, Router ID 1.1.1.1, Network Type POINT_TO_POINT, Cost: 1000Note the Cost: 1000. OSPF picks cost based on interface bandwidth, and the default tunnel-interface bandwidth is very low (100 Kbps in the show interface output). That gives OSPF a high cost on the tunnel and may cause unexpected path-selection if the tunnel is supposed to be primary. Two fixes:
! Option A: pin the tunnel cost directly
R1(config)# interface Tunnel0
R1(config-if)# ip ospf cost 100
! Option B: tell OSPF the bandwidth is what you actually have
R1(config)# interface Tunnel0
R1(config-if)# bandwidth 1000000 ! 1 Gbps in kbpsOption A is more deliberate; Option B affects more than just OSPF (EIGRP and policy-based decisions also use bandwidth). Use whichever fits your operational style.
EIGRP over GRE
EIGRP requires the same kind of multicast support as OSPF, so it works over GRE. Unlike OSPF, EIGRP cares about interface bandwidth and delay because they go directly into the composite metric.
R1(config)# router eigrp 100
R1(config-router)# network 10.0.0.0 0.0.0.3
R1(config-router)# network 192.168.1.0 0.0.0.255
R1(config-router)# passive-interface GigabitEthernet2
R2(config)# router eigrp 100
R2(config-router)# network 10.0.0.0 0.0.0.3
R2(config-router)# network 192.168.2.0 0.0.0.255
R2(config-router)# passive-interface GigabitEthernet2
R1# show ip eigrp neighbors
EIGRP-IPv4 Neighbors for AS(100)
H Address Interface Hold Uptime SRTT RTO Q Seq
(sec) (ms) Cnt Num
0 10.0.0.2 Tu0 13 00:00:42 12 100 0 4The EIGRP gotcha: with the default 100 Kbps tunnel bandwidth, EIGRP's metric is enormous and the tunnel becomes the slowest path EIGRP knows about, which is the opposite of what you want. Fix the bandwidth or fix the delay:
R1(config)# interface Tunnel0
R1(config-if)# bandwidth 1000000 ! 1 Gbps for metric calc
R1(config-if)# delay 100 ! 1000 microsecondsSet both ends to the same values. EIGRP uses minimum bandwidth and cumulative delay along the path; both ends must agree on the local interface values for the metric calculation to be sane.
EIGRP also has a per-interface SIA (Stuck-In-Active) timer that is sensitive to high-latency tunnels. If the tunnel rides over an internet path with 200 ms latency, the default SIA timer (180 seconds) is fine, but extreme jitter or transient drops can trigger SIA flaps. The deeper EIGRP-tuning discussion is at the EIGRP cluster.
BGP over GRE
BGP is unicast TCP and does not strictly need GRE. The case where BGP rides a GRE tunnel is when you have an existing GRE overlay (perhaps GRE-over-IPsec for encrypted multicast support) and you want iBGP to use the same overlay rather than building a separate transport.
R1(config)# router bgp 65001
R1(config-router)# bgp router-id 1.1.1.1
R1(config-router)# neighbor 10.0.0.2 remote-as 65001
R1(config-router)# neighbor 10.0.0.2 update-source Tunnel0
R1(config-router)# network 192.168.1.0 mask 255.255.255.0
R2(config)# router bgp 65001
R2(config-router)# bgp router-id 2.2.2.2
R2(config-router)# neighbor 10.0.0.1 remote-as 65001
R2(config-router)# neighbor 10.0.0.1 update-source Tunnel0
R2(config-router)# network 192.168.2.0 mask 255.255.255.0
R1# show ip bgp summary
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.0.0.2 4 65001 8 8 12 0 0 00:03:21 1The update-source Tunnel0 command forces BGP to send TCP packets with the tunnel-interface IP as the source. Without it, BGP uses the underlay interface IP as source, which works on the underlay but does not match the IP the remote peer is configured to expect. update-source is the canonical fix and standard practice for any BGP session that is not on a directly-connected interface.
For eBGP between separate ASes over GRE, add ebgp-multihop with a TTL value if the tunnel makes the BGP peer appear more than one IP hop away (which it usually does, since the tunnel destination IP is not the BGP peer IP):
R1(config)# router bgp 65001
R1(config-router)# neighbor 10.0.0.2 remote-as 65002
R1(config-router)# neighbor 10.0.0.2 ebgp-multihop 2
R1(config-router)# neighbor 10.0.0.2 update-source Tunnel0OSPF Network Types over Multipoint GRE
Standard point-to-point GRE: OSPF defaults to network type POINT_TO_POINT, no DR/BDR election, simple. mGRE / DMVPN changes this. Multipoint tunnels require careful OSPF network-type planning:
| OSPF network type on Tunnel | DR/BDR? | Hello timer | When to use |
|---|---|---|---|
| point-to-point | No | 10 sec | Standard 2-router GRE tunnel |
| broadcast | Yes | 10 sec | mGRE where hub is DR (not common) |
| non-broadcast (NBMA) | Yes (manual neighbor) | 30 sec | DMVPN Phase 1 hub-and-spoke |
| point-to-multipoint | No | 30 sec | DMVPN Phase 2/3 (recommended for most modern DMVPN) |
For a standard two-router GRE tunnel, leave the default. For DMVPN designs, the OSPF-network-type choice drives a lot of the design decisions and is covered in the DMVPN guide.
Design Considerations
- Use Loopbacks as tunnel sources for stable peering. If the underlay IP changes (DHCP, DMVPN), use a Loopback as the tunnel source so the tunnel and the routing-protocol peer have a stable address.
- Authentication. OSPF area authentication, EIGRP authentication keys, or BGP MD5 password should be set even on a tunnel that is itself encrypted. Defense in depth.
- Hello / Dead timer tuning. Defaults are conservative. For faster failover on a dedicated tunnel, set OSPF hello to 1, dead to 4 (or use
ip ospf dead-interval minimal hello-multiplier 4). EIGRP hello to 1, hold to 3. BGP keepalive 3, hold 9. Confirm both ends have matching values. - Filtering. Run a distribute-list or prefix-list to ensure you do not accidentally redistribute the underlay routes through the tunnel-side routing protocol. This was the recursive-routing scenario above; it is preventable but the default config does not prevent it.
- Multiple tunnels for redundancy. A single GRE tunnel between two sites is a single point of failure. For HA, build two tunnels via different underlay paths and let the routing protocol choose the best one. Each tunnel needs its own distinct overlay /30 and tunnel destination.
Summary
OSPF, EIGRP, and BGP all run over GRE tunnels with very small additional config beyond the basic GRE setup. The protocol-specific gotchas are: OSPF cost depends on the tunnel-interface bandwidth (override it), EIGRP composite metric depends on bandwidth and delay (set both deliberately), BGP needs update-source Tunnel0 for the TCP session to land on the right IP. The universal trap is recursive routing: prevent it with a static route to the tunnel destination via the underlay, every time, before the routing protocol has a chance to learn its way back through the tunnel.
For specific protocol depth, see the OSPF cluster, EIGRP cluster, and BGP cluster. For the full GRE story, the PingLabz GRE pillar is the cluster index.