Page MenuHomeVyOS Platform

[1.3->1.4 Migration] An empty interface configuration drops all interfaces configuration
Needs reporter action, HighPublicBUG

Description

1. Migration from 1.3.5 to 1.4.0-epa2
An empty vif interface drops all vif's configuration during migration from 1.3.5 to 1.4.0-epa2
Configuration 1.3.5

interfaces {
    ethernet eth0 {
        address 192.168.0.1/24
        vif 2
        vif 800 {
            address 192.168.1.1/24
        }
        vif 801 {
            address 192.168.2.1/24
        }
    }
    loopback lo
}

After migration all vifs configs under this interface are empty.
If we change from vif 2 to vif 2 {} in the configuration manually then migration passes.

2. Migration from 1.3.5 to 1.5 (1.5-rolling-202405010020)

The same config from 1.3.5
After migration, there is only a loopback interface in the configuration. Interface eth0 is absent.
If we change from loopback lo to loopback lo {} in the configuration manually then interfaces appear but vifs not.
After
If we change from vif 2 to vif 2 {} in the configuration manually then migration passes.

Details

Difficulty level
Unknown (require assessment)
Version
VyOS 1.5-rolling-202405010020, VyOS 1.4.0-epa2
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

a.apostoliuk created this task.
c-po changed the task status from Open to In progress.Fri, May 3, 4:07 PM
c-po claimed this task.

How was this configuration achieved? Or is it manually crafted?

c-po changed the task status from In progress to Needs reporter action.Wed, May 8, 4:05 PM

Migration requires the config file to be in the standard syntax, such as produced by the system itself (set/del; commit; save) --- in this case, a configuration that can be loaded and saved on VyOS 1.3.5 would not be missing braces as above. If one needs to hand edit a config file, at the very least one needs to load/save on the source system before migration. The only weird corner case, linked above, is when a change of mac address triggers a rewrite by the ealry-legacy parser (only used in <= 1.3.x, and only in one remaining place in 1.3.x: vyatta_interface_rescan) --- that does produce incorrect syntax and is a known problem as described in the comment in T5611; that case is also restored by saving the config on the source image before system update and the resulting migration on reboot.

Checking a recent 1.5 build (1.5-rolling-202405090225), I do not see the discrepancy mentioned in the description: the result for 1.5 is also (just) missing vif entries, and one can observe that the syntax error in vif 2 causes cascading syntax errors in the other vif sections.
The following script recreates the effect of the XorpConfigParser:

#! /usr/bin/perl

use strict;
use lib "/opt/vyatta/share/perl5/";
use Sys::Syslog qw(:standard :macros);
use XorpConfigParser;

sub xorp_write {
    my ($INFILE, $OUTFILE) = @_;

    # parse config input file
    my $xcp = new XorpConfigParser();
    $xcp->parse($INFILE);

    # write config output file
    open (my $out, '>', $OUTFILE)
    or die "Can't open $OUTFILE : $!";

    select $out;
    $xcp->output(0);
    select STDOUT;
    close $out;
}

die "xorp-write needs two args: input_file output_file"
    unless ($#ARGV == 1);

xorp_write(@ARGV);
exit 0;

The result on the lines in question (example.config is syntactically sound; xorped.config is not):

└──> diff -C 2 example.config xorped.config
*** example.config      2024-05-12 19:26:59.377107781 -0500
--- xorped.config       2024-05-12 19:36:30.562143990 -0500
***************
*** 7,12 ****
          address 192.168.0.1/24
          hw-id 52:54:00:c1:df:f9
!         vif 2 {
!         }
          vif 800 {
              address 192.168.1.1/24
--- 7,11 ----
          address 192.168.0.1/24
          hw-id 52:54:00:c1:df:f9
!         vif 2
          vif 800 {
              address 192.168.1.1/24
***************
*** 16,21 ****
          }
      }
!     loopback lo {
!     }
  }
  service {
--- 15,19 ----
          }
      }
!     loopback lo
  }
  service {
***************

This leads to failed parsing for the whole vif subsection:

In [1]: from vyos.configtree import ConfigTree

In [2]: with open('./example.config') as f:
   ...:     example_config_str = f.read()
   ...: 

In [3]: example_ct = ConfigTree(example_config_str)

In [4]: example_vif = example_ct.get_subtree(['interfaces', 'ethernet', 'eth1', 'vif'], with_node=True)

In [5]: print(example_vif.to_string())
vif 2 {
}
vif 800 {
    address "192.168.1.1/24"
}
vif 801 {
    address "192.168.2.1/24"
}

In [6]: with open('./xorped.config') as f:
   ...:     xorped_config_str = f.read()
   ...: 

In [7]: xorped_ct = ConfigTree(xorped_config_str)

In [8]: xorped_vif = xorped_ct.get_subtree(['interfaces', 'ethernet', 'eth1', 'vif'], with_node=True)

In [9]: print(xorped_vif.to_string())
vif {
    800 {
        address "192.168.1.1/24"
    }
    801 {
        address "192.168.2.1/24"
    }
}

The second format is incorrect for tag nodes.