Skip to content

[yang-mgmt] Treat empty CONFIG DB leaf-list (['']) as empty so libyang3 accepts empty pattern-constrained leaf-lists#28248

Merged
lguohan merged 1 commit into
sonic-net:masterfrom
deepak-singhal0408:fix/yang-empty-leaflist-38183186
Jul 9, 2026
Merged

[yang-mgmt] Treat empty CONFIG DB leaf-list (['']) as empty so libyang3 accepts empty pattern-constrained leaf-lists#28248
lguohan merged 1 commit into
sonic-net:masterfrom
deepak-singhal0408:fix/yang-empty-leaflist-38183186

Conversation

@deepak-singhal0408

@deepak-singhal0408 deepak-singhal0408 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Why I did it

config apply-patch, config replace and config rollback fail on master for any configuration that contains an empty pattern-constrained leaf-list. BGP_ALLOWED_PREFIXES is the common trigger, because a deployment often populates only prefixes_v4 or only prefixes_v6, leaving the other leaf-list empty.

An empty leaf-list is stored in CONFIG DB as field@ = "". The Python ConfigDBConnector deserialises that empty string into a single empty-string element (['']), which is the CONFIG DB representation of "no elements", not a real element. Before the libyang1 to libyang3 port (#26584) the '' sentinel was tolerated by the validation library. libyang3 validates the '' element against the leaf type's pattern (for example the ipv4-prefix pattern of BGP_ALLOWED_PREFIXES.prefixes_v4) and rejects the whole config:

Unsatisfied pattern - "" does not conform to "(([0-9]| ... )/(([0-9])|([1-2][0-9])|(3[0-2]))( (le|ge) ...)?"
Data path: .../BGP_ALLOWED_PREFIXES_LIST[deployment='DEPLOYMENT_ID'][id='0']/prefixes_v4

This is a read-side (config-to-YANG validation) regression. #26584 did add a guard for the sibling case of an empty leaf-list that has a schema default "", but missed the pattern-typed, no-default leaf-list case (['']), which is exactly BGP_ALLOWED_PREFIXES.

This fixes the read-side regression behind sonic-mgmt test generic_config_updater/test_bgp_prefix.py (tracked by sonic-mgmt issue 25549). It is complementary to, and does not replace, the separate write-side effort that avoids writing prefixes_v4@ = "" into CONFIG DB in the first place (sonic-buildimage issue 27818, sonic-utilities PR 4478). Even with that write-side fix, existing configs and other tables can still present an empty leaf-list, so the validation layer should accept it.

Work item tracking
  • Microsoft ADO (number only): 38183186

How I did it

In the CONFIG DB to YANG translation in src/sonic-yang-mgmt/sonic_yang_ext.py (the leaf-list branch of _findYangTypedValue), drop the empty-string sentinel so an empty leaf-list is represented as an empty list [], which libyang3 accepts. The drop is gated on the leaf-list having no schema default (not list(leaf.defaults())), so the existing empty-with-default handling introduced by #26584 is left byte-for-byte unchanged.

Added a regression unit test (test_empty_leaflist_collapses_to_empty) that loads BGP_ALLOWED_PREFIXES with an empty prefixes_v4 leaf-list and asserts the config validates and the leaf-list collapses to [].

How to verify it

Unit test (sonic-yang-mgmt suite): with the fix the new test passes and the full suite is green; reverting only the two changed lines makes just test_empty_leaflist_collapses_to_empty fail with the Unsatisfied pattern - "" error above.

End-to-end on a KVM t1 testbed (vms-kvm-t1-lag), baseline master image built after #26584 (so it carries the regression), matched before/after with only sonic_yang_ext.py swapped:

DUT state generic_config_updater/test_bgp_prefix.py::test_bgp_prefix_tc1_suite
before (unpatched baseline) 2 failed, 2 errors — config apply-patch returns non-zero, teardown config rollback failed
after (fix applied) 2 passed

Also verified the mechanism directly: with BGP_ALLOWED_PREFIXES|DEPLOYMENT_ID|0 holding prefixes_v4@ = "", a subsequent valid config apply-patch fails with the Unsatisfied pattern - "" error before the fix and succeeds after it.

Which release branch to backport (provide reason below if selected)

  • 202305
  • 202311
  • 202405
  • 202411
  • 202505
  • 202511
  • 202512
  • 202605
  • 202608

Tested branch (Please provide the tested image version)

  • master — SONiC.master.1145536-931dbfb70 (build 2026-06-22)

Description for the changelog

[yang-mgmt] Treat an empty CONFIG DB leaf-list (['']) as empty so libyang3 does not reject empty pattern-constrained leaf-lists such as BGP_ALLOWED_PREFIXES.

Link to config_db schema for YANG module changes

No YANG model change. BGP_ALLOWED_PREFIXES schema: https://github.com/sonic-net/sonic-buildimage/blob/master/src/sonic-yang-models/doc/Configuration.md#bgp_allowed_prefixes

A picture of a cute animal (not mandatory but encouraged)

🦔

… an element

An empty leaf-list is stored in CONFIG DB as `field@ = ""`, which the Python
ConfigDBConnector deserialises to a single empty-string element (['']). This is
the CONFIG DB representation of "no elements", not a real element.

Before the libyang1 -> libyang3 port (sonic-net#26584) the '' sentinel was tolerated by
the validation library. libyang3 validates the '' element against the leaf
type's pattern (e.g. the ip-prefix pattern of BGP_ALLOWED_PREFIXES.prefixes_v4)
and rejects the whole config with:

    Unsatisfied pattern - "" does not conform to <ipv4-prefix> ...

This breaks `config apply-patch` / `config replace` / `config rollback` for any
config that contains an empty pattern-constrained leaf-list (BGP_ALLOWED_PREFIXES
is a common trigger, since a deployment often populates only prefixes_v4 or only
prefixes_v6, leaving the other empty).

Fix: in the config -> YANG translation, drop the empty-string sentinel so an
empty leaf-list is represented as [] (which libyang3 accepts). This is gated on
the leaf-list having no schema default, so the existing empty-with-default
handling (which deliberately rejects the empty representation) is unchanged.

Added a regression unit test that loads BGP_ALLOWED_PREFIXES with an empty
prefixes_v4 leaf-list and asserts it validates and collapses to [].

Signed-off-by: Deepak Singhal <deepsinghal@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 6, 2026 06:48
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run Azure.sonic-buildimage

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression in sonic-yang-mgmt’s CONFIG_DB→YANG translation after the libyang1→libyang3 port: it treats the CONFIG DB empty leaf-list sentinel ([''], originating from field@ = "") as an actual empty leaf-list ([]) so libyang3 does not reject pattern-constrained leaf-lists like BGP_ALLOWED_PREFIXES.prefixes_v4.

Changes:

  • Collapse the [''] empty leaf-list sentinel into [] during _findYangTypedValue() leaf-list conversion (only for leaf-lists without schema defaults).
  • Add a regression unit test covering BGP_ALLOWED_PREFIXES validation and ensuring the sentinel does not survive into the translated data.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/sonic-yang-mgmt/sonic_yang_ext.py Drops the empty-string sentinel when translating leaf-list values to avoid libyang3 pattern validation failures.
src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py Adds a regression test asserting [''] is treated as an empty leaf-list and validation succeeds.

@deepak-singhal0408 deepak-singhal0408 self-assigned this Jul 6, 2026
@deepak-singhal0408

Copy link
Copy Markdown
Contributor Author

This is a read-side fix for the regression from the libyang1->libyang3 port. @bhouse-nexthop @qiluo-msft @vaibhavhd @rimunagala, could you help review the change? Thanks,

@bhouse-nexthop bhouse-nexthop left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This look valid to me, thanks!

@deepak-singhal0408

Copy link
Copy Markdown
Contributor Author

@lguohan @yxieca, could you help merge this PR. thanks,

@deepak-singhal0408

deepak-singhal0408 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

202605 branch verification ✅

Verified this fix on the 202605 release branch with a matched A/B on a KVM t1-lag testbed (vlab-03), 202605 nightly 202605.1157773-9c84048a4 (Debian 13/trixie, Python 3.13 / libyang3). The failing test is xfail-marked (issue 25549), so it was run with --runxfail for a real pass/fail verdict. The patched sonic_yang_ext.py was hot-deployed onto the pristine 202605 image; the yang file is the only variable.

Test: generic_config_updater/test_bgp_prefix.py::test_bgp_prefix_tc1_suite ([None-empty], [None-1010:1010]), --runxfail.

Build tests failures errors
UNFIXED (pristine 202605 sonic_yang_ext.py) 2 2 2
FIXED (patched leaf-list sentinel drop) 2 0 0

regression_confirmed = true, fix_confirmed = true on 202605 — the empty CONFIG DB leaf-list (['']) fails libyang3 validation on the unfixed build (GCU apply-patch errors), and both parametrizations pass with the fix.

@lguohan
lguohan merged commit f837baa into sonic-net:master Jul 9, 2026
29 checks passed
@mssonicbld

Copy link
Copy Markdown
Collaborator

Cherry-pick PR to 202605: #28308

@mssonicbld

Copy link
Copy Markdown
Collaborator

@deepak-singhal0408 cherry pick PR didn't pass PR checker after retry. Please help check! Thanks.
#28308

---Powered by SONiC BuildBot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants