Skip to content

Conversation

davidrapan
Copy link
Contributor

@davidrapan davidrapan commented May 15, 2025

Proposed change

Currently default stable-privacy is probably sufficient for some users, but for the rest of us, there should be an option to easily change this configuration therefore I'm introducing the changes in this PR.

Added are two new opt-in configuration items for IPv6:

  • addr_gen_mode
    • with options: eui64, stable-privacy, default-or-eui64 and default
  • ip6_privacy
    • with three options: enabled, enabled but prefer public, disabled and default

More 'bout the options here

Configuration of

addr_gen_mode: eui64
ip6_privacy: enabled

combines the best of both "worlds" because Privacy Extensions also adds an additional temporary address that is used for all ongoing connections, just like in the "stable-privacy" generation mode, but still has a fixed and deterministic address for all incoming connections.

I've been using this configuration myself since day 1 and it should also be the default in my opinion, but I understand that some may have a different one.

Edit: I just found out that there have been some attempts in the past to bring this configuration to HA:

So hopefully this one will be successful, hah 😆 But I also think it's not necessary to expose this configuration in the frontend.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to the supervisor)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Ruff (ruff format supervisor tests)
  • Tests have been added to verify that the new code works.

If API endpoints or add-on configuration are added/changed:

Summary by CodeRabbit

  • New Features

    • Added support for configuring IPv6 address generation mode and privacy settings through the network API.
    • IPv6 settings now include new parameters for address generation mode and privacy in configuration and display.
  • Bug Fixes

    • Improved validation and serialization of IPv6 configuration options in network interface settings.
  • Tests

    • Updated tests to verify the presence and correctness of new IPv6 configuration options.

@davidrapan davidrapan changed the title feat: Add IPv6 Address Generation mode Add IPv6 Address Generation mode May 15, 2025
Copy link
Contributor

coderabbitai bot commented May 15, 2025

📝 Walkthrough

Walkthrough

The changes introduce explicit support for IPv6 address generation mode and privacy settings throughout the network configuration stack. New data structures, constants, and enums are added to represent these IPv6-specific parameters. Serialization, deserialization, validation, and API exposure are updated to handle and propagate the new fields, ensuring consistent management and representation of IPv6 configuration.

Changes

File(s) Change Summary
supervisor/api/network.py Added handling for addr_gen_mode and ip6_privacy in IPv6 settings; introduced Ip6Setting and new serialization logic.
supervisor/const.py Added constants: ATTR_ADDR_GEN_MODE and ATTR_IP6_PRIVACY.
supervisor/dbus/const.py Added enums: InterfaceAddrGenMode and InterfaceIp6Privacy for IPv6 config parameters.
supervisor/dbus/network/configuration.py Added Ip6Properties dataclass with addr_gen_mode and ip6_privacy fields for IPv6.
supervisor/dbus/network/setting/init.py Added IPv6 config attributes; updated type annotations and loading logic for IPv6 settings to use new fields and class.
supervisor/dbus/network/setting/generate.py Updated IPv4/IPv6 settings functions to use new types; added logic to serialize IPv6-specific settings if method is AUTO.
supervisor/host/configuration.py Added Ip6Setting dataclass; updated Interface to use it; mapped NetworkManager values to new enums via static methods.
supervisor/host/const.py Added enums: InterfaceAddrGenMode and InterfaceIp6Privacy for interface configuration.
tests/api/test_network.py Updated test to assert presence of new IPv6 fields: addr_gen_mode and ip6_privacy.
tests/dbus/network/setting/test_generate.py Extended tests to cover IPv6 settings generation with default addr_gen_mode and ip6_privacy values.
tests/dbus/network/setting/test_init.py Replaced MagicMock with actual NetworkManager fixture in tests for better integration; added test for IPv6 addr_gen_mode.

Sequence Diagram(s)

sequenceDiagram
    participant API as Network API
    participant Host as Host Configuration
    participant DBus as DBus Layer

    API->>API: Receive IPv6 config (addr_gen_mode, ip6_privacy)
    API->>Host: Create Ip6Setting with new fields
    Host->>DBus: Map and forward settings (addr_gen_mode, ip6_privacy)
    DBus->>DBus: Store as Ip6Properties
    DBus-->>Host: Return updated IPv6 config
    Host-->>API: Serialize with addr_gen_mode, ip6_privacy
    API-->>Client: Expose IPv6 config with new fields
Loading

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 89c1f15 and e1b71d3.

📒 Files selected for processing (2)
  • supervisor/dbus/network/setting/generate.py (5 hunks)
  • tests/dbus/network/setting/test_init.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/dbus/network/setting/test_init.py
  • supervisor/dbus/network/setting/generate.py
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Build i386 supervisor
  • GitHub Check: Build amd64 supervisor
  • GitHub Check: Build armv7 supervisor
  • GitHub Check: Build armhf supervisor
  • GitHub Check: Build aarch64 supervisor
  • GitHub Check: Run tests Python 3.13.3
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
supervisor/api/network.py (1)

241-248: ⚠️ Potential issue

Constructor arguments are in the wrong order – will corrupt data at runtime

Ip6Setting inherits the field order from IpSetting (method, address, gateway, nameservers) and then appends the new fields (addr_gen_mode, ip6_privacy).
By passing the arguments positionally as

Ip6Setting(method, addr_gen_mode, ip6_privacy, address, gateway, nameservers)

each value is shifted one slot to the right:

  • addr_gen_mode is stored in address
  • ip6_privacy is stored in gateway
  • the real address list ends up in nameservers

This will break validation, generate garbage DBus payloads, and likely raise exceptions when the supervisor tries to iterate ipv6setting.address.

Fix by using keyword arguments (safer) or the correct positional order.

- interface.ipv6setting = Ip6Setting(
-     config.get(ATTR_METHOD, InterfaceMethod.STATIC),
-     config.get(ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.STABLE_PRIVACY),
-     config.get(ATTR_IP6_PRIVACY, InterfaceIp6Privacy.ENABLED),
-     config.get(ATTR_ADDRESS, []),
-     config.get(ATTR_GATEWAY),
-     config.get(ATTR_NAMESERVERS, []),
- )
+ interface.ipv6setting = Ip6Setting(
+     method=config.get(ATTR_METHOD, InterfaceMethod.STATIC),
+     address=config.get(ATTR_ADDRESS, []),
+     gateway=config.get(ATTR_GATEWAY),
+     nameservers=config.get(ATTR_NAMESERVERS, []),
+     addr_gen_mode=config.get(ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.STABLE_PRIVACY),
+     ip6_privacy=config.get(ATTR_IP6_PRIVACY, InterfaceIp6Privacy.ENABLED),
+ )
♻️ Duplicate comments (1)
supervisor/api/network.py (1)

310-319: Same argument-ordering bug when creating VLANs

The positional call to Ip6Setting in VLAN creation has the identical mis-ordering and needs the same fix as above to avoid corrupting the new interface object.

🧹 Nitpick comments (6)
supervisor/host/const.py (1)

18-30: Consider specialising the doc-string for the new enums
InterfaceAddrGenMode and InterfaceIp6Privacy inherit the generic “Configuration of an interface.” description that is already used above. A short, specific sentence (“IPv6 address generation mode”, “IPv6 privacy extension behaviour”) will make the generated reference documentation clearer.

supervisor/api/network.py (3)

72-80: Validation schema looks good – tiny readability nit
The _SCHEMA_IPV6_CONFIG correctly adds the two new options and type-coerces to the StrEnums.
If you move ATTR_GATEWAY & ATTR_NAMESERVERS beneath the new fields you added, the IPv4 / IPv6 schemas stay visually aligned which helps readers spot the diff faster.


115-126: Duplication between ipconfig_struct and ip6config_struct
The two functions are almost identical except for two extra fields. A tiny helper (_common_ip_struct(...)) or an optional-param approach could remove the code copy-paste and keep future changes in one place.


