Skip to content

sonic: regen drops default-VRF BGP_GLOBALS/BGP_GLOBALS_AF/BGP_GLOBALS_ROUTE_ADVERTISE entries, breaking EVPN route advertisement #2515

Description

@berendt

Summary

Since the table-ownership enforcement (953be8a, refined in #2339), generate_sonic_config() drops the content of every owned table up front and rebuilds it from NetBox data and hardcoded policy. BGP_GLOBALS, BGP_GLOBALS_AF, and BGP_GLOBALS_ROUTE_ADVERTISE are owned tables (part of SCAFFOLDED_OWNED_TABLE_KEYS), but the generator only repopulates them for VRFs with an EVPN VNI (_add_vrf_configuration). The default-VRF entries that the base config_db.json deliberately ships — introduced in #1937 with the split "default entries in base config_db.json for the default VRF, VRF-specific entries from the generator" — no longer survive regeneration.

Impact

On leaves without VNI VRFs, the regenerated config contains an empty BGP_GLOBALS_AF and an empty BGP_GLOBALS_ROUTE_ADVERTISE. In our production pod, the data leaves consequently stopped advertising default-VRF IPv4 unicast routes into EVPN. All traffic that has to transit the fabric to subnets attached to a different leaf (NetApp NVMe over TCP storage) was silently dropped. Because of per-flow ECMP, roughly half of all new storage connections failed. The result was recurring platform-wide incidents since 2026-06-19 — shortly after the ownership enforcement was rolled out — with aborted VM builds, volumes stuck in deleting, and Octavia load balancers going into ERROR. All interface and error counters stayed clean, which made this very hard to diagnose.

The blast radius is not limited to leaves without VNI VRFs:

  • BGP_GLOBALS|default is replaced wholesale with only router_id/local_asn (config_generator.py:352-372). The base-config attributes — network_import_check, ebgp_requires_policy, holdtime/keepalive, always_compare_med, log_nbr_state_changes, … — are lost on every switch.
  • BGP_GLOBALS_AF default|l2vpn_evpn (advertise-all-vni: true, advertise-svi-ip: true, dad-enabled: true) and default|ipv4_unicast/default|ipv6_unicast (ECMP max_ebgp_paths/max_ibgp_paths) are never regenerated for the default VRF, on any switch.
  • The per-VRF BGP_GLOBALS entries are deep-copied from the thinned-out default entry (config_generator.py:2159-2163), so VNI VRFs inherit the attribute loss as well.

Root cause

  1. Add BGP_GLOBALS_ROUTE_ADVERTISE for L2VPN_EVPN in SONIC #1937 (71b834c, 2026-01-14) added the default-VRF entries (BGP_GLOBALS|default attributes, BGP_GLOBALS_AF default|*, BGP_GLOBALS_ROUTE_ADVERTISE default|L2VPN_EVPN|IPV4_UNICAST / …|IPV6_UNICAST) to files/sonic/config_db.json, which the Containerfile installs as /etc/sonic/config_db.json — the base config every regen starts from. The generator was only extended to emit the VRF-specific entries.
  2. 953be8a (2026-06-02) introduced the ownership model: all owned tables are popped up front (config_generator.py:323-324) and rebuilt from scratch; BGP_GLOBALS|default is assigned wholesale instead of merged. sonic: Enforce config table ownership statically #2339 (8718b2f) added the static guard test that cements this classification.
  3. Nothing in the generator recreates the default-VRF entries: BGP_GLOBALS_AF and BGP_GLOBALS_ROUTE_ADVERTISE are only written in _add_vrf_configuration for VRFs with a VNI (config_generator.py:2113-2141).

The ownership enforcement and the "defaults live in the base config" convention from #1937 are mutually exclusive, and the enforcement won.

Expected behavior

Regenerated configs still contain the default-VRF entries: either the generator emits them itself for the default VRF, or these tables get inherited/merge semantics for the default|* keys.

Actual behavior

The owned-table semantics drop the base-config content; only entries for VRFs with a VNI are regenerated.

Reproduction

Regenerate the SONiC config for any switch without VNI VRFs and diff the BGP_GLOBALS* tables against files/sonic/config_db.json: BGP_GLOBALS_AF and BGP_GLOBALS_ROUTE_ADVERTISE come back empty, BGP_GLOBALS|default contains only router_id and local_asn.

Suggested fix

Under the ownership model, operator- or image-provided content in owned tables is explicitly unsupported, so the consistent fix is for the generator to own the default-VRF entries too: emit the BGP_GLOBALS|default attributes, the BGP_GLOBALS_AF default|ipv4_unicast / default|ipv6_unicast / default|l2vpn_evpn entries, and the BGP_GLOBALS_ROUTE_ADVERTISE default|L2VPN_EVPN|IPV4_UNICAST / …|IPV6_UNICAST entries as hardcoded SONiC policy (values as currently shipped in files/sonic/config_db.json), and drop the then-redundant entries from the base config. The per-VRF BGP_GLOBALS copy then picks up the full attribute set again automatically.

A regression test should assert that a device without VNI VRFs still gets the default-VRF entries in all three tables.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions