summaryrefslogtreecommitdiff
path: root/python
AgeCommit message (Collapse)Author
2026-09-26python: T8859: fail loudly on an invalid Diffie-Hellman keysize argumentfix/T8859-dh-keysize-validationYuriy Andamasov
The Diffie-Hellman length check stringified the requested minimum keysize into a variable it never used, then converted the original argument again for the comparison. A non-numeric value therefore escaped as an uncaught ValueError from the comparison rather than being reported where it was passed in. The argument is now typed and validated up front: a non-integer raises TypeError, booleans included, and a non-positive integer raises ValueError. Both indicate a logic error in the calling script and should fail loudly instead of silently reporting an undersized key. The only callers today are the unit tests, so the contract is free to change. A file that exists but holds no readable parameters is user input rather than a logic error, and now fails the check instead of propagating the error from openssl. The bit-count pattern becomes a raw string, and the tests pass integer keysizes and cover the new paths.
2026-09-25Merge pull request #5376 from natali-rs1985/T9146Daniil Baturin
vpp: T9146: Enable DPDK no-multi-seg when a full frame fits the buffer
2026-09-25Merge pull request #5500 from c-po/ppp-interface-ipv6-llChristian Breunig
ppp: T9060: do not derive a link-local address from a synthetic MAC
2026-09-24ppp: T9060: do not derive a link-local address from a synthetic MACChristian Breunig
A PPP link has no hardware address. RFC 5072 defines the IPv6 interface identifier of such a link as the one negotiated via IPV6CP, and that negotiation is also what guarantees its uniqueness - which is why duplicate address detection is skipped for the link-local address on PPP links. VyOS additionally derived an EUI-64 link-local address from a synthetic MAC address and assigned it to PPPoE and SSTP client interfaces. The peer knows nothing about that address and its uniqueness was never verified. With two link-local addresses present, RFC 6724 source address selection falls through to rule 8 and may pick the synthetic one, so DHCPv6 prefix delegation and router solicitations leave from an address the BRAS never negotiated. ISPs validating the source address silently drop them and delegation stalls. Both interface types now carry only the address negotiated via IPV6CP. A leftover address on an established session is removed on commit.
2026-09-24Merge pull request #5484 from haakonnore/feat/T9319-vxlan-gbpChristian Breunig
vxlan: T9319: add VXLAN-GBP support
2026-09-22vxlan: T9319: add VXLAN-GBP supportHaakon Nore
Expose the Group Policy extension as a valueless gbp CLI node and pass it to iproute2 when creating VXLAN links. Recreate links when GBP changes and reject configurations combining GBP with GPE. Reject conflicting GBP settings on a shared UDP port, accounting for address families and underlay VRF socket bindings. Warn that external mode carries GBP in tunnel metadata instead of the packet mark. Add smoketest coverage for GBP creation, removal and re-enabling, retained interface settings, rejection without changing the running tunnel, shared ports, separate address families, and external mode.
2026-09-22Merge pull request #5466 from rnavarro/fix/configtree-serialize-libvyosconfigChristian Breunig
configtree: T9307: serialize libvyosconfig calls across threads
2026-09-16smoketest: T9316: do not race the DHCP client when checking VRF membershipChristian Breunig
test_dhcp_vrf and test_dhcpv6_vrf resolved the DHCP client's PID, then read the VRF's process list and asserted the PID appeared in it. The client re-executes itself at moments of its own choosing, so between those two steps it can come back with a new PID - the process is in the VRF, it simply is not the process we asked about: AssertionError: '13502' not found in '14322 dhclient\n 14324 dhclient-script\n 14485 dhclient...' Observed failing and passing on the same image, so it costs a rerun rather than telling anyone anything. get_process_cmdline() already fights the same race for the /proc read. Resolve the PID and read the VRF's list as one step and retry, so a restart costs a retry instead of a failure. The probe itself was also loose: substring-matching the raw output of "ip vrf pids <name>" lets a PID check be satisfied by the process name column or by a longer PID containing ours. Add vyos.utils.network.get_vrf_pids(), which parses the command's "<pid> <name>" lines into (pid, process_name) tuples and returns an empty list for an unknown VRF, and compare the PID field as an int.
2026-09-16Merge pull request #5441 from ordex/T8264-openvpn-dco-lifecycleChristian Breunig
T8264: openvpn dco lifecycle
2026-09-15Merge pull request #5429 from rockfish-vyos/T9254-ike-esnDaniil Baturin
ipsec: T9254: do not emit ESN transforms in IKE proposals
2026-09-15smoketest: T8264: cover adopting a pre-created DCO interfaceAntonio Quartulli
assertDcoDataPath() checks the link kind, the operating mode and that the daemon is up, and none of those change when the offload carries nothing. A client whose server is not up yet never opens its tun, so VyOS creates the "ovpn" device for it and OpenVPN has to adopt that device once the server appears. Get the adoption wrong and the daemon takes the device but not its ifindex: dco_new_peer() fails, the daemon exits and deletes the interface on its way out, systemd starts it again and the second attempt creates a device of its own. The tunnel comes up either way, so the state it ends in proves nothing - the restart it cost does. Ask the Kernel for its peers as well, which is the one thing no amount of userspace bookkeeping can fake.
2026-09-15openvpn: T8264: create the interface type the data path needsAntonio Quartulli
apply() restarts the daemon and then creates the interface itself, as a tun device. OpenVPN declines the offload when it finds a device of the wrong type, so DCO worked only until the first reconfiguration. The Kernel module takes its operating mode at creation time and iproute2 can neither set nor report it, so go through netlink - multipoint for a server, point-to-point otherwise, matching what OpenVPN asks for itself. A server adopting a point-to-point device rejects every client, and the attribute is dropped silently if it is ever unrecognised, so read the mode back. A raw option does not change this. verify() turns away the ones known to drop the offload, and beyond those "openvpn-option" is documented as the user's own responsibility - so an offloaded interface is created either way. A raw option that does decline the offload now leaves the daemon unable to open the device it is given, which is at least visible, rather than quietly carrying traffic in userspace.
2026-09-14ifconfig: T9313: fix removal of QinQ sub-interfacesChristian Breunig
EthernetIf.remove() snapshotted Section.sub_interfaces() once and then removed every entry of that list. For Q-in-Q setups the list contains both the vif-s (eth0.10) and its vif-c children (eth0.10.20), as Section.sub_interfaces() matches every configured interface whose name starts with "<ifname>.". Removing eth0.10 cascades in the Kernel and also deletes eth0.10.20. Once the loop reached eth0.10.20, Interface.__init__() no longer found it and - as "create" defaults to True, re-created it via a bare "ip link add dev eth0.10.20" without any type. This failed and left a stranded interface behind which in turn broke all subsequent smoketests. The same cascade silently killed DHCP clients running on sub-interfaces of any other interface type, as only the interface itself got its addresses flushed: * deletion of a bond or bridge interface carrying vif/vif-s/vif-c * deletion of an entire vif-s, as get_removed_vlans() only populates "vif_c_remove" for a vif-s which still exists in the new configuration Move the sub-interface teardown from EthernetIf.remove() into the base class Interface.remove(), where it benefits every interface type. The list is walked deepest first (vif-c before vif-s/vif), which is what T7813 requires to stop the DHCP client and return the lease, and interfaces which vanished in the meantime are skipped so they are never accidentally re-created. As a side effect of this move, an ethernet interface is now only placed into A/D state after the base class has released the addresses - previously the lease of the interface itself was returned over an already downed link.
2026-09-14Merge pull request #5460 from c-po/T9228-interface-naggingChristian Breunig
ethernet: T9228: only warn about unsupported NIC features when node changed
2026-09-14ipsec: T9254: split get_esp_ike_cipher() into get_esp_cipher() / ↵rockfish-vyos
get_ike_cipher() get_esp_ike_cipher() took an esn flag defaulting to True (ESP/CHILD_SA semantics), and every IKE_SA call site had to remember to pass esn=False. Nothing enforced that, so a future call site could reintroduce the ESN-in-IKE bug this task fixed. Following review feedback from hedrok, split it into two public filters: get_esp_cipher(group_config, ike_group=None) ESP/CHILD_SA, esn=True get_ike_cipher(group_config) IKE_SA, esn=False always The shared implementation moves to _get_esp_ike_cipher() (no register_filter), so a template can no longer call it directly and skip picking one of the two entry points. Updated call sites: peer.j2, profile.j2, remote_access.j2, l2tp.j2 (proposals -> get_ike_cipher, esp_proposals -> get_esp_cipher), and test_template.py.
2026-09-12configtree: T9307: serialize libvyosconfig calls across threadsRobert Navarro
libvyosconfig is not safe for concurrent entry. ctypes releases the GIL for each foreign call, so threads in one process can be inside the library at the same time; two concurrent from_string calls, or from_string racing destroy, corrupt the shared parser state and crash the process with SIGSEGV. vyos-http-api reaches this when a configure operation runs in the threadpool while a retrieve is served on the event loop. Serialize every entry point on one process-wide RLock in the _Lib wrapper. For the entry points that report through the library's global error buffer, read the buffer while the lock is held and keep it per thread, so get_error() returns the caller's own error; destroy, which can run from __del__ between a failed call and get_error(), leaves it untouched.
2026-09-12Merge pull request #5451 from c-po/T8409Christian Breunig
configquery: T8409: resolve op-mode config paths independent of edit level
2026-09-11Merge pull request #5372 from ruben-herold/T9157-fib-type-matchRuben Herold
firewall: T9157: add fib-type match for destination/source
2026-09-10ethernet: T9228: only warn about unsupported NIC features when node changedChristian Breunig
EthernetIf.update() re-applies every ethernet knob on every commit touching the interface. The capability messages (offload, flow-control, ring-buffer, coalesce, switchdev) are emitted whenever the CLI-desired state differs from what the driver reports - and on drivers where a feature is fixed (virtio_net, vmxnet3, vif, veth, ...) that is permanently true. The message is correct the first time, but it then re-appears on unrelated commits like an interface description or IP address change. Record in interfaces_ethernet.py which of the affected CLI nodes were altered - the mechanism already used for speed_duplex_changed - and pass it to the setters via a "warn" argument. Settings are still applied unconditionally, only the message is gated. While at it, consolidate the seven offload setters onto a common helper and use Warning() instead of print().
2026-09-10Merge pull request #5454 from c-po/bond-fix-add-memberChristian Breunig
bond: T9269: keep the bond MAC when appending a member interface
2026-09-10configdict: T9269: no phantom removal when a multi node gains a valueChristian Breunig
A multi node with a single value is a plain string in the JSON rendering of the config tree, and only becomes a list once it holds several values. leaf_node_changed() tested for a string before diffing the lists, so appending a value reported the already configured one as gone. Adding a second bond member thus produced an "interface_remove" entry for the first, and BondIf.update() released it right after enslaving the new one, leaving the bond with the new member only. Normalize to a list and reuse list_diff(). Only the string to list append changes, from [old] to []. interface.py was immune as it re-applies list_diff() to address_old, protocols_static_arp.py was not.
2026-09-10Merge pull request #5457 from sever-sever/T9290Daniil Baturin
T9290: Fix typo for the image.py file
2026-09-10T9290: Fix typo for the image.py fileViacheslav Hletenko
Typo "writeable" should be "writable"
2026-09-09vyos.utils: T9269: no zero-component key path for an empty dictChristian Breunig
dict_to_key_paths() yields the path leading to an empty dict, which is a valueless leaf node. An empty dict at the top level means "no configuration" and yielded a single zero-component path, making dict_to_paths_values() report an option named ''. A bare "interfaces ethernet eth1" - as found in a container, where no hw-id is deployed - could therefore not be added to a bond: Cannot add interface "eth1" to bond, it has a "" assigned! interfaces_ethernet.py recorded the same phantom path in bond_blocked_changes. configdiff.py was immune, owner([]) is falsy.
2026-09-09bond: T9269: keep the bond MAC when appending a member interfaceChristian Breunig
Commit 6ebb8cd26 ("bond: T7571: fix inconsistent MAC address behaviour") re-assigns the first member's MAC address to the bond, as newer Kernels no longer do so themselves. The flag driving it was initialized unconditionally and an already enslaved member hits "continue" without clearing it, so the step ran again on every append and handed the bond the newly added member's address: bond0 aa:c1:ab:c3:62:48 eth1 aa:c1:ab:98:48:0f eth2 aa:c1:ab:c3:62:48 Only adopt a member MAC while the bond has no member at all, which is what T7571 intended. The added smoketest covers this together with T9269 in leaf_node_changed: it commits one member, appends a second, and verifies both stay enslaved, the pre-existing member stays admin up, and the bond MAC does not move.
2026-09-07configquery: T8409: resolve op-mode config paths independent of edit levelChristian Breunig
op_mode_config_dict() rewrote the absolute path passed in by the caller into one relative to VYATTA_EDIT_LEVEL. list_strip() returns an empty list as soon as a path component mismatches, so from e.g. [edit qos policy] the path "qos interface eth1" became the current edit level itself and cli-shell-api dumped an unrelated subtree: [edit qos policy] vyos@vyos# run show qos shaper interface eth1 WARNING: Specified configuration path is not valid QoS is not applied to eth1! Relative lookups are unreliable even when the edit level is a proper prefix of the path, as cli-shell-api validates the path against VYATTA_TEMPLATE_LEVEL and rejects a relative tag node value. Keep the absolute path and reset both level variables for the child process instead.
2026-09-06dhcp: T9278: move DHCP client hook tracing to a gated debug levelChristian Breunig
Each lease event emitted some fifteen daemon.info lines tracing internal steps rather than recording a change. Add a "debug" level to logmsg(), silenced unless /tmp/vyos.dhclient.debug exists, following the flag file convention used for FRR and ifconfig. Demoting alone would not help, as journald shows all priorities by default. Fifteen tracing messages move to debug; the sixteen recording an actual change stay at info. Also fix logmsg(): "warn" had no case arm although it is used, and the global LOG_PRIO leaked the preceding call's priority. It is now local.
2026-09-04static: T9278: honor dhcp-interface routes in dedicated routing tablesChristian Breunig
get_dhcp_route_interfaces() only walked "protocols static route <prefix> dhcp-interface", so routes configured below "protocols static table <id> route <prefix> dhcp-interface" never made it into the interface list. Both nodes share the same include/static/static-route.xml.i definition and both are rendered from the DHCP lease via the get_dhcp_router() filter in staticd.frr.j2, so they depend on the current lease in exactly the same way. As a result the affected interfaces were missing from the DHCP gateway cache used for FRR change detection. A lease event on an interface referenced only by a table based route would compare equal to the cached state and the re-render requested by the dhclient hook was skipped, leaving the stale gateway in the rendered configuration. Iterate the route sections of every table in addition to the top level ones. Only IPv4 routes are considered, as "dhcp-interface" does not exist for route6. Named VRFs have no table node, but the collection is shared and stays correct there as well.
2026-09-04static: T9278: reconcile FRR config after every DHCP lease eventChristian Breunig
The default route derived from "interfaces <type> <ifname> address dhcp" is rendered from the DHCP lease file, so it is only known at lease time. Until now the sole runtime path into staticd was the one-shot vtysh injection in dhclient-enter-hooks.d/03-vyos-ipwrapper. That injection races the FRR reload of the very commit which started the DHCP client: dhclient runs with "-nw", thus the commit does not wait for a lease, and when BOUND arrives mid-reload frr_alive() can report FRR as down. The route is then installed into the kernel only and FRR never learns about it. Nothing recovers afterwards, as FRRender.generate() short-circuits on an unchanged configuration dict. The self-healing re-render used by "protocols static route <prefix> dhcp-interface" was gated on /tmp/static_dhcp_interfaces, which never lists plain "address dhcp" interfaces - protocols_static.py does not even run on an interface-only commit, as no config-mode dependency points to it. Derive the DHCP dependent interface list from the configuration dict itself, both for the default VRF and for every named VRF, and use it for FRR change detection. Drop the interface list gate in the dhclient exit hook so any lease event requests a re-render. Also poll for the lease and for the rendered route in the affected smoketests instead of relying on a fixed sleep.
2026-09-01T9231: add wrappers for reference_tree utilsJohn Estabrook
2026-09-01utils: T9269: do not leak sysctl(8) errors to stderrChristian Breunig
sysctl_write() reports success through its return code, but the underlying sysctl(8) call inherited stderr. net.ipv4.neigh.default.gc_thresh* is not network namespace aware, so a container printed six "cannot stat ... No such file or directory" lines on every boot. Capture the output and keep the return code as the only interface to the caller.
2026-09-01version: T9269: omit hardware details on containersChristian Breunig
A container has no hardware of its own - vendor, model, serial and UUID are read from /sys/class/dmi/id and thus describe the host system. Listing them below "System type: container" reads as a property of the node. Leave the hardware_* keys unset when running as a container and omit the entire block in both "show version" and the airbag bug report. The latter moves the fields into an optional HARDWARE section, as str.format() has no conditionals.
2026-09-01version: T9269: report "container image" as boot typeChristian Breunig
A container is never booted on its own - is_live_boot() parses the Kernel cmdline of the host system, which on an installed host contains a BOOT_IMAGE pointing to /boot/<version>/vmlinuz. A container was thus reported to be running from an "installed image". Report "container image" for containers and keep the livecd against installed image distinction for everything else.
2026-09-01version: T9269: report "container" as system typeChristian Breunig
A container shares the Kernel with its host and inherits its DMI and CPUID data, thus hvinfo reports the hypervisor of the host system - a VyOS container on a KVM host was described as "KVM guest". Check is_running_as_container() first and report "container", otherwise fall back to hvinfo as before. Note that boot_via and the hardware vendor, model, serial and UUID fields are still derived from the host.
2026-09-01image: T9269: skip GRUB updates on container and diskless systemsChristian Breunig
Kernel cmdline and serial console updates rewrite the GRUB configuration on the persistence partition. A container has no GRUB at all, and on a system where the persistence partition is not mounted disk.find_persistence() returns an empty string, so the code reads '//boot/grub/grub.cfg' and dies with FileNotFoundError. Extend is_running_as_container() to also honor /run/.containerenv (Podman) and the container= variable systemd sets for PID 1, and add if_not_container() plus if_persistence() decorators guarding all grub_util entry points.
2026-09-01Merge pull request #5434 from c-po/python-startup-time-improvementsChristian Breunig
T9261: Python interpreter startup makes the CLI sluggish on low-cache CPUs
2026-09-01Merge pull request #5418 from abukharov/feat/t9225-pki-edsignsViacheslav Hletenko
pki: T9225: Support ED25519 and ED448 signatures on public keys in PKI
2026-08-31ipsec: T9254: do not emit ESN transforms in IKE proposalsrockfish-vyos
get_esp_ike_cipher() renders both IKE_SA proposals and CHILD_SA proposals. It unconditionally appended the -esn / -noesn variants, which are only meaningful for ESP: ESN is Transform Type 5 per RFC 7296 section 3.3.2 and is defined for CHILD_SAs only. Emitting ESN in an IKE_SA proposal breaks interoperability with implementations that reject the malformed payload without replying at all. Observed against a Cisco FTD: the IKE_SA_INIT is silently discarded, no NO_PROPOSAL_CHOSEN and no INVALID_KE_PAYLOAD, so the tunnel never comes up and nothing on the initiator side explains it. Add an explicit esn parameter defaulting to True so ESP behaviour is unchanged, and pass esn=False at the four IKE call sites: peer.j2, profile.j2, remote_access.j2 and l2tp.j2. The five esp_proposals call sites keep ESN. ike_group could have served as the discriminator, since IKE call sites do not pass it, but that coupling is incidental: the argument only exists to resolve PFS. Smoke test assertions on the proposals lines are updated accordingly; the esp_proposals assertions are left untouched.
2026-08-31vpp: T9146: Enable DPDK no-multi-seg when a full frame fits the bufferNataliia Solomko
Disabling DPDK multi-segment buffers (no-multi-seg) lets VPP receive each frame into a single buffer, increasing forwarding throughput. The frame must then fit the buffer 'data-size', so 'no-multi-seg' is computed: it is enabled only while the largest MTU across all VPP-bound interfaces, plus its L2 framing overhead (26 bytes), fits 'data-size'. Otherwise VPP keeps multi-seg and Jumbo frames still work without a larger buffer. Changing the MTU of a VPP-bound interface can flip the flag, so interfaces_ethernet reconfigures VPP when it changes, via an initial dependency (set_dependents_initial) to avoid a cycle with the existing vpp -> ethernet dependency.
2026-08-31pki: T9225: Support ED25519 and ED448 signatures on public keys in PKIAlex Bukharov
2026-08-30vyos: T9261: defer more heavy imports off the CLI hot pathsChristian Breunig
Follow-up sweep to f696b2d65. Every conf-mode script not handled in-daemon by vyos-configd, every op-mode script and every Python validator is a fresh interpreter, so module-scope imports of heavy dependencies are paid over and over - which is what makes the CLI feel sluggish on CPUs with little cache. configsource.py imported vyos.vyconf_session, and with it google.protobuf, for a class that is only instantiated when the vyconf backend is active. opmode.py imported ConfigTreeQuery for a single decorator most op-mode scripts never use. template.py imported jinja2 at module scope although Environment is only touched in the lru_cache'd _get_environment(), while most callers want just the is_ipv4/is_ipv6 predicates. ethtool.py pulled pyroute2 via vyos.netlink for two calls in Ethtool.__init__. ifconfig/interface.py pulled the whole cryptography stack via vyos.pki for set_eapol() alone. Also deferred: netaddr, jmespath, tabulate, hurry.filesize, vyos.ifconfig in qos, and cracklib - the last of which also opens its dictionary database on import. import vyos.opmode 34.0 -> 4.6 ms (-86%), 206 -> 71 modules import vyos.ifconfig 132.9 -> 30.8 ms (-77%), 618 -> 193 modules import vyos.config 40.7 -> 20.6 ms (-49%), 194 -> 130 modules import vyos.qos 134.1 -> 12.5 ms (-91%), 631 -> 124 modules import vyos.template 18.8 -> 6.3 ms (-66%), 153 -> 89 modules import vyos.firewall 22.2 -> 12.2 ms (-45%), 168 -> 114 modules Deferring textwrap in base.py and logging in configtree.py was measured too and made no difference; both were left alone.
2026-08-30configtree: T9261: bind libvyosconfig once instead of per ConfigTreeChristian Breunig
Every ConfigTree re-opened libvyosconfig with cdll.LoadLibrary and re-declared all 31 function prototypes inline in __init__. DiffTree and the twelve module-level helpers repeated the pattern per call, and since a DiffTree builds six further trees internally, a single one performed seven dlopens and roughly 200 argtypes/restype assignments. referencetree.py had its own copy. Declare the prototypes once in a _PROTOTYPES table and hand out an lru_cache'd wrapper keyed on libpath. Symbols are resolved on first use rather than up front, because not every build of the library exports every entry point and the previous code only failed on symbols actually called. referencetree.py shares the cache and picks up LIBPATH from configtree, so it now honours the /tmp/libvyosconfig/_build development path instead of hardcoding the install path. ConfigTree() 72.3 -> 6.3 us (-91%, 11.5x) DiffTree() 397.3 -> 34.7 us (-91%, 11.4x) Two prototypes were wrong and are fixed by declaring them in one place. validate_tree_filter had no restype, so ctypes defaulted to c_int and truncated the returned tree pointer to 32 bits before ConfigTree(address=...) saw it; harmless while the heap stays below 4 GB, corrupt above it. get_subtree declared two argtypes but is called with three, leaving with_node unchecked.
2026-08-30vyos: T9261: defer heavy imports out of the Config/ConfigSession pathChristian Breunig
Importing vyos.config dragged in the whole HTTP and crypto stack. vyos.version imported requests and urllib3 for get_remote_version(), plus vyos.system.image for a single call in get_full_version_data() - and that reaches vyos.system.grub and vyos.template, so every consumer paid for jinja2 as well. vyconf_session imported vyos.remote, and therefore paramiko and cryptography, for a get_config_file() used in two methods. All of these move to their call sites. vyos/utils/__init__.py eagerly imported all 18 submodules, so 'from vyos.utils.dict import get_sub_dict' also loaded auth, network and process. It now resolves them on first attribute access via a module-level __getattr__. No caller relied on the eager import; the common 'from vyos.utils.<sub> import <name>' form is unaffected. import vyos.config 129.6 -> 47.7 ms (-63%, 2.7x), 575 -> 194 modules import vyos.ifconfig 205.0 -> 149.7 ms (-27%, 1.4x) This is per process, so it is paid again by every conf-mode script not handled in-daemon by vyos-configd, every op-mode script, and every smoketest.
2026-08-29smoketest: T9014: add CPU architecture decorator to guard testsChristian Breunig
VyOS supports both amd64 and arm64 CPU architectures, but not every smoketest is applicable to both of them. Add a cpu_arch() decorator to vyos.utils.cpu which takes a list of supported CPU architectures - if the test is run on any other architecture it is skipped with a message naming both the supported and the current architecture. Tests without the decorator run everywhere. Use it to replace the ad-hoc IS_ARM64 checks in test_kernel_options.py and to guard the x86 only intel and intel_qat module sets in test_module_load.py, which so far failed on arm64.
2026-08-28Merge pull request #5408 from cqjjjzr/T9166-ipv6-haViacheslav Hletenko
ha: T9166: add IPv6 support for HA peer links
2026-08-27Merge pull request #5427 from jestabro/configdep-initialJohn Estabrook
T9146: add initial set/call_dependents as exempt from possible cycle
2026-08-26T9244: fix regression in setting console type on installJohn Estabrook
The introduction of util get_kernel_boot_arg() has many uses, however, it is not appropriate for use in get_kernel_serial_console: since it searches right to left, it picks up an incorrect and incomplete entry; consequently get_kernel_serial_console returns a None tuple, which voids selection of console type on install. Restore original implementation of get_kernel_serial_console.
2026-08-26T9146: add initial set/call_dependencies as exempt from possible cycleJohn Estabrook
The category of initial set/call_dependents only apply when the script is called natively, and not as a dependency. This allows an exemption from a possible dependency cycle.
2026-08-26dhcp: T9166: add IPv6 support for HA peer linkschariri
Accept IPv6 source and remote addresses for Kea high availability and bracket IPv6 endpoints in generated peer URLs.
2026-08-25Merge pull request #5425 from l0crian1/mac-mask-addViacheslav Hletenko
firewall: T9242: Add mac-address-mask support