Skip to content

Commit fdfbbca

Browse files
committed
feat(dhcpv6): Add DHCPv6 support for macvlan and bridge drivers
This commit introduces full support for stateful IPv6 address assignment via DHCPv6, resolving the issue where containers would not receive a global IPv6 address on macvlan networks. The implementation follows the standard IPv6 design of separating gateway discovery (via Router Advertisements) from stateful address assignment (via DHCPv6). Key changes include: - **Kernel Configuration:** Netavark now configures the container's kernel to accept Router Advertisements (`accept_ra=2`) for automatic gateway discovery, while disabling SLAAC (`autoconf=0`) to ensure a managed, deterministic network environment. - **DHCPv6 Service:** A new `DhcpV6Service` is added to the DHCP proxy. It uses the `mozim` library to acquire IPv6 leases and correctly generates a stable DUID-LL from the container's static MAC address to ensure a persistent network identity. - **gRPC Layer:** The gRPC `Lease` object and its `From` implementations have been updated to act as a universal carrier for both IPv4 and IPv6 lease information. - **Generic Proxy Logic:** Core functions like `process_client_stream` and `update_lease_ip` have been refactored to handle both DHCPv4 and DHCPv6 services generically, with conditional logic to correctly handle the differences between the protocols (e.g., gateway handling). Signed-off-by: Rishikpulhani <[email protected]>
1 parent 7d87176 commit fdfbbca

File tree

12 files changed

+790
-168
lines changed

12 files changed

+790
-168
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ futures-core = "0.3.31"
6262
futures-util = "0.3.31"
6363
tower = { version = "0.5.2", features = ["util"] }
6464
hyper-util = "0.1.17"
65+
hex = "0.4.3"
66+
dhcproto = "0.12.0"
6567

6668
[build-dependencies]
6769
chrono = { version = "0.4.42", default-features = false, features = ["clock"] }

src/commands/dhcp_proxy.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![cfg_attr(not(unix), allow(unused_imports))]
22

33
use crate::dhcp_proxy::cache::{Clear, LeaseCache};
4-
use crate::dhcp_proxy::dhcp_service::{process_client_stream, DhcpV4Service};
4+
use crate::dhcp_proxy::dhcp_service::{
5+
process_client_stream, DhcpService, DhcpV4Service, DhcpV6Service,
6+
};
57
use crate::dhcp_proxy::ip;
68
use crate::dhcp_proxy::lib::g_rpc::netavark_proxy_server::{NetavarkProxy, NetavarkProxyServer};
79
use crate::dhcp_proxy::lib::g_rpc::{
@@ -14,6 +16,7 @@ use crate::error::{NetavarkError, NetavarkResult};
1416
use crate::network::core_utils;
1517
use clap::Parser;
1618
use log::{debug, error, warn};
19+
use mozim::DhcpV6IaType;
1720
use tokio::task::AbortHandle;
1821

1922
use std::collections::HashMap;
@@ -38,7 +41,7 @@ use tonic::{
3841
transport::Server, Code, Code::Internal, Code::InvalidArgument, Request, Response, Status,
3942
};
4043

41-
type TaskData = (Arc<tokio::sync::Mutex<DhcpV4Service>>, AbortHandle);
44+
type TaskData = (Arc<tokio::sync::Mutex<DhcpService>>, AbortHandle);
4245

4346
#[derive(Debug)]
4447
/// This is the tonic netavark proxy service that is required to impl the Netavark Proxy trait which
@@ -437,7 +440,7 @@ async fn process_setup<W: Write + Clear>(
437440
let mut service = DhcpV4Service::new(network_config, timeout)?;
438441

439442
let lease = service.get_lease().await?;
440-
let service_arc = Arc::new(tokio::sync::Mutex::new(service));
443+
let service_arc = Arc::new(tokio::sync::Mutex::new(DhcpService::V4(service)));
441444
let service_arc_clone = service_arc.clone();
442445
let task_handle = tokio::spawn(process_client_stream(service_arc_clone));
443446
tasks
@@ -446,9 +449,20 @@ async fn process_setup<W: Write + Clear>(
446449
.insert(mac.to_string(), (service_arc, task_handle.abort_handle()));
447450
lease
448451
}
449-
//V6 TODO implement DHCPv6
450452
1 => {
451-
return Err(Status::new(InvalidArgument, "ipv6 not yet supported"));
453+
// ia_type for conatainers is generally NonTemporaryAddresses
454+
let mut service =
455+
DhcpV6Service::new(network_config, timeout, DhcpV6IaType::NonTemporaryAddresses)?;
456+
let lease = service.get_lease().await?;
457+
// service in the generic DhcpService enum.
458+
let service_arc = Arc::new(tokio::sync::Mutex::new(DhcpService::V6(service)));
459+
let service_arc_clone = service_arc.clone();
460+
let task_handle = tokio::spawn(process_client_stream(service_arc_clone));
461+
tasks
462+
.lock()
463+
.expect("lock tasks")
464+
.insert(mac.to_string(), (service_arc, task_handle.abort_handle()));
465+
lease
452466
}
453467
_ => {
454468
return Err(Status::new(InvalidArgument, "invalid protocol version"));

0 commit comments

Comments
 (0)