Skip to content

Conversation

@MoeSalah1999
Copy link
Contributor

Proposed Commit Message

On Azure FreeBSD images, cloud-init fails during early networking setup due to a combination of platform mismatches and incorrect assumptions:

- Azure exposes both a Hyper-V synthetic NIC (hn*) and an accelerated VF (mce*) that intentionally share the same MAC address.
- cloud-init assumes MAC addresses uniquely identify interfaces, causing one interface to be silently discarded during enumeration.
- FreeBSD lacked parity with Linux logic that filters Hyper-V accelerated VFs when a synthetic interface is present.
- Interface ordering on FreeBSD was undefined, allowing the VF to be selected as the primary NIC.
- BSD networking code did not fully match the netops API used by cloud-init core.
- Azure ephemeral networking logic hard-failed when DHCP context fields were not populated on non-Linux platforms.

In combination, these issues caused cloud-init to attempt DHCP on the wrong interface, invoke Linux-specific networking operations on FreeBSD, and abort instance initialization.

**Changes Made:**
**1. Tolerate duplicate MAC addresses on FreeBSD**

get_interfaces_by_mac_on_freebsd() now preserves the first discovered interface when duplicate MAC addresses are encountered and logs the event instead of overwriting or failing.

- Maintains the existing Dict[str, str] return contract.
- Prevents loss of the synthetic hn* interface when an accelerated VF shares its MAC.
- Aligns FreeBSD behavior with existing Linux duplicate-MAC tolerance.

**2. Correct FreeBSD device discovery**

get_devicelist() and FreeBSD NIC discovery paths were adjusted to avoid relying on MAC-keyed maps for interface enumeration.

- Ensures all candidate interfaces are discovered on FreeBSD.
- Prevents interface loss due to MAC collisions.
- Keeps Linux and BSD discovery paths separate and appropriate.

**3. Filter Hyper-V accelerated VFs on FreeBSD**

Added FreeBSD parity with existing Linux logic that filters Hyper-V accelerated virtual functions when a synthetic interface is present.

- On Azure FreeBSD:
                 - hn* interfaces are treated as synthetic.
                 - mce* interfaces are treated as accelerated VFs.
- Prevents cloud-init from selecting the VF as the primary interface.
- Mirrors established Linux behavior for Hyper-V environments.

**4. Prefer hn0 as the primary interface on FreeBSD**

Explicitly orders FreeBSD interfaces so that hn0 is preferred when present.

- Reflects Azure platform expectations.
- Ensures deterministic primary NIC selection.
- Avoids reliance on enumeration order or timing.

**5. Fix BSD netops API mismatch**

Updated BsdNetOps.link_down() to accept the family argument expected by the cloud-init netops API.

- Prevents runtime TypeError during network teardown/setup.
- Aligns BSD netops with other platform implementations.
- Does not alter behavior for existing callers.


Fixes GH-6657 

Additional Context

Results:

With these changes applied:

  • The correct synthetic NIC (hn*) is consistently selected on Azure FreeBSD.
  • Duplicate MAC addresses no longer cause interface loss.
  • Accelerated VFs are ignored when inappropriate.
  • FreeBSD networking uses the correct netops implementation.
  • Azure datasource initialization completes successfully.
  • No public APIs or existing test expectations are broken.

Scope and Compatibility:

  • Changes are limited to FreeBSD and Azure-specific behavior.
  • Linux behavior remains unchanged.
  • Public helper function return types are preserved.
  • All existing unit tests remain valid.

Test Steps

Provided tests in tests/unittests/net/test_net_freebsd.py.

Log Evidence

This change is covered by new FreeBSD-specific unit tests which assert:

  • duplicate MAC detection
  • preservation of the synthetic hn* interface
  • emission of the expected debug log message

Example asserted log output:

                        Duplicate MAC aa:bb:cc:dd:ee:ff found on hn0 and mce0; keeping first

Merge type

  • Squash merge using "Proposed Commit Message"
  • Rebase and merge unique commits. Requires commit messages per-commit each referencing the pull request number (#<PR_NUM>)

@MoeSalah1999
Copy link
Contributor Author

@holmanb I closed the previous PR and opened a new one from a clean branch, still CLA checks aren't passing.

@holmanb
Copy link
Member

holmanb commented Jan 26, 2026

@holmanb I closed the previous PR and opened a new one from a clean branch, still CLA checks aren't passing.

It only checks public email addresses that are associated with your account.

@MoeSalah1999
Copy link
Contributor Author

It only checks public email addresses that are associated with your account.

@holmanb There is only 1 email associated with my account, it's the same email that I have used to make other PRs where checks passed.
I have tried to re-sign the CLA but got an internal server error. The CLA checks log shows an error code 500 as well, which suggests the CLA service may be in a bad state.

@holmanb
Copy link
Member

holmanb commented Jan 26, 2026

It only checks public email addresses that are associated with your account.

@holmanb There is only 1 email associated with my account, it's the same email that I have used to make other PRs where checks passed. I have tried to re-sign the CLA but got an internal server error. The CLA checks log shows an error code 500 as well, which suggests the CLA service may be in a bad state.

Strange. After rerunning the CLA job it still fails, though I do see a passing test within the last hour so it doesn't seem likely for it to be in a bad state.

@MoeSalah1999
Copy link
Contributor Author

Strange. After rerunning the CLA job it still fails, though I do see a passing test within the last hour so it doesn't seem likely for it to be in a bad state.

@holmanb I'm not sure, at this point it could be a problem on my end, could you override the checks or raise this issue to an admin? I have already emailed Chad Smith regarding this issue.

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