Broken commit diff on Cisco IOS XR
Vincent Bernat
TL;DR
Never trust show commit changes diff
on Cisco IOS XR.
Cisco IOS XR is the operating system running for the Cisco ASR, NCS, and
8000 routers. Compared to Cisco IOS, it features a candidate
configuration and a running configuration. In configuration mode, you can
modify the first one and issue the commit
command to apply it to the running
configuration.1 This is a common concept for many NOS.
Before committing the candidate configuration to the running configuration, you
may want to check the changes that have accumulated until now. That’s where the
show commit changes diff
command2 comes up. Its goal is to show the
difference between the running configuration (show running-configuration
) and
the candidate configuration (show configuration merge
). How hard can it be?
Let’s put an interface down on IOS XR 7.6.2 (released in August 2022):
RP/0/RP0/CPU0:router(config)#int Hu0/1/0/1 shut RP/0/RP0/CPU0:router(config)#show commit changes diff Wed Nov 23 11:08:30.275 CET Building configuration... !! IOS XR Configuration 7.6.2 + interface HundredGigE0/1/0/1 + shutdown ! end
The +
sign before interface HundredGigE0/1/0/1
makes it look like you did
create a new interface. Maybe there was a typo? No, the diff is just broken. If
you look at the candidate configuration, everything is like you expect:
RP/0/RP0/CPU0:router(config)#show configuration merge int Hu0/1/0/1 Wed Nov 23 11:08:43.360 CET interface HundredGigE0/1/0/1 description PNI: (some description) bundle id 4000 mode active lldp receive disable transmit disable ! shutdown load-interval 30
Here is a more problematic example on IOS XR 7.2.2 (released in January 2021). We want to unconfigure three interfaces:
RP/0/RP0/CPU0:router(config)#no int GigabitEthernet 0/0/0/5 RP/0/RP0/CPU0:router(config)#int TenGigE 0/0/0/5 shut RP/0/RP0/CPU0:router(config)#no int TenGigE 0/0/0/28 RP/0/RP0/CPU0:router(config)#int TenGigE 0/0/0/28 shut RP/0/RP0/CPU0:router(config)#no int TenGigE 0/0/0/29 RP/0/RP0/CPU0:router(config)#int TenGigE 0/0/0/29 shut RP/0/RP0/CPU0:router(config)#show commit changes diff Mon Nov 7 15:07:22.990 CET Building configuration... !! IOS XR Configuration 7.2.2 - interface GigabitEthernet0/0/0/5 - shutdown ! + interface TenGigE0/0/0/5 + shutdown ! interface TenGigE0/0/0/28 - description Trunk (some description) - bundle id 2 mode active ! end
The two first commands are correctly represented by the first two chunks of the
diff: we remove GigabitEthernet0/0/0/5
and create TenGigE0/0/0/5
. The two
next commands are also correctly represented by the last chunk of the diff.
TenGigE0/0/0/28
was already shut down, so it is expected that only
description
and bundle id
are removed. However, the diff
command forgets
about the modifications for TenGigE0/0/0/29
. The diff should include a chunk
similar to the last one.
RP/0/RP0/CPU0:router(config)#show run int TenGigE 0/0/0/29 Mon Nov 7 15:07:43.571 CET interface TenGigE0/0/0/29 description Trunk to other router bundle id 2 mode active shutdown ! RP/0/RP0/CPU0:router(config)#show configuration merge int TenGigE 0/0/0/29 Mon Nov 7 15:07:53.584 CET interface TenGigE0/0/0/29 shutdown !
How can the diff be correct for TenGigE0/0/0/28
but incorrect for
TenGigE0/0/0/29
while they have the same configuration? How can you trust the
diff
command if it forgets part of the configuration?
Do you remember the last time you ran an Ansible playbook and discovered the
whole router ospf
block disappeared without a warning? If you use automation
tools, you should check how the diff is assembled. Automation tools should build
it from the result of show running-config
and show configuration merge
. This
is what NAPALM does. This is not what cisco.iosxr
collection for Ansible does.
The problem is not limited to the interface
directives. You can get similar
issues for other parts of the configuration. For example, here is what we get
when removing inactive BGP neighbors on IOS XR 7.2.2:
RP/0/RP0/CPU0:router(config)#router bgp 65400 RP/0/RP0/CPU0:router(config-bgp)#vrf public RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.66.1 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.66.75 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.66.110 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.66.112 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.66.158 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.67.10 RP/0/RP0/CPU0:router(config-bgp-vrf)#no neighbor 217.29.67.15 RP/0/RP0/CPU0:router(config-bgp-vrf)#show commit changes diff Tue Aug 2 13:58:02.536 CEST Building configuration... !! IOS XR Configuration 7.2.2 router bgp 65400 vrf public - neighbor 217.29.66.1 - remote-as 16004 - use neighbor-group MIX_IPV4_PUBLIC - description MIX: MIX-IT ! - neighbor 217.29.66.75 - remote-as 49367 - use neighbor-group MIX_IPV4_PUBLIC ! - neighbor 217.29.67.10 - remote-as 19679 ! - neighbor 217.29.67.15 - neighbor 217.29.66.112 - remote-as 8075 - use neighbor-group MIX_IPV4_PUBLIC - description MIX: Microsoft - address-family ipv4 unicast - maximum-prefix 1500 95 restart 5 ! ! - neighbor 217.29.66.158 - remote-as 24482 - use neighbor-group MIX_IPV4_PUBLIC - description MIX: SG.GS - address-family ipv4 unicast ! ! ! ! end
The only correct chunk is for neighbor 217.29.66.112. All the others are missing some of the removed lines. 217.29.67.15 is even missing all of them. How bad is the code providing such a diff?
I could go all day with examples such as these. Cisco TAC is happy to open a
case in DDTS, their bug tracker, to fix specific occurrences of this
bug.3 However, I fail to understand why the XR team is not just
providing the diff between show run
and show configuration merge
. The output
would always be correct! 🙄
-
IOS XR has several limitations. The most inconvenient one is the inability to change the AS number in the
router bgp
directive. Such a limitation is a great pain for both operations and automation. ↩︎ -
This command could have been just
show commit
, asshow commit changes diff
is the only valid command you can execute from this point. Starting from IOS XR 7.5.1,show commit changes diff precise
is also a valid command. However, I have failed to find any documentation about it and it seems to provide the same output asshow commit changes diff
. That’s how clunky IOS XR can be. ↩︎ -
See CSCwa26251 as an example of a fix for something I reported earlier this year. You need a valid Cisco support contract to be able to see its content. ↩︎