Skip to content
LinkState
Go back

Parser accepted it but runtime behavior still broke

Introduction to Configuration Validation

Understanding Parse Success

Parse success means the configuration text conforms to the device’s grammar and can be loaded into the running configuration without syntax errors. In FRR (Free Range Routing) this is verified by invoking vtysh in batch mode or via the interactive shell; the parser returns exit code 0 and no error messages. Parse success does not guarantee that the configured features will operate as intended.

Understanding Apply Success

Apply success is the operational proof that the configuration, once loaded, produces the expected behavior in the data plane. This is verified by examining show‑commands, counters, or traffic after the configuration has been committed. A configuration can parse cleanly yet fail to apply because of missing pre‑conditions, resource exhaustion, or semantic mismatches (e.g., referencing a non‑existent interface).


Syntactically Valid Configurations

Examples of Valid Configurations

The following FRR snippets are syntactically correct according to the FRR CLI grammar (FRR 8.4). They define a BGP speaker, a static route, and an ACL. Each block can be pasted into vtysh and will be accepted without error.

! router bgp 65001
bgp router-id 10.0.0.1
no bgp default ipv4-unicast
neighbor 10.0.0.2 remote-as 65002
!
! ipv6 route
ipv6 route 2001:db8:cafe::/64 Null0
!
! ip access-list
ip access-list standard LAN-ALLOW
  permit 10.0.0.0 0.0.0.255
exit
!

Reproduced CLI Output for Valid Configurations

The lab uses Containerlab to spin up a single FRR node (frr1). The configuration is loaded via a batch file.

# Deploy the lab
$ sudo clab deploy -t frr-simple.yml
+---+----------------------+--------------+--------------+---------+
| # | Name                 | Container ID | Image        | Status  |
+---+----------------------+--------------+--------------+---------+
| 1 | clab-frr-simple-frr1 | a1b2c3d4     | frrouting/frr:8.4 | running |
+---+----------------------+--------------+--------------+---------+

# Load the configuration (batch mode)
$ docker exec -it clab-frr-simple-frr1 vtysh -b -f /opt/frr/config.txt
# No output, exit code 0
$ echo $?
0

The vtysh -b -f command returns immediately with exit code 0, indicating the parser accepted every line. No confirmation yet that BGP peers are up, the static route is installed, or the ACL is applied.


Runtime Failures in Valid Configurations

Common Causes of Runtime Failures

  1. Missing pre‑conditions – e.g., BGP neighbor IP not reachable because the interface lacks an address or is down.
  2. Semantic mismatches – referencing a route‑map, prefix‑list, or ACL that does not exist.
  3. Resource exhaustion – too many routes or ACL entries causing CPU/memory spikes.
  4. Protocol‑specific constraints – OSPF area ID mismatch, BGP timers incompatible with peer, etc.
  5. Incorrect direction/scope – applying an egress ACL in the inbound direction or binding a service to the wrong VRF.

Parser Responses for Runtime Failures

When the configuration is loaded, FRR’s parser still reports success because the offending statements are syntactically valid. The only indication of a problem appears later in operational show‑commands or in the log.

# Simulate missing interface address for BGP neighbor
$ docker exec -it clab-frr-simple-frr1 vtysh -b -f /opt/frr/config-missing-ip.txt
# No parser errors
$ echo $?
0

Even though the neighbor 10.0.0.2 is configured, the local interface eth1 has no IP address, so the TCP session cannot be established. The parser does not complain because the neighbor statement itself is valid.

Operational State After Runtime Failures

After loading the broken config, the operational state shows the failure.

# BGP summary – neighbor stays Idle
$ docker exec -it clab-frr-simple-frr1 vtysh -c "show ip bgp summary"
BGP router identifier 10.0.0.1, local AS number 65001
BGP table version is 0
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
* 10.0.0.2      4 65002     0     0        0    0    0 never    Active
# Static route – not installed because Null0 is always valid, but we test an unreachable next-hop
$ docker exec -it clab-frr-simple-frr1 vtysh -c "show ip route"
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
       O - OSPF, IA - OSPF inter area, N1 - OSPF NSSA external type 1,
       N2 - OSPF NSSA external type 2, E1 - OSPF external type 1,
       E2 - OSPF external type 2, i - IS-IS, L1 - IS-IS level-1,
       L2 - IS-IS level-2, ia - IS-IS inter area, * - candidate default,
       U - user-updated static, o - ODR, P - periodic downloaded static,
       + - replicated route

Gateway of last resort is not set

C        10.0.0.0/24 is directly connected, eth0

The BGP neighbor remains in Active state (never established). The static route to Null0 is installed as expected, but if we had pointed to an unreachable next‑hop the route would appear as S yet be unusable. No error messages appear in the CLI; the operator must actively query the state.


Troubleshooting Runtime Failures

Identifying Root Causes

The troubleshooting flow starts with verifying pre‑conditions (interface state, reachability) then moves to protocol‑specific diagnostics.

CLI Commands for Troubleshooting

# 1. Check interface status and IP address
$ docker exec -it clab-frr-simple-frr1 vtysh -c "show ip interface brief"
Interface          IP-Address      OK? Method Status                Protocol
eth0               10.0.0.1/24     YES manual up                    up
eth1               unassigned      YES unset  administratively down down
# 2. Verify that the neighbor IP is reachable (ping from the same netns)
$ docker exec -it clab-frr-simple-frr1 ping -c 2 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56 data bytes
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1019ms
# 3. Enable BGP debugging to see why the session stays Active
$ docker exec -it clab-frr-simple-frr1 vtysh -c "terminal monitor"
$ docker exec -it clab-frr-simple-frr1 vtysh -c "debug bgp events"
$ docker exec -it clab-frr-simple-frr1 vtysh -c "show logging"
...
% BGP-5-ADJCHANGE: neighbor 10.0.0.2 Down Active
% BGP-4-PEERESTAB: BGP peer 10.0.0.2 failed to establish: No route to host

Parser Responses for Troubleshooting

During troubleshooting, the parser still returns success for any configuration changes we make; the proof lies in the operational output.

# Correct the missing IP address
$ docker exec -it clab-frr-simple-frr1 vtysh -b -c "configure terminal" \
    -c "interface eth1" -c "ip address 10.0.0.2/24" -c "exit"
# No parser error
$ echo $?
0

After the fix, the BGP session comes up:

$ docker exec -it clab-frr-simple-frr1 vtysh -c "show ip bgp summary"
BGP router identifier 10.0.0.1, local AS number 65001
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
* 10.0.0.2      4 65002     5     5        0    0    0 00:02:13  1

The parser accepted the interface address change without complaint. Only


Share this post on:

Next Post
veth is not free just because it is virtual