102-104: Type hint: accept None for ipv6setting
_get_ipv6_connection_settings() is called with interface.ipv6setting, which can legitimately be None. Declare the parameter as Ip6Setting | None (or Optional[Ip6Setting]) to satisfy type-checkers and future maintainers.

Also applies to: 158-160

supervisor/dbus/network/setting/generate.py (2)

103-118: Avoid magic integers – use the IntEnum values directly
Hard-coding 0 / 1 / 2 for CONF_ATTR_IPV6_ADDR_GEN_MODE and CONF_ATTR_IPV6_PRIVACY works but obscures intent. The corresponding InterfaceAddrGenMode and InterfaceIp6Privacy IntEnums already define .value, so you can write:

ipv6[CONF_ATTR_IPV6_ADDR_GEN_MODE] = Variant("i", ipv6setting.addr_gen_mode.value)
...
ipv6[CONF_ATTR_IPV6_PRIVACY] = Variant("i", ipv6setting.ip6_privacy.value)

This keeps the mapping in one place and prevents accidental divergence if enum values ever change.


61-63: Signature mismatch: allow None for ipv4setting / ipv6setting
Both helper functions operate correctly when the setting object is None, but their annotations specify a non-optional type. Updating the type hints avoids false positives for static analysis tools.

-def _get_ipv4_connection_settings(ipv4setting: IpSetting) -> dict:
+def _get_ipv4_connection_settings(ipv4setting: IpSetting | None) -> dict:
...
-def _get_ipv6_connection_settings(ipv6setting: Ip6Setting) -> dict:
+def _get_ipv6_connection_settings(ipv6setting: Ip6Setting | None) -> dict:
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between d0d11db and dd3e85b.

📒 Files selected for processing (9)
  • supervisor/api/network.py (8 hunks)
  • supervisor/const.py (2 hunks)
  • supervisor/dbus/const.py (1 hunks)
  • supervisor/dbus/network/configuration.py (1 hunks)
  • supervisor/dbus/network/setting/__init__.py (6 hunks)
  • supervisor/dbus/network/setting/generate.py (4 hunks)
  • supervisor/host/configuration.py (6 hunks)
  • supervisor/host/const.py (1 hunks)
  • tests/api/test_network.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
`*/**(html|markdown|md)`: - For instructional content in documentation, use a direct and authoritative tone. Avoid expressions of politeness such as 'may' or 'please', and ensure t...

*/**(html|markdown|md): - For instructional content in documentation, use a direct and authoritative tone. Avoid expressions of politeness such as 'may' or 'please', and ensure the goal of the instruction is fronted.

  • Apply the Microsoft Style Guide to ensure documentation maintains clarity and conciseness.
  • In step-by-step instructions, front the location phrase in the instructional sentence.
  • In step-by-step instructions, front the 'goal' in the instructional sentence.
  • In step-by-step instructions, if in doubt what to front, front the 'goal' before the location phrase in the instructional sentence.
  • do not hyphenate terms like 'top-right' or 'bottom-left' with 'corner'
  • supervisor/const.py
`*/**(html|markdown|md)`: - Use bold to mark UI strings. - If "" are used to mark UI strings, replace them by bold.

*/**(html|markdown|md): - Use bold to mark UI strings.

  • If "" are used to mark UI strings, replace them by bold.
  • supervisor/const.py
`*/**(html|markdown|md)`: - Be brief in your replies and don't add fluff like "thank you for..." and "Please let me know if"

*/**(html|markdown|md): - Be brief in your replies and don't add fluff like "thank you for..." and "Please let me know if"

  • supervisor/const.py
`*/**(html|markdown|md)`: - Use sentence-style capitalization also in headings.

*/**(html|markdown|md): - Use sentence-style capitalization also in headings.

  • supervisor/const.py
`*/**(html|markdown|md)`: do not comment on HTML used for icons

*/**(html|markdown|md): do not comment on HTML used for icons

  • supervisor/const.py
`*/**(html|markdown|md)`: Avoid flagging inline HTML for embedding videos in future reviews for this repository.

*/**(html|markdown|md): Avoid flagging inline HTML for embedding videos in future reviews for this repository.

  • supervisor/const.py
🧬 Code Graph Analysis (4)
supervisor/host/const.py (1)
supervisor/dbus/const.py (2)
  • InterfaceAddrGenMode (213-217)
  • InterfaceIp6Privacy (220-225)
supervisor/dbus/const.py (1)
supervisor/host/const.py (2)
  • InterfaceAddrGenMode (18-22)
  • InterfaceIp6Privacy (25-30)
supervisor/api/network.py (3)
supervisor/dbus/const.py (3)
  • InterfaceAddrGenMode (213-217)
  • InterfaceIp6Privacy (220-225)
  • InterfaceMethod (204-210)
supervisor/host/const.py (3)
  • InterfaceAddrGenMode (18-22)
  • InterfaceIp6Privacy (25-30)
  • InterfaceMethod (10-15)
supervisor/host/configuration.py (2)
  • Ip6Setting (59-63)
  • IpConfig (39-45)
supervisor/host/configuration.py (5)
supervisor/dbus/const.py (3)
  • InterfaceAddrGenMode (213-217)
  • InterfaceIp6Privacy (220-225)
  • InterfaceMethod (204-210)
supervisor/host/const.py (6)
  • InterfaceAddrGenMode (18-22)
  • InterfaceIp6Privacy (25-30)
  • InterfaceMethod (10-15)
  • AuthMethod (41-46)
  • InterfaceType (33-38)
  • WifiMode (49-55)
supervisor/dbus/network/interface.py (4)
  • connection (87-89)
  • connection (92-97)
  • NetworkInterface (27-187)
  • settings (100-102)
supervisor/dbus/network/connection.py (1)
  • NetworkConnection (27-183)
supervisor/host/network.py (1)
  • get (108-113)
🔇 Additional comments (16)
supervisor/const.py (2)

100-100: LGTM! New attribute constant for IPv6 address generation mode.

This constant provides a consistent key name for the new IPv6 address generation mode configuration option and follows the existing naming convention in the file.


224-224: LGTM! New attribute constant for IPv6 privacy settings.

This constant provides a consistent key name for the new IPv6 privacy settings configuration option and follows the existing naming convention in the file.

supervisor/dbus/network/configuration.py (1)

80-86: LGTM! Well-designed IPv6 properties extension.

Good approach to extend the base IpProperties class with IPv6-specific fields while maintaining the inheritance hierarchy. This allows for IPv6-specific configuration while reusing the common IP properties.

tests/api/test_network.py (1)

54-54: LGTM! Test coverage for new IPv6 configuration options.

Appropriate test assertions for the new IPv6 address generation mode and privacy settings, ensuring that the API correctly exposes these new configuration options with their expected default values.

Also applies to: 57-57

supervisor/dbus/const.py (1)

213-226: LGTM! Well-structured enums for the new IPv6 configuration options.

The new enum classes for IPv6 address generation mode and privacy settings follow the existing pattern in the codebase and are correctly defined as IntEnum for DBus integration. The values align with the corresponding string enums in supervisor/host/const.py, providing consistent representation across different layers of the system.

supervisor/dbus/network/setting/__init__.py (5)

15-15: New IPv6 Properties import added correctly.

The import of Ip6Properties is appropriate for the new IPv6 configuration capabilities being added.


62-63: IPv6 address generation mode and privacy configuration added.

These new configuration attributes align with the PR objectives to support custom IPv6 address generation modes.


75-76: IPv6 configuration attributes properly added to ignore fields.

Adding these fields to IPV4_6_IGNORE_FIELDS ensures they'll be correctly handled during settings updates.


119-119: Type annotations updated for IPv6 properties.

Correctly updating the type annotations from generic IpProperties to specialized Ip6Properties improves type safety.

Also applies to: 159-159


286-293: IPv6 properties initialization properly includes new settings.

The new address generation mode and privacy settings are correctly extracted from the loaded configuration data.

supervisor/host/configuration.py (6)

10-13: NetworkManager IPv6 enums imported with appropriate aliases.

Good practice using aliases to avoid naming conflicts between the NetworkManager constants and internal representation.


17-24: Well-structured import of internal enums.

The reorganization to explicitly import all required enums enhances code readability.


58-64: Well-defined IPv6 settings dataclass with appropriate defaults.

The new Ip6Setting dataclass properly extends IpSetting with IPv6-specific attributes, and includes sensible defaults that match the PR objectives (EUI64 for address generation and ENABLED for privacy).


99-99: Type annotation updated for IPv6 settings.

Correctly specifying the more specialized Ip6Setting type improves type safety.


138-160: IPv6 settings mapping implementation is thorough.

The implementation correctly maps NetworkManager IPv6 configurations to internal representations, including the new address generation mode and privacy settings.


221-241: Comprehensive mapping functions for IPv6 settings.

The new static methods provide clean conversions between NetworkManager constants and internal enum representations, with appropriate defaults for handling unknown values:

  • STABLE_PRIVACY for address generation mode
  • ENABLED for IPv6 privacy

This aligns with the PR objectives that mention these as sensible defaults.

@agners
Copy link
Member

agners commented May 19, 2025

combines the best of both "worlds" because Privacy Extensions also adds an additional temporary address that is used for all ongoing connections, just like in the "stable-privacy" generation mode, but still has a fixed and deterministic address for all incoming connections.

How is address selection properly implement/what APIs allow to get the correct IP? Do you know how that plays out with e.g. mDNS specifically? How well is address selection in mDNS resonder and similar implementations which use the IP address implemented? E.g. Home Assistant itself announces services using Python Zeroconf, I wonder if it selects addresses correctly. It uses ifaddr to get a list of interfaces and IP addresses from what I remember, but I don't think it does any address selection.

Also, there is a suspicion that systems with privacy extensions which run an OpenThread Border Router and announce the TREL services with an IPv6 address which later gets rotated, leading to TREL peers not correctly addressed. There was also the rather uncommon ordering of GUA over ULA over link-local, but it seems that got recently changed.

@davidrapan
Copy link
Contributor Author

How is address selection properly implement/what APIs allow to get the correct IP?

It is in RFC 6724 and is simply enforced by a temporary over public rule in kernel address selection or left to the application to bind() to a specific source address (binding to a public one with privacy extensions enabled would violate the RFC).

Do you know how that plays out with e.g. mDNS specifically? How well is address selection in mDNS responder and similar implementations which use the IP address implemented?

Both are announced and the source address is a link-local.

It uses ifaddr to get a list of interfaces and IP addresses from what I remember, but I don't think it does any address selection.

This is correct behavior. In cases like this, the kernel address selection is in charge.

I'm not sure about OpenThread Border as I've never used it, but I think it will be a similar case to mDNS. Service-specific announcements have very little to do with source address selection. It's all about where the packets are coming from, not what their content is. :) And that should be at least configurable? I guess.

BUT, that's why everything presented here is opt-in for those who know what's going on. HA never initiated any connections outside using anything other than a temporary address.

If you want me to do any specific tests, let me know. :)

@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch from 07c3652 to c6f1d64 Compare May 19, 2025 14:40
@agners
Copy link
Member

agners commented May 19, 2025

Do you know how that plays out with e.g. mDNS specifically? How well is address selection in mDNS responder and similar implementations which use the IP address implemented?

Both are announced and the source address is a link-local.

I am not really worried what the source address of the multicast packet is, it's largely irrelevant for the receiving system.

What is relevant is the payload of mDNS packets, which contains A and AAAA information of the host. What I wonder is if mDNS responder correctly handle such rotating addresses, or rather, how they should handle them correctly. From what I've seen in Python Zeroconf code, by default it announces all addresses returned by ifaddr of a particular interface. What happens if that address lifetime expires before the receiving system is using that address? Probably the mDNS announcement should align the record lifetime with the address. Or probably the address deprecation feature is useful for this, so mDNS should only announce non-deprecated address, and the deprecation period should at least be as long as the announced record cache TTL value.

This really deviates a bit from that PR, but I try to understand the ramification of enabled privacy extensions for Home Assistant as a whole, and tap your expertise on this topic 😅

It uses ifaddr to get a list of interfaces and IP addresses from what I remember, but I don't think it does any address selection.

This is correct behavior. In cases like this, the kernel address selection is in charge.

I am worried about the remote system here. From what I understand, there is no way for the remote system to tell which address is which.

BUT, that's why everything presented here is opt-in for those who know what's going on. HA never initiated any connections outside using anything other than a temporary address.

Ok, yeah I didn't look at the code just yet, but I was assuming so. Can you clarify that in the PR description as well, so that it will be clear in the future what to expect from this change?

Also, as you wrote in the description, not adding this to the frontend make sense, at least for now.

@davidrapan
Copy link
Contributor Author

davidrapan commented May 19, 2025

I am not really worried what the source address of the multicast packet is, it's largely irrelevant for the receiving system.

Of course it is, I just wanted to provide "full picture", just in case. 😉

This really deviates a bit from that PR, but I try to understand the ramification of enabled privacy extensions for Home Assistant as a whole, and tap your expertise on this topic

  • ip addr: valid_lft 271sec, preferred_lft 121sec
  • mDNS TTL: 120 seconds

I am worried about the remote system here. From what I understand, there is no way for the remote system to tell which address is which.

In the case of mDNS? It doesn't matter.

Ok, yeah I didn't look at the code just yet, but I was assuming so. Can you clarify that in the PR description as well, so that it will be clear in the future what to expect from this change?

Sure.

Also, as you wrote in the description, not adding this to the frontend make sense, at least for now.

👍

@davidrapan
Copy link
Contributor Author

davidrapan commented May 19, 2025

And I do rely heavily on the mDNS. I'm connecting almost everything within my network through .local. Using 3 VLANs, HA is the only one (not counting network elements) connected to all of them and router is running custom build of avahi mDNS repeater with hardcoded mac filter for HA :-D ...

@agners
Copy link
Member

agners commented May 19, 2025

* `ip addr: valid_lft 271sec, preferred_lft 121sec`

* mDNS TTL: 120 seconds

Hm, ok I see https://datatracker.ietf.org/doc/html/rfc6762#section-10 says 120 seconds for the host records (including A and AAAA). It seems that non-host records have much higher values by default, it was probably what I had in mind. Python Zeroconf seems to also use the RFC values, so we should be fine.

I am worried about the remote system here. From what I understand, there is no way for the remote system to tell which address is which.

In the case of mDNS? It doesn't matter.

Ok, yeah with the above it doesn't matter because the TTL is lower than the lifetime of the IP address. As long as the client doesn't store/use the address longer than TTL (which probably should be seen as a bug), we should be fine.

Related: Do you happen to know how an open TCP connection behaves in face of this? 🤔

@davidrapan
Copy link
Contributor Author

davidrapan commented May 19, 2025

This temporary address is not regenerated that often (RFC says the default TEMP_PREFERRED_LIFETIME is 1 day). + I've never seen it used as a destination address, so I'd have to do some synthetic testing, but my best guess is a simple dc and in case of source address.. I'm using this configuration on every machine sice forever and never noticed anything unusual in terms of connection stability :)

@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@home-assistant home-assistant bot marked this pull request as draft May 19, 2025 18:23
@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch 2 times, most recently from a93298e to babdd8a Compare May 19, 2025 21:25
@davidrapan davidrapan marked this pull request as ready for review May 19, 2025 21:28
@home-assistant home-assistant bot requested a review from agners May 19, 2025 21:28
@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch from babdd8a to 87589a1 Compare May 20, 2025 03:49
Copy link
Member

