Skip to content

Handling of interface renaming by kernel. - #171

Open
joeysk2012 wants to merge 1 commit into
amazonlinux:mainfrom
joeysk2012:iface-name-inconsistent
Open

Handling of interface renaming by kernel.#171
joeysk2012 wants to merge 1 commit into
amazonlinux:mainfrom
joeysk2012:iface-name-inconsistent

Conversation

@joeysk2012

@joeysk2012 joeysk2012 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available:
#166

Description of changes:
Perform cleanup of systemd interface configs, when the udev rule remove is triggered. There were orphaned systemd unit files which could potentially affect the operation of the network. In this specific case, an interface ens6 was detached and attached again as ens7 (due to Hypervisor selecting a different PCI slot) with the same MAC. From there, any new changes from the control plane would only affect the config for ens6 as it is lower in alpha-numeric order, when ens6 does not even exist anymore.

Other options for the fix were considered but they were deemed too risky:

Option 1: NamePolicy=mac (systemd .link file)

Ship a new .link file scoping NamePolicy=mac (or similar) to ENA/ixgbevf
interfaces, so udev derives the interface name from the MAC address instead of
the PCI slot. Since the MAC is stable for a given ENI (confirmed by test
evidence — same MAC across the ens6/ens7 rename), this prevents the rename
at the source.

Benefits

  • Only option that fixes the root cause: the name itself never changes across
    re-attach, so no downstream config (ours or anyone else's) is ever orphaned.
  • Small code footprint: one new file, no changes to existing logic.

Risks

  • Fleet-wide, customer-visible change: every ENA/ixgbevf interface on every
    AL2023 instance gets a new naming scheme. Any customer automation, monitoring,
    or scripts hardcoding slot-based names (ens5, ens6, ...) would see
    different names after this ships.
  • .link-file-driven renames only fully take effect after a networkd reload +
    udev "move" event. amazon-ec2-net-utils' own add_altnames() explicitly
    avoids this mechanism today for the (much smaller) altname use case, citing
    that overhead — the same concern applies here, at a larger scale, and could
    introduce a new timing race with setup-policy-routes.sh start's
    wait-for-sysfs-node loop.
  • Not validated: no compatibility testing done against AL2023's existing default
    naming scheme (v252) or other higher-priority .link/naming rules that might
    already claim these interfaces.

Verdict: Highest risk / highest blast radius. Worth prototyping and testing
in isolation before proposing upstream, but not implemented in this pass.


Option 2: Match [Match] stanza by interface Name= instead of MACAddress=

Considered switching the generated .network config's [Match] stanza from
MACAddress=${ether} to Name=${iface}, on the theory that "matching by name"
might sidestep the rename problem.

Correction during discussion: the [Match] stanza already uses
MACAddress=${ether} today — only the file path / directory name / systemd
unit instance
(70-<iface>.network, policy-routes@<iface>.service) is keyed
by interface name, not the match rule itself.

Benefits

  • None identified. Matching by name does not solve the rename problem (a
    Name=ens6 rule stops matching anything the instant the ENI renames to
    ens7), so the underlying instability is unaddressed.

Risks

  • Reintroduces a real correctness bug that MAC-based matching was specifically
    designed to prevent (see cd0f361, "Don't reconfigure interfaces on service
    'stop'"): if a different ENI later reuses the same slot/name, a
    Name=ens6-matched leftover config (secondary IPs, routes, policy rules) from
    the previous, unrelated ENI would incorrectly apply to it. MACAddress=
    matching prevents this by construction; Name= matching would not.
  • Makes the rename scenario strictly worse than today: currently the MAC-matched
    config at least keeps functioning correctly across a rename (only the on-disk
    label is orphaned); with Name= matching the config would stop matching
    anything the moment the rename occurs.

Verdict: Rejected. Not implemented — this would reopen a closed correctness
issue for no benefit.

(Note: a related, narrower idea — keying the config file path by MAC
instead of interface name, while keeping [Match] MACAddress= as-is — was also
discussed. It would prevent orphaning more structurally than Option 3 below, but
requires touching ~36 call sites across lib.sh, breaks the documented
networkctl status ens5/run/systemd/network/70-ens5.network convention,
and touches the systemd unit instantiation key. Assessed as moderate-to-high
risk and deprioritized in favor of Option 3.)


Option 3: Clean up stale config on interface removal (implemented)

Wire the udev remove event to deterministically delete the departing
interface's 70-<iface>.network file and drop-in directory, scoped to exactly
that interface name — no broad scan, no reload.

History: this cleanup logic existed once (pre-cd0f361) via
ExecStop=setup-policy-routes %i stop, triggering a global networkctl reload on every stop. That reload was found to reset conntrack state for
unrelated live interfaces, causing 100% packet loss for established
connections on Docker-bridge-networking hosts. cd0f361 removed the wiring
entirely to fix that regression, leaving the remove cleanup logic in the
script but orphaned (nothing calls it).

Benefits

  • Directly closes the gap found by the test: no more orphaned
    70-<oldname>.network files after a rename.
  • Minimal, additive change (~10 lines): re-wires ExecStop= on
    policy-routes@.service to call the existing remove) branch, and removes
    that branch's call to register_networkd_reloader/touch "$reload_flag" so
    it never triggers a reload.
  • Cannot reintroduce the cd0f361 regression: the fix deliberately does not
    call networkctl reload or reconfigure. This is safe because by the time
    udev's remove action fires, the kernel has already destroyed the link — its
    routes/rules/addresses are already torn down independently of these config
    files, so there is nothing live left to reconfigure and no reload-driven
    conntrack risk for other interfaces.
  • Precisely scoped: only ever deletes the file for the exact interface name the
    OS just reported as removed. (An earlier draft additionally scanned all
    70-*.network files and reaped any whose name no longer resolved via ip link show — this broader sweep was deliberately dropped as unnecessarily
    risky; the scoped, event-driven deletion is sufficient and does not depend on
    a live-interface heuristic that could misfire.)

Risks

  • Does not prevent the rename itself — ens6/ens7 will still occur; this only
    ensures the old name's config doesn't linger.
  • Relies on ExecStop= firing reliably for a Type=oneshot, RemainAfterExit=yes
    unit stopped via systemctl disable --now (the exact mechanism the udev
    remove rule already uses) — not yet validated on a live host.

Verdict: Implemented on iface-name-inconsistent. Lowest risk of the three
options, directly addresses the observed gap, and does not touch the MAC-based
[Match] matching that is already correct.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants