-
Notifications
You must be signed in to change notification settings - Fork 389
container: T7186: Add macvlan network type for containers #4686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Modified: - interface-definitions/container.xml.in: - Add macvlan network type - Add gateway option - python/vyos/utils/network.py: - Add gen_mac function to generate mac address - smoketest/scripts/cli/test_container.py: - Add test for container network types - src/conf_mode/container.py: - Add support for macvlan network type - Add gateway option
👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for macvlan network type in VyOS container configuration, allowing containers to connect directly to physical networks with dedicated MAC addresses. This enables containers to appear as separate hosts on the physical network rather than being behind NAT.
- Adds macvlan network type with configurable mode (bridge/private/vepa) and parent interface
- Implements custom gateway configuration for container networks
- Generates deterministic MAC addresses for containers using host identity and container details
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
File | Description |
---|---|
src/conf_mode/container.py | Core implementation for macvlan network support, gateway validation, and MAC address generation |
smoketest/scripts/cli/test_container.py | Test cases for macvlan and bridge network types |
python/vyos/utils/network.py | Utility functions for generating deterministic MAC addresses |
interface-definitions/container.xml.in | CLI configuration schema for gateway and network type options |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/conf_mode/container.py
Outdated
mac_address = f'--mac-address {gen_mac(name, addr_info)}' | ||
|
||
return f'{container_base_cmd} --no-healthcheck --net {networks} {ip_param} {mac_address} {entrypoint} {image} {command} {command_arguments}'.strip() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MAC address generation logic runs for every network loop iteration but only uses the last network's address. This will generate incorrect MAC addresses for containers with multiple networks and overwrite the mac_address variable on each iteration.
mac_address = f'--mac-address {gen_mac(name, addr_info)}' | |
return f'{container_base_cmd} --no-healthcheck --net {networks} {ip_param} {mac_address} {entrypoint} {image} {command} {command_arguments}'.strip() | |
mac_address += f' --mac-address {gen_mac(name, addr_info)}' | |
return f'{container_base_cmd} --no-healthcheck --net {networks} {ip_param}{mac_address} {entrypoint} {image} {command} {command_arguments}'.strip() |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one network can be applied to a container:
if 'network' in container_config:
if len(container_config['network']) > 1:
raise ConfigError(f'Only one network can be specified for container "{name}"!')
With that said, to prevent collisions in case that behavior changes later, I'll make some changes to move the gen_mac()
function outside of that loop.
src/conf_mode/container.py
Outdated
net_interface = dict_search('macvlan.parent', type_config) | ||
driver = 'macvlan' | ||
mode = dict_search('macvlan.mode', type_config) | ||
elif dict_search('bridge', type_config) != None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using != None
is unnecessary and not idiomatic. Use is not None
instead, or simply check the truthiness with elif dict_search('bridge', type_config):
.
elif dict_search('bridge', type_config) != None: | |
elif dict_search('bridge', type_config) is not None: |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dict_search
will return either None if the path doesn't exist, or {}
if it does. This would cause a simple if dict_search()
to fail, so the None
check is required. I'll make it is not None
uuid = cmd(f"cat /sys/class/dmi/id/product_uuid").strip().replace("-", "").lower() | ||
host = cmd("hostname").strip().lower() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These commands are executed every time gen_mac()
is called through get_host_identity()
. Since host identity rarely changes during runtime, consider caching the result to avoid repeated subprocess calls.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, there's no need to get that data per-container. I'll make that change.
ident = get_host_identity() | ||
h = hashlib.sha256(f"{ident}:{name}:{addr}".encode()).hexdigest() | ||
# 0x02 = locally-administered, unicast | ||
b = [0x02] + [int(h[i:i+2], 16) for i in range(0, 10, 2)] # 5 bytes = 40 bits |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magic number 10
should be extracted as a constant or calculated as 5 * 2
to make the relationship between 5 bytes and 10 hex characters explicit.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
10 isn't a magic number, it's the number of digits I need to grab to equal 40bits. Each hex digit is 4 bits, so 10*4=40. I don't think changing this as Copilot suggests is an improvement.
- Moved gen_mac function outside of 'for network' loop - Cached result of get_host_identity() to prevent multiple calls - Other minor improvements per Copilot suggestions
CI integration ❌ failed! Details
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes suggested by copilot made; smoketest additions tested and passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. One note: macvlan interfaces are historically known as "pseudo-ethernet" in VyOS — a strange decision that has been carried over from Vyatta (set interfaces pseudo-ethernet pethX ...
).
Now we will have both "MACVLAN" and "pseudo-ethernet" terms in the system, so I wonder if we should eventually rename interfaces pseudo-ethernet
to interfaces macvlan
.
Change summary
This change adds the ability to configure macvlan as a network type for podman.
Syntax additions:
Example network JSON:
Types of changes
Related Task(s)
https://vyos.dev/T7186
Related PR(s)
How to test / Smoketest result
Configure physical interface to use as container network's parent (note that it doesn't need an IP):
Configure the macvlan network:
Optionally add a gateway. This is important since a physical network might have a gateway that isn't the first IP in the subnet:
Attach a container to the network. This will be the same syntax as it's always been:
You should see the MAC address for the container in the FDB of VyOS:
The IP should be reachable on your physical network:
Smoketest results:
Checklist: