summaryrefslogtreecommitdiff
path: root/python
AgeCommit message (Collapse)Author
16 hoursdhcp-server: T9267: make client-class substring matching contains-anywhereRuben Herold
The Mikrotik configuration referenced by T9267 uses matching-type=substring, documented to match the value anywhere within the option string. This PR's "substring" match instead compared a fixed-length slice at a fixed byte offset (default 0) for exact equality - effectively an anchored prefix match, not a substring search - which does not reliably reproduce the ticket's own use case of picking a device model string (e.g. "T42S") out of a longer, variably-formatted hostname. Rebuild "hostname substring"/"vendor-class-id substring" on Kea's match()+lcase() instead of substring()==, so a configured value now matches anywhere in the option content and case-insensitively (options like vendor-class-id are not guaranteed to arrive in a fixed case). Drop the "offset" leaf together with it, since it has no remaining purpose once matching is no longer anchored to a fixed position, and there is no released behavior to preserve. Raw hex input and values containing a literal single quote are rejected for substring matching in verify(), since neither can be safely embedded into the generated Kea regular expression; exact "value" matching is unaffected and still accepts both. Reported by alexk37 in review of PR #5436.
16 hoursdhcp-server: T9267: drop standalone substring "length" optionRuben Herold
The byte length compared by a hostname/vendor-class-id "substring" match is always derived from "value" for a meaningful equality test: a shorter length never matches (comparing fewer option bytes against the full value literal), and a longer one is silently clamped by Kea to the available bytes, turning what looks like a prefix match into an exact match of the whole remainder. There is no legitimate use for setting it independently of "value", so drop the leaf rather than add another verify() constraint around it. Reported by alexk37 in review of PR #5436.
16 hoursdhcp-server: T9267: fix substring default length for odd hex digit countRuben Herold
The auto-computed substring length floored instead of rounding up, so a value like 0x1 produced substring(..., 0, 0) - an always-empty comparison that can never match, even though Kea itself pads 0x1 to the single byte 0x01. Round up to match Kea's own padding behavior. Found by CodeRabbit review on PR #5436.
16 hoursdhcp-server: T9267: add client-class matching on hostname/vendor-class-idRuben Herold
Client classes could previously only match on relay agent information (Option 82). Add matching on the client-sent hostname (Option 12) and vendor class identifier (Option 60), each with an exact-value or substring form, so clients sharing a subnet can be told apart by e.g. device model without splitting the subnet into per-model pools. Also let a client-class deliver its own options (reusing the existing subnet/range option syntax), so a match can directly hand out a model-specific value such as a provisioning URL, independent of which pool the client's lease is drawn from.
35 hoursMerge pull request #5550 from c-po/T9453-http-api-reload-readyJohn Estabrook
http-api: T9453: wait for the API server to be ready after a reload
36 hoursMerge pull request #5478 from jestabro/rdep-interfaceDaniil Baturin
T7886: add a general method for verifying interface reverse dependencies
44 hoursMerge pull request #5552 from c-po/T9456-container-kernel-overlayfsNataliia S.
container: T9456: use kernel overlayfs unless storage sits on overlayfs
3 daysMerge pull request #5546 from natali-rs1985/T9161-fix-smoketestJohn Estabrook
vpp: T9161: Fix smoketests failing on NICs capped at 1500 MTU
4 daysMerge pull request #5539 from c-po/T9253-anycast-gw-shared-macKyrylo Yatsenko
pseudo-ethernet: T9253: fix anycast-gateway with shared MAC on bridge VLANs
4 daysMerge pull request #5487 from ar0311/fix/T9332-geoip-src-dst-set-collisionChristian Breunig
firewall: T9332: fix GeoIP source/destination nftables set name colli…
4 daysMerge pull request #5545 from rnavarro/fix/ospf-metric-type-defaultChristian Breunig
ospf: T9448: do not render metric-type when it is the default
5 dayscontainer: T9456: use kernel overlayfs unless storage sits on overlayfsChristian Breunig
Since T5003 every system was configured to mount container storage via fuse-overlayfs. This is only needed on live boot, where the storage sits on the root overlayfs and podman refuses native overlay. Installed systems keep it on the persistence partition and paid for a userspace FUSE process per container plus a round trip on every file operation. The mount program is now only configured when the storage is backed by overlayfs, otherwise the kernel overlay driver is used. Existing storage keeps using fuse-overlayfs: podman records that a mount program was used, as its layers store whiteouts in a format the kernel driver does not understand. Moving such a system to kernel overlayfs requires resetting the container storage and re-pulling all images.
5 dayshttp-api: T9453: wait for the API server to be ready after a reloadChristian Breunig
A commit that changes an already running HTTP API only signals the server and returns at once. The server then restarts uvicorn asynchronously, and until it listens again requests through nginx fail. A fixed one-second sleep was meant to cover this but is too short on slow systems, making the https smoketest fail intermittently and API clients see errors right after a commit. The server now creates a readiness marker once it accepts requests. The commit clears the marker before reloading and waits for it to reappear, warning if that takes longer than 30 seconds.
7 daysospf: T9448: do not render metric-type when it is the defaultRobert Navarro
With metric-type 2 (the CLI default), every FRR reload deletes and re-adds "default-information originate" and every "redistribute" line under "router ospf". ospfd flushes the Type-5 LSAs on the delete and re-originates them right after, so neighbours can briefly lose the external routes on commits that do not touch OSPF. ospfd and ospf6d (for redistribute) write "metric-type 1" back to the running config and print nothing for type 2, their default. The templates render "metric-type 2", so frr-reload sees a different line on every reload. frrender now adds the XML default of metric-type to the OSPF and OSPFv3 dicts as xml_default_metric_type, for the default and every VRF instance. The templates render metric-type only when it differs from that default, so the generated config matches what FRR prints back. OSPFv3 default-information keeps rendering metric-type, as ospf6d prints it for both types. Add smoketests that read the generated config and vtysh for types 2, 1 and back to 2. Rename the "ptotocol" loop variable in test_protocols_ospf.py to "protocol", which the typos check flags on any change to this file.
7 daysMerge pull request #5502 from natali-rs1985/T6304John Estabrook
config-management: T6304: Rewrite commit-archive location into a structured CLI
7 daysvpp: T9161: Fix smoketests failing on NICs capped at 1500 MTUNataliia Solomko
VPP now rejects an MTU above the NIC limit, but the CI NICs are capped at 1500, so tests using MTU 2500 on eth1 failed. The rejected commit also left a queued initial VPP dependency in the commit daemon, which the next commit ran with the old config, so every following test failed too. Pending initial dependents are now cleared before each script run in vyos-configd and vyos-commitd, and the tests use MTUs that fit any NIC.
7 daysMerge pull request #5366 from l0crian1/urpf-refactorViacheslav Hletenko
interfaces: T9152: Refactor source-validation to use vmaps
7 dayspseudo-ethernet: T9253: fix anycast-gateway with shared MAC on bridge VLANsChristian Breunig
Several anycast-gateway pseudo-ethernets with the same MAC on different VLANs of one bridge (the usual EVPN layout) failed to commit with "bridge fdb add ... File exists". The local FDB entry was always installed without a VLAN, so every interface competed for the same entry. A failing commit at boot left only one interface configured and dropped the rest of the config. The local FDB entry is now bound to the VLAN of the bridge sub-interface when the bridge is VLAN aware, and it is installed with replace so a re-commit over an existing entry no longer fails. Two anycast-gateways with the same MAC on the same source-interface are rejected.
8 daysT7886: add concatenation of vif entriesJohn Estabrook
8 daysT7886: add verification of reverse dependenciesJohn Estabrook
Suggested-by: l0crian1 <ryan.claridge13@gmail.com>
8 daysT7886: add supporting functions for calculation of reverse dependenciesJohn Estabrook
8 daysT7886: T9231: add missing conversion in get_ownerJohn Estabrook
8 daysvpp: T9161: Enforce NIC MTU limit and apply MTU to VLAN sub-interfacesNataliia Solomko
On a VPP-bound interface the MTU limit is the NIC's, which only VPP knows (the kernel side is an LCP tap reporting a meaningless larger max). Reject at commit an MTU larger than that limit, read from VPP's 'show hardware-interfaces' (max mtu + driver frame overhead), so the kernel and dataplane cannot silently end up with different MTUs. Also apply a VLAN sub-interface's MTU to its VPP dataplane sub-interface and its linux-cp tap (created with MTU 0), not just the parent; a sub-interface without its own MTU inherits the parent's. Covers ethernet (vif/vif-s) and VPP bond/loopback (vif).
8 daysMerge pull request #5520 from c-po/T9278-frr-render-without-configdChristian Breunig
configd: T9368: reconcile FRR after a DHCP lease without the commit socket
8 daysMerge pull request #5523 from mandelbitdev/T9370-openvpn-chacha20poly1305Christian Breunig
openvpn: T9370: add chacha20poly1305 data cipher
8 daysfrrender: T9368: reconcile FRR after a DHCP lease without the commit socketChristian Breunig
Reconciling the FRR configuration after a DHCP lease event was requested from the configuration daemon over the socket the commit pipeline uses. The daemon serves one client at a time and assumes it is the running commit, so the request either landed in the middle of the handshake which hands over the configuration, or kept the daemon busy past the 10ms a commit waits for it. Either way the commit fell back to running the conf-mode scripts directly. Those never render FRR, only the daemon does, so the commit succeeded while FRR kept the configuration rendered before it, until the next lease event. A lease event now renders FRR in its own process, and a commit which could not use the daemon renders FRR itself instead of skipping the reload. Both take the same lock. A commit post-hook would remove the second case, for a full render on every commit.
8 daysMerge pull request #5536 from alexk37/bgp-default-local-pref-100Christian Breunig
bgp: T9404: do not render "bgp default local-preference" when the value is 100
9 daysMerge pull request #5442 from ritika0313/T9328-v1x-blast-radiusViacheslav Hletenko
T9351: Accel-PPP-NG: Add CLI support for Message Authenticator attribute in Access packets (Blast-RADIUS mitigation)
9 daysconfig-management: T6304: Rewrite commit-archive location into a structured CLINataliia Solomko
Replace the free-form 'commit-archive location <url>' leafNode with a structured, per-destination tagNode: `set system config-management commit-archive location <name> <protocol> \ authentication { username | password } | server | port | path` Each location selects exactly one transport protocol (scp, sftp, ssh, ftp, ftps, http, https, git, tftp). 'git' additionally accepts a 'transport' (https/http/ssh, default https). 'source-address' and 'vrf' stay under 'commit-archive' and apply to every location, as before.
9 daysbgp: T9404: do not render "bgp default local-preference" when the value is 100Alex Kudentsov
FRR does not print "bgp default local-preference 100" in show running-config because 100 is its default, so frr-reload never finds the line in the running config and sends it again on every reload. The command handler calls bgp_clear_star_soft_in() whether or not the value changed, so every reload ran "clear bgp * soft in" (once in pass 0 and twice in pass 1), a full inbound re-evaluation of every peer. Add the default (100) to the XML definition of parameters default local-pref. Templates cannot query the XML definition while rendering, so frrender takes the value from the config defaults of "parameters default" (conf.get_config_defaults) and adds it to the BGP dict as the key xml_default_local_pref, for the global instance and for every VRF instance. bgpd.frr.j2 renders the line only when the configured value differs from xml_default_local_pref, so the value 100 is not hardcoded in the template. A real value change (100 to 200, or 200 to 100) is still sent: frr-reload sees the difference between the rendered file and the running config.
10 daysop-mode: T861: add "show secure-boot detail" commandChristian Breunig
"show secure-boot" only reported whether Secure Boot is enabled, not who signed the running Linux Kernel. An image signed by the VyOS CA could not be told apart from one signed with a custom Machine Owner Key. "show secure-boot detail" now lists issuer and subject of the Kernel image signature certificates. The same information is added to the raw "show version" data as "secure_boot_detail", issuer and subject delimited by ",". The key is only present when Secure Boot is enabled and a signature could be read.
10 daysMerge pull request #5533 from alexk37/config-mgmt-hook-read-onceChristian Breunig
config-mgmt: T9399: read the committed config once in the post-commit hooks
11 daysMerge pull request #5524 from alexk37/frrender-no-second-saveChristian Breunig
frrender: T9377: do not save the FRR configuration a second time
11 daysMerge pull request #5532 from c-po/T9395-pppoe-frr-default-routeChristian Breunig
pppoe: T9395: render default routes via FRR only
11 daysconfig-mgmt: T9399: read the committed config once in the post-commit hooksAlex Kudentsov
01vyos-commit-revision built a full Config() in ConfigMgmt() (active and working config, the working one read through the session's unionfs-fuse) and then ran vyos-save-config.py, which built a second full Config() to write the same active config out. On a config with a 2,000-entry prefix-list the hook took 17 s of every commit. The hooks run after the active config has been written, so read it once from the active store, and write the archive copy and config.json from the tree already held. The read is made as ConfigSourceSession makes it (stdout only, unmodified), and as there, no running config is passed until the boot configuration is complete, so the boot commit's hooks see no effective values and 02vyos-commit-archive uploads nothing at boot. After a commit that does not end in COMMIT_STATUS=SUCCESS (PARTIAL in the tests; a conf_mode script failure gives PARTIAL, and FAILURE takes the same branch) the hooks read the config the stock way (a full Config() of the working config); only the archive copy is still written from that tree in-process instead of by vyos-save-config.py. vyatta-cfg's discard removes the session's changes underneath the unionfs-fuse mount, and a set within about a second of it fails while the kernel still caches the removed directories; the stock hook takes longer than that and so hides it. A faster hook after a failed commit made smoketest test_bgp_27_route_reflector_client fail; on stock it fails the same way with 01vyos-commit-revision removed. confirm and initialize_revision use the same archive helper, so they also write the archive copy from the tree already held instead of starting vyos-save-config.py.
12 dayspppoe: T9395: render default routes via FRR onlyChristian Breunig
Deleting a PPPoE interface shortly after its session came up could fail the commit with "% could not lock candidate DS". The default routes were installed via vtysh both from the commit and from the asynchronous ppp ip-up hook, so the two FRR sessions raced for the mgmtd lock. The IPv6 default route was also missing from the rendered FRR configuration, so an FRR reload could remove it. Both default routes are now part of the rendered FRR configuration, which vyos-configd applies at the end of every commit. PPPoE no longer calls vtysh.
2026-10-01T9365: add wrappers for reference tree path from config/partial pathJohn Estabrook
2026-10-01Merge pull request #5493 from jestabro/trim-reftree-cachesDaniil Baturin
T9341: Fix consistency of legacy templates, xml_ref cache, and reference tree
2026-10-01frrender: T9377: do not save the FRR configuration a second timeAlex Kudentsov
apply() runs frr-reload.py --reload without --daemon, and in that mode frr-reload.py saves the configuration itself (vtysh "write" to /etc/frr/frr.conf, bind-mounted from /run/frr/config/frr.conf). The following vtysh -n --writeconfig, added by T3217 when VyOS still reloaded one daemon at a time with --daemon, writes the same file again and asks every daemon for its configuration once more. That second round trip comes several seconds after the change was applied. On a large FRR configuration it reaches bgpd after the route-map update timer (5 s) has started a policy walk, and the commit then waits until the walk ends: on a 20,000-line FRR configuration with 100 update groups and 500,000 routes a policy commit took 497.9/501.0 s against 381.1/381.6 s without this second save.
2026-10-01openvpn: T9370: add chacha20poly1305 data cipherAntonio Quartulli
Offer chacha20poly1305 in "encryption data-ciphers" and "encryption data-ciphers-fallback", rendered as CHACHA20-POLY1305 and allowed with DCO.
2026-09-30wwan: T9326: always pre-negotiate the attach-time PDN type before connectAdam Smith
modem_connect() only ran the --3gpp-set-initial-eps-bearer-settings pre-step (added by T9326) when the requested ip-type included IPv6, gated on options.partition('ip-type=')[2].partition(',')[0] in ('ipv6', 'ipv4v6'). A bare 'ipv4' request skipped it entirely. Confirmed live (same MC7455/Google Fi setup as T9326's original report) that the underlying ip-version-mismatch rejection isn't IPv6-specific: with the attach committed to ip-type=ipv6, a bare ip-type=ipv4 --simple-connect fails outright with the same QMI CallEndReason, not just the ipv4v6 case's silent single-family drop. A WWAN interface whose configured address family changes (e.g. dropping dhcpv6 down to dhcp-only) can hit exactly this, and won't self-heal on retry since nothing about a failed connect touches the attach-committed PDN type - vyos-netlinkd's reconcile loop would back off and retry the identical failing request forever. Removed the gate entirely: the pre-step already fails silently and falls through unchanged on a modem/network that doesn't need it, so there's no reason to skip it for any particular family.
2026-09-30Merge pull request #5483 from yzguy/wwan-modem-by-port-ownershipChristian Breunig
wwan: T7487: identify modem by port ownership, not interface number
2026-09-30wwan: T7487: catch malformed mmcli JSON, not just OSErrorAdam Smith
mmcli can return empty or non-JSON output while ModemManager is still starting (T6604), and json.loads() raising on that is a ValueError, not an OSError - it was propagating straight out of _modem_owning_port() uncaught. Under wait=True that reaches wait_for()'s callback and aborts the poll loop instead of retrying, exactly the startup race this module exists to ride out. Co-authored-by: Christian Breunig <christian@breunig.cc>
2026-09-29ethtool: T9353: fix BASEX mode(s) support in check_speed_duplex()_mrplow
Bugfix which allows for BaseX link modes reported by ethtool to be correctly validated, so config can be commited.
2026-09-29wwan: T7487: move json/wait_for imports into their only callersAdam Smith
Requested by c-po: json.loads and wait_for were only used by _modem_owning_port() and modem_index()'s wait branch respectively, so importing them at module level cost every other caller of this module an import it does not need.
2026-09-29wwan: T7487: only wait for a modem in start_modem_manager()Adam Smith
modem_index() unconditionally polled for up to modem_wait_timeout before returning None, so every caller that expects "no modem" as a routine outcome - interface teardown, admin-disconnect markers, disconnect/connect status checks, and vyos-netlinkd's reconcile loop checking every configured interface once per pass - blocked on it too. The reconcile loop in particular calls is_wwan_connected() synchronously, not per-interface, so one interface with no modem stalled the whole daemon's reconcile pass, including unrelated DHCP interfaces, every cycle. Add a wait parameter, default False (single check, returns immediately). Only start_modem_manager() passes wait=True, where waiting for a still-initializing modem is the actual point.
2026-09-29wwan: T7487: identify modem by port ownership, not interface numberAdam Smith
modem_index() in python/vyos/utils/wwan.py derived the ModemManager modem index straight from the interface name (wwan0 -> 0). The kernel-assigned WWAN interface number and ModemManager's own modem index are two independently enumerated values and are not guaranteed to match - on a box with more than one modem, they can enumerate in different orders, so modem index 0 does not necessarily own wwan0. Every function in this module funnels through modem_index() (start_modem_manager, modem_disconnect, modem_connect, and both admin-disconnect marker helpers), and is_wwan_connected() in vyos.utils.network had its own separate copy of the same assumption - so a single reversed enumeration order silently commands the wrong physical modem for every one of them. modem_index() now lists every modem ModemManager currently knows about and returns whichever one actually has ifname in its own port list, instead of assuming the correspondence. A modem that has not shown up on the bus yet looks the same as one that will never exist, so this waits up to the same modem_wait_timeout budget start_modem_manager() already gives a modem to become dialable, then returns None if nothing claimed the interface. is_wwan_connected() now calls the same resolver instead of keeping its own copy of the old assumption. None is a real, expected return now, not just a theoretical one - the three callers that previously assumed modem_index() always produced *a* string (right or wrong) are updated: start_modem_manager() bails out early (matching the tolerance its own caller's w.exists() check already has for hardware that isn't detected yet), modem_disconnect() and modem_connect() treat it as nothing to disconnect / a failed dial, matching each function's own existing return contract. show_wwan.py's modem_info() raises a clear, specific error instead, which its own top-level exception handler already reports cleanly. set_admin_disconnected()/clear_admin_disconnected() only ever used modem_index() to validate the interface name looks like a WWAN interface in the first place, so they're unaffected.
2026-09-29T9351: Fix lint errors (includes fixes for other areas of code in the files ↵Ritika Chopra
not related to T9351)
2026-09-29T9351: Accel-PPP-NG: RADIUS: CLI support for Message Authenticator attribute ↵Ritika Chopra
in Access packets Add CLI options to control Message-Authenticator handling for Access packets. The new options allow including Message-Authenticator in Access-Request packets and requiring it in Access-Accept, Access-Reject and Access-Challenge responses. Render the corresponding accel-ppp-ng configuration options and warn when response validation is configured as required while Access-Request packets are not configured to include Message-Authenticator.
2026-09-29Merge pull request #5499 from c-po/wwan-improvementsChristian Breunig
wwan: T9350: possible dead interface after boot, disconnect does not stick