Page MenuHomeVyOS Platform

FRR 7.5 adds a second route when you attempt to change a static route distance instead of overwriting the old route
Closed, ResolvedPublicBUG

Description

Frr 7.5.1 has different behavior for static routes
For example such configuration:

VyOS

set protocols static route 10.0.0.0/8 next-hop 192.0.2.2
commit
set protocols static route 10.0.0.0/8 next-hop 192.0.2.2 distance '200'
commit

FRR see it as "multinode" as 2 separate routes (Frr 7.5.1)

ip route 10.0.0.0/8 192.0.2.2 
ip route 10.0.0.0/8 192.0.2.2 200

Frr 7.3 see it as 1 route

!
ip route 10.0.0.0/8 192.0.2.2 200
!
line vty
!

So we need to rewrite our node handlers for it
https://github.com/vyos/vyatta-cfg-quagga/blob/equuleus/templates/protocols/static/route/node.tag/next-hop/node.def
https://github.com/vyos/vyatta-cfg-quagga/blob/equuleus/templates/protocols/static/interface-route/node.tag/next-hop-interface/node.def
In other words we can't delete static routes in 7.5.1 now for 1.3 with distance

set protocols static interface-route 10.0.0.0/8 next-hop-interface dum08765
set protocols static route 10.0.0.0/8 next-hop 192.0.2.2
commit
set protocols static interface-route 10.0.0.0/8 next-hop-interface dum08765 distance '200'
set protocols static route 10.0.0.0/8 next-hop 192.0.2.2 distance '200'
commit
del protocols
commit

vtysh

!
ip route 10.0.0.0/8 192.0.2.2 200
ip route 10.0.0.0/8 dum08765 200
!
line vty
!

Smoketest fail for routes with distance

07:23:08  DEBUG - Running Testcase: /usr/libexec/vyos/tests/smoke/cli/test_protocols_static.py
07:23:17  DEBUG - test_interface_routes (__main__.StaticRouteTest) ... ok
07:23:23  DEBUG - test_static_routes (__main__.StaticRouteTest) ... FAIL
07:23:23  DEBUG - 
07:23:23  DEBUG - ======================================================================
07:23:23  DEBUG - FAIL: test_static_routes (__main__.StaticRouteTest)
07:23:23  DEBUG - ----------------------------------------------------------------------
07:23:23  DEBUG - Traceback (most recent call last):
07:23:23  DEBUG -   File "/usr/libexec/vyos/tests/smoke/cli/test_protocols_static.py", line 112, in test_static_routes
07:23:23  DEBUG -     self.assertTrue(found)
07:23:23  DEBUG - AssertionError: False is not true

Because in the "test_interface_routes" expect one route (node "dev")

{
   "type":"unicast",
   "dst":"10.0.0.0/8",
   "nhid":41,
   "dev":"dum08765",
   "protocol":"static",
   "scope":"global",
   "metric":20,
   "flags":[
      
   ]

But get 2 routes (one route with distance was not deleted)

{
   "type":"unicast",
   "dst":"10.0.0.0/8",
   "nhid":243,
   "protocol":"static",
   "scope":"global",
   "metric":20,
   "flags":[
      
   ],
   "nexthops":[
      {
         "dev":"dum08765",
         "weight":1,
         "flags":[
            
         ]
      },
      {
         "gateway":"192.0.2.2",
         "dev":"dum08765",
         "weight":1,
         "flags":[
            
         ]
      }
   ]
}

Details

Difficulty level
Normal (likely a few hours)
Version
live-image-amd64.hybrid.iso, VyOS 1.3-beta-202105021529
Why the issue appeared?
Issues in third-party code
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

One solution for it:

vyos_bld@3c88687662fe:/vyos/work/T3516/vyatta-cfg-quagga$ git diff
diff --git a/templates/protocols/static/interface-route/node.tag/next-hop-interface/node.def b/templates/protocols/static/interface-route/node.tag/next-hop-interface/node.def
index f8bc9270..991a30ee 100644
--- a/templates/protocols/static/interface-route/node.tag/next-hop-interface/node.def
+++ b/templates/protocols/static/interface-route/node.tag/next-hop-interface/node.def
@@ -14,7 +14,10 @@ end:
       if ! ${vyatta_sbindir}/vyatta-next-hop-check $VAR(../@) ipv4 interface; then
         exit 1;
       fi
+      DIST=`cli-shell-api returnEffectiveValue protocols static interface-route $VAR(../@) next-hop-interface $VAR(@) distance`
+
       vtysh -c "configure terminal" \
+                   -c "no ip route $VAR(../@) $VAR(@) $DIST" \
                    -c "no ip route $VAR(../@) $VAR(@)"
     else
       if [[ -n "$VAR(./distance/@)" ]]; then
diff --git a/templates/protocols/static/route/node.tag/next-hop/node.def b/templates/protocols/static/route/node.tag/next-hop/node.def
index 0574781d..44a39bfb 100644
--- a/templates/protocols/static/route/node.tag/next-hop/node.def
+++ b/templates/protocols/static/route/node.tag/next-hop/node.def
@@ -16,10 +16,12 @@ end:
       if ! ${vyatta_sbindir}/vyatta-next-hop-check $VAR(../@) ipv4 address; then
         exit 1;
       fi
+      DIST=`cli-shell-api returnEffectiveValue protocols static route $VAR(../@) next-hop $VAR(@) distance`
       if ${vyatta_sbindir}/vyatta-gateway-static_route-check.pl \
           "$VAR(../@)" "$VAR(@)"
       then
         vtysh -c "configure terminal" \
+                     -c "no ip route $VAR(../@) $VAR(@) $DIST" \
                      -c "no ip route $VAR(../@) $VAR(@)"
       fi
     else

And it resolves smoketest and can delete "single" routes with distance

vyos@r4-1.3# /usr/libexec/vyos/tests/smoke/cli/test_protocols_static.py
test_interface_routes (__main__.StaticRouteTest) ... ok
test_static_routes (__main__.StaticRouteTest) ... ok

----------------------------------------------------------------------
Ran 2 tests in 6.712s

OK
[edit]
vyos@r4-1.3#

But it can't solve bug with such configuration:

set protocols static route 10.0.0.0/8 next-hop 192.0.2.2 distance '201'
commit
set protocols static route 10.0.0.0/8 next-hop 192.0.2.2 distance '202'
commit
set protocols static route 10.0.0.0/8 next-hop 192.0.2.2 distance '203'
commit

Show protocols, VyOS shows single node

vyos@r4-1.3# show protocols 
 static {
     route 10.0.0.0/8 {
         next-hop 192.0.2.2 {
             distance 203
         }
     }
 }

Frr 7.5.1 shows "multinode"

!
ip route 10.0.0.0/8 192.0.2.2 203
ip route 10.0.0.0/8 192.0.2.2 202
ip route 10.0.0.0/8 192.0.2.2 201
!
line vty
!
dmbaturin renamed this task from FRR 7.5 static route behavior for 1.3 to FRR 7.5 adds a second route when you attempt to change a static route distance instead of overwriting the old route.May 18 2021, 10:42 PM
dmbaturin changed Why the issue appeared? from Will be filled on close to Issues in third-party code.

This is still reproducible in the FRR master branch, so I've filed an issue: https://github.com/FRRouting/frr/issues/8695

However, I've also found a viable, apparently non-disruptive workaround: running no ip route 192.0.2.0/24 203.0.113.1 1 deletes only the route "without distance".

vyos(config)# ip route 192.0.2.0/24 203.0.113.1
vyos(config)# ip route 192.0.2.0/24 203.0.113.1 200
vyos(config)# do sh ip route 192.0.2.0/24
Routing entry for 192.0.2.0/24
  Known via "static", distance 200, metric 0
  Last update 00:00:06 ago
    203.0.113.1, via eth1, weight 1

Routing entry for 192.0.2.0/24
  Known via "static", distance 1, metric 0, best
  Last update 00:00:08 ago
  * 203.0.113.1, via eth1, weight 1

vyos(config)# no ip route 192.0.2.0/24 203.0.113.1 1
vyos(config)# 
vyos(config)# do sh ip route 192.0.2.0/24
Routing entry for 192.0.2.0/24
  Known via "static", distance 200, metric 0, best
  Last update 00:00:23 ago
  * 203.0.113.1, via eth1, weight 1

Since running no ip route 192.0.2.0/24 203.0.113.1 1 does not cause an error if that route doesn't exist, I think it's safe to always run that command after adding a route with a distance.

One caveat I can think of is that it may be possible to change the default admin distance for static routes. If it is, then we need to take the effective default distance into account.

Viacheslav assigned this task to dmbaturin.
SrividyaA set Issue type to Bug (incorrect behavior).Aug 31 2021, 3:34 PM