dhcpv4: support socket creation in netns - #79
Conversation
|
@cathay4t Can you review this PR. |
cathay4t
left a comment
There was a problem hiding this comment.
Please also provide integration test case for this feature, ideally example code also.
|
Copilot also suggest this changes which I find reasonable: diff --git a/src/dhcpv4/socket.rs b/src/dhcpv4/socket.rs
index 4f2ba9e..4fad44c 100644
--- a/src/dhcpv4/socket.rs
+++ b/src/dhcpv4/socket.rs
@@ -4,6 +4,7 @@ use std::{
ffi::CString,
fs::File,
future::Future,
+ marker::PhantomData,
net::{Ipv4Addr, UdpSocket as StdUdpSocket},
os::{
fd::{AsFd, AsRawFd, OwnedFd},
@@ -327,13 +328,20 @@ fn bind_socket_to_iface(fd: RawFd, iface_name: &str) -> Result<(), DhcpError> {
struct NetnsGuard {
host_netns: Option<File>,
+ // Prevent Send so this guard cannot be held across await points.
+ // setns() only affects the calling thread; moving across threads would
+ // silently switch the wrong thread's namespace.
+ _not_send: PhantomData<*const ()>,
}
impl NetnsGuard {
// This switches only the current thread and must not be held across await.
fn enter(netns_path: Option<&str>) -> Result<Self, DhcpError> {
let Some(netns_path) = netns_path else {
- return Ok(Self { host_netns: None });
+ return Ok(Self {
+ host_netns: None,
+ _not_send: PhantomData,
+ });
};
let host_netns = File::open("/proc/self/ns/net").map_err(|e| {
@@ -362,6 +370,7 @@ impl NetnsGuard {
Ok(Self {
host_netns: Some(host_netns),
+ _not_send: PhantomData,
})
}
} |
4c3ed0d to
f215ab8
Compare
Done. I added the PhantomData<*const ()> marker so NetnsGuard is !Send. The implementation is slightly adjusted from the suggested diff because the guard is now only constructed when socket_netns_path is Some, so NetnsGuard::enter takes the namespace path directly and stores the host netns File directly. The safety intent is the same: the guard cannot be sent across threads while setns() is active. |
|
@cathay4t I addressed the review comments and force-pushed the updated branch. Changes made:
Validation completed:
The x86_64 VM full test result was 13 tests passed plus 2 doctests passed. |
|
Please squash commits into single one. Thanks! Please give me more time on reviewing. |
|
I have doubt on using |
Allow DHCPv4 callers to request socket creation inside a target network namespace without moving the async DHCP flow into that namespace. The netns switch is scoped to socket open/bind, only runs when socket_netns_path is set, and uses a non-Send guard so the setns state cannot cross await points. Add integration coverage and an example for the netns socket path flow.
a74a817 to
a0d4fa4
Compare
|
Cool, squashed into a single commit. Please take your time on the review. and on the My understanding is that holding an |
| let mut config = DhcpV4Config::new_proxy(&args[1], &args[2])?; | ||
| config.set_iface_index(iface_index); | ||
| config.set_socket_netns_path(Some(args[4].clone())); |
There was a problem hiding this comment.
I think this example is wrong.
The iface_index is in host network namespace which does not exist in container's namespace. This socket binding will fail after we switched to container namespace.
The whole point of DHCP proxy in container usage is running DHCP process in host network namespace.
cathay4t
left a comment
There was a problem hiding this comment.
Please provide more detail on this unmanaged bridge VLAN setups use case.
And this tokio async runner in host namespace, but UDP socket in container namespace is weird (I don't even know how to describe why we need this use case to kernel network team).
|
My bad @cathay4t , After spending more time reproducing the original Netavark issue, I agree this mozim change is not the right direction. The issue turned out to be specific to Netavark unmanaged bridge VLAN handling: for a network configured with I’m reworking the Netavark PR to fix this in Netavark by using a bridge VLAN interface for DHCP traffic, without changing mozim’s socket/netns behavior or adding this API. Closing this PR to avoid adding an unnecessary mozim feature. Thanks again for the guidance and pointing the issue out! |
This is a dependency PR for netavark work here:
containers/netavark#1307
This adds support for opening DHCPv4 sockets inside a target network namespace
without moving the higher-level async DHCP flow into that namespace.
Summary:
Why:
Netavark needs DHCP traffic for unmanaged bridge VLAN setups to originate from
the target network namespace, but doing that in Netavark by spawning a dedicated
Tokio runtime per container is the wrong layer and does not scale well.
This keeps the namespace-sensitive part limited to socket open/bind time and
lets callers keep their normal async/task model.