On Tue, Jun 23, 2026 at 12:15 PM Dumitru Ceara <[email protected]> wrote:

> On 6/23/26 10:47 AM, Ales Musil wrote:
> > The update_test() function only remapped hardcoded
> > table=NUMBER values in the range [LOG_EGRESS_PIPELINE,
> > SAVE_INPORT).  Tables beyond SAVE_INPORT, such as
> > CHK_LB_AFFINITY (78 -> 102), were not patched.  This
> > caused all LB affinity upgrade tests to fail when
> > upgrading from branch-24.03 because the old test files
> > use hardcoded table=78 while the new ovn-controller
> > puts learned flows in table 102.
> >
> > Keep the range-based shift for in-pipeline tables
> > [LOG_EGRESS, SAVE_INPORT) since tests use hardcoded
> > offsets within the pipeline, and add exact remapping
> > for every OFTABLE_ define that changed outside
> > that range.
> >
> > Fixes: 9b2645580c78 ("ci: Run system tests in upgrade scenario.")
> > Assisted-by: Claude Opus 4.6, OpenCode
> > Signed-off-by: Ales Musil <[email protected]>
> > ---
>
> Hi Ales,
>
> Thanks for the fix!
>

Hi Dumitru,

thank you for the review.


>
> >  .ci/ovn_upgrade_utils.py | 77 ++++++++++++++++++++++++++++------------
> >  1 file changed, 54 insertions(+), 23 deletions(-)
> >
> > diff --git a/.ci/ovn_upgrade_utils.py b/.ci/ovn_upgrade_utils.py
> > index f5ae787cb..982bf440b 100755
> > --- a/.ci/ovn_upgrade_utils.py
> > +++ b/.ci/ovn_upgrade_utils.py
> > @@ -410,14 +410,28 @@ def ovn_upgrade_save_ovn_debug(binaries_dir):
> >      return True
> >
> >
> > -def update_test(old_start, old_end, shift, test_file):
> > +def _parse_oftable_defines(lines):
> > +    """Return {name: int_value} for all OFTABLE_ #defines."""
> > +    result = {}
> > +    for line in lines:
> > +        parts = line.split()
> > +        if len(parts) >= 3 and parts[0] == '#define' \
> > +                and parts[1].startswith('OFTABLE_'):
> > +            try:
> > +                result[parts[1]] = int(parts[2])
>
> Nit: I think this breaks on stuff like:
>
> #define OFTABLE_BLAH_VERY_LOOOOONG_NAME \
>     42
>
> But we shouldn't try to roll out a full C parser here so maybe it's fine
> to leave it as is.  It was already the case in ovn_upgrade_extract_info().
>

Yeah we might need to find a better way to do the parsing.


>
> > +            except ValueError:
> > +                pass
> > +    return result
> > +
> > +
> > +def update_test(table_remap, test_file):
> >      with open(test_file, encoding='utf-8') as f:
> >          content = f.read()
> >
> >      def replace_table(match):
> >          table_num = int(match.group(1))
> > -        if old_start <= table_num < old_end:
> > -            return f"table={table_num + shift}"
> > +        if table_num in table_remap:
> > +            return f"table={table_remap[table_num]}"
> >          return match.group(0)
> >
> >      # Replace all table=NUMBER patterns
> > @@ -430,44 +444,61 @@ def update_test(old_start, old_end, shift,
> test_file):
> >  def ovn_upgrade_table_numbers_in_tests_patch(config):
> >      lflow_h = Path('controller/lflow.h')
> >
> > -    if not config.file.new_egress.exists():
> > -        log("No LOG_EGRESS")
> > +    if not config.file.ofctl_defines.exists():
> > +        log("No ofctl defines file")
> >          return False
> >
> >      if not lflow_h.exists():
> >          log("Controller/lflow.h not found")
> >          return False
> >
> > -    with open(config.file.new_egress, encoding='utf-8') as f:
> > -        new_log_egress = int(f.read().strip())
> > +    # Get new OFTABLE values (saved from the current version).
> > +    with open(config.file.ofctl_defines, encoding='utf-8') as f:
> > +        new_defines = _parse_oftable_defines(f.readlines())
> >
> > -    # Get old values from base version's lflow.h
> > +    # Get old OFTABLE values from the base version's lflow.h.
> >      with open(lflow_h, encoding='utf-8') as f:
> > -        content = [
> > -            line.strip() for line in f if line.startswith('#define
> OFTABLE_')
> > -        ]
> > +        old_defines = _parse_oftable_defines(f.readlines())
> >
> > -    old_log_egress, old_save_inport = extract_oftable_values(content)
> > +    old_log_egress, old_save_inport = extract_oftable_values(
> > +        [f"#define {k} {v}" for k, v in old_defines.items()])
>
> This feels like over-engineering it TBH.  Isn't this simpler and also
> correct?
>
> old_log_egress = old_defines.get('OFTABLE_LOG_EGRESS_PIPELINE')
> old_save_inport = old_defines.get('OFTABLE_SAVE_INPORT')
>
> With this addressed, the rest looks good to me, thanks!
>

That should be enough indeed.


>
> Acked-by: Dumitru Ceara <[email protected]>
>
> Regards,
> Dumitru
>
> >
> > -    if (not old_log_egress or not old_save_inport
> > -            or old_log_egress == new_log_egress):
> > -        log(f"No change in test files as
> old_log_egress={old_log_egress}, "
> > -            f"old_save_inport={old_save_inport} and "
> > -            f"new_log_egress={new_log_egress}")
> > -        # No change needed is success.
> > -        return True
> > +    if not old_log_egress or not old_save_inport:
> > +        log("Could not extract LOG_EGRESS / SAVE_INPORT from base")
> > +        return False
> > +
> > +    new_log_egress = new_defines.get('OFTABLE_LOG_EGRESS_PIPELINE')
> > +
> > +    # Build {old_value: new_value} remap for all changed tables.
> > +    table_remap = {}
> >
> > -    shift = new_log_egress - old_log_egress
> > +    # Range-based shift for in-pipeline tables [LOG_EGRESS,
> SAVE_INPORT).
> > +    # These include hardcoded offsets that are not OFTABLE_ defines.
> > +    if new_log_egress and new_log_egress != old_log_egress:
> > +        shift = new_log_egress - old_log_egress
> > +        for t in range(old_log_egress, old_save_inport):
> > +            table_remap[t] = t + shift
> > +
> > +    # Exact remap for every OFTABLE_ define that changed and is
> > +    # outside the pipeline range (e.g. CHK_LB_AFFINITY, ECMP_NH).
> > +    for name, old_val in old_defines.items():
> > +        if name in new_defines and new_defines[name] != old_val:
> > +            if old_val not in table_remap:
> > +                table_remap[old_val] = new_defines[name]
> > +
> > +    if not table_remap:
> > +        log("No table number changes detected")
> > +        return True
> >
> > -    log(f"Updating hardcoded table numbers in tests (shift: +{shift}
> for "
> > -        f"tables {old_log_egress}-{old_save_inport - 1})")
> > +    log(f"Updating hardcoded table numbers in tests "
> > +        f"({len(table_remap)} table(s) remapped)")
> >
> >      # Update test files
> >      for test_file in ['tests/system-ovn.at', 'tests/system-ovn-kmod.at
> ',
> >                        'tests/system-ovn-netlink.at']:
> >          if Path(test_file).exists():
> >              log(f"Updating {test_file}")
> > -            update_test(old_log_egress, old_save_inport, shift,
> test_file)
> > +            update_test(table_remap, test_file)
> >      return True
> >
> >
>
>
With the fix above applied to main and 26.03.

Regards,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to