@agners agners left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the suggested changes applied the tests then also need some adjustments. Other than those defaults, LGTM!

@home-assistant home-assistant bot marked this pull request as draft May 20, 2025 07:43
@home-assistant home-assistant bot marked this pull request as draft May 20, 2025 13:12
@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch from 485f02d to 48a521d Compare May 20, 2025 13:21
@davidrapan davidrapan marked this pull request as ready for review May 20, 2025 13:23
@home-assistant home-assistant bot requested a review from agners May 20, 2025 13:23
@agners
Copy link
Member

agners commented May 20, 2025

There are some ruff issues still.

Ideally also rebase, I merged two PRs. I think then we are good!

@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch from 48a521d to 7a236d0 Compare May 20, 2025 13:35
@davidrapan
Copy link
Contributor Author

davidrapan commented May 20, 2025

Oh yeah forgot to check ruff after the changes. 😉

What's up w/ that AwesomeVersion in tests (other than test change)?

@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch 4 times, most recently from 162d888 to 7a71f2f Compare May 20, 2025 13:45
@davidrapan
Copy link
Contributor Author

davidrapan commented May 20, 2025

Anyway, builds still fails

Load key ".ssh/id_rsa": error in libcrypto

for some reason since the last bump of crypto. :/

When I revert the bump, everything works.

@agners
Copy link
Member

agners commented May 20, 2025

How do you build Supervisor?

@davidrapan davidrapan force-pushed the dev_ipv6_addr-gen-mode branch from 7a71f2f to bb94f15 Compare May 20, 2025 13:58
@agners
Copy link
Member

agners commented May 20, 2025

When I revert the bump, everything works.

Ah I see, you meant in CI. That is because the wheels bump gets triggered. I wonder though why that is the case, the necessary wheels should be present 🤔

@davidrapan
Copy link
Contributor Author

Yeah, since I'm not home right now, I thought it might be because of that, but what I found strange is why version has such a significance, since I'm not that familiar with all these quality of life "contraptions" yet. :P

@agners
Copy link
Member

agners commented May 20, 2025

Yeah our infrastructure builds wheels for musllinux automatically. However, that wheels build should only trigger if a PR touches requirements.txt or build.yaml. Wheels build do fail for PRs from forks currently because CI can't reed the necessary keys to upload wheels to our servers (for security reasons).

Your PR should not touch those files, so no wheels build should be triggered. 🤔

It seems to work now, so I think it's fine.

@davidrapan
Copy link
Contributor Author

davidrapan commented May 20, 2025

Yeah, I think I get it:

if: needs.init.outputs.requirements == 'true'

this evaluates to True and shouldn't. 😉

@davidrapan
Copy link
Contributor Author

davidrapan commented May 20, 2025

I don't understand that AwesomeVersion thing. When it's the class it complains it's not valid... but it doesn't like string either...

Edit: Ah, now it's a mocking issue, or even better it's a mocking issue all along. :-D

This fixes the test by since the extended implementation now can read
the version of NetworkManager.
@agners
Copy link
Member

agners commented May 20, 2025

Edit: Ah, now it's a mocking issue, or even better it's a mocking issue all along. :-D

Yes, and we have fixture for that. Just updated the test, should be fine now.

@davidrapan
Copy link
Contributor Author

davidrapan commented May 20, 2025

Great, thanks!

It's annoying that it revealed itself as a mocking issue only after I used comparison to string. :-P

@agners
Copy link
Member

agners commented May 20, 2025

Added another test to validate addr_gen_mode is correctly set. And actually realized that 1.40.0 already knows value default value 3, so I've fixed that.

Copy link
Member

@agners agners left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@agners agners merged commit 3b575ee into home-assistant:main May 20, 2025
22 checks passed
@davidrapan
Copy link
Contributor Author

Awesome! 🎉

@davidrapan davidrapan deleted the dev_ipv6_addr-gen-mode branch May 20, 2025 19:10
@github-actions github-actions bot locked and limited conversation to collaborators May 22, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants