Skip to content

Commit

Permalink
bridge: support DHCP ipam driver
Browse files Browse the repository at this point in the history
Support DHCP for bridge driver, like macvlan.

Signed-off-by: Jim Paris <[email protected]>
  • Loading branch information
jimparis committed Mar 10, 2024
1 parent 3a1902a commit 7e0eed9
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 42 deletions.
19 changes: 18 additions & 1 deletion src/network/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use netlink_packet_route::link::{
InfoData, InfoKind, InfoVeth, LinkAttribute, LinkInfo, LinkMessage,
};

use crate::network::macvlan_dhcp::{get_dhcp_lease};
use crate::{
dns::aardvark::AardvarkEntry,
error::{ErrorWrap, NetavarkError, NetavarkErrorList, NetavarkResult},
Expand Down Expand Up @@ -150,9 +151,23 @@ impl driver::NetworkDriver for Bridge<'_> {
// interfaces map, but we only ever expect one, for response
let mut interfaces: HashMap<String, types::NetInterface> = HashMap::new();

// if dhcp is enabled, we need to call the dhcp proxy to perform
// a dhcp lease. it will also perform the IP address assignment
// to the container interface.
let subnets = if data.ipam.dhcp_enabled {
get_dhcp_lease(
&data.bridge_interface_name,
&data.container_interface_name,
self.info.netns_path,
&container_veth_mac,
)?
} else {
data.ipam.net_addresses.clone()
};

let interface = types::NetInterface {
mac_address: container_veth_mac,
subnets: Option::from(data.ipam.net_addresses.clone()),
subnets: Option::from(subnets),
};
// Add interface to interfaces (part of StatusBlock)
interfaces.insert(data.container_interface_name.clone(), interface);
Expand Down Expand Up @@ -250,6 +265,8 @@ impl driver::NetworkDriver for Bridge<'_> {

let mut error_list = NetavarkErrorList::new();

core_utils::dhcp_teardown(&self.info, netns_sock)?;

let routes = core_utils::create_route_list(&self.info.network.routes)?;
for route in routes.iter() {
netns_sock
Expand Down
51 changes: 50 additions & 1 deletion src/network/core_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::error::{ErrorWrap, NetavarkError, NetavarkResult};
use crate::network::{constants, internal_types, types};
use crate::network::macvlan_dhcp::{release_dhcp_lease};
use crate::wrap;
use ipnet::IpNet;
use log::debug;
Expand All @@ -17,7 +18,12 @@ use std::os::unix::prelude::*;
use std::str::FromStr;
use sysctl::{Sysctl, SysctlError};

use super::netlink;
use super::{
netlink,
driver::{DriverInfo},
};

use netlink_packet_route::link::{LinkAttribute};

pub const IPVLAN_MODE_L2: u16 = 0;
pub const IPVLAN_MODE_L3: u16 = 1;
Expand Down Expand Up @@ -446,3 +452,46 @@ pub fn disable_ipv6_autoconf(if_name: &str) -> NetavarkResult<()> {
};
Ok(())
}

pub fn get_mac_address(v: Vec<LinkAttribute>) -> NetavarkResult<String> {
for nla in v.into_iter() {
if let LinkAttribute::Address(ref addr) = nla {
return Ok(CoreUtils::encode_address_to_hex(addr));
}
}
Err(NetavarkError::msg(
"failed to get the the container mac address",
))
}

pub fn dhcp_teardown(
info: &DriverInfo, sock: &mut netlink::Socket,
) -> NetavarkResult<()> {

let ipam = get_ipam_addresses(info.per_network_opts, info.network)?;
let if_name = info.per_network_opts.interface_name.clone();

// If we are using DHCP, we need to at least call to the proxy so that
// the proxy's cache can get updated and the current lease can be released.
if ipam.dhcp_enabled {
let dev = sock
.get_link(netlink::LinkID::Name(if_name))
.wrap(format!(
"get container interface {}",
&info.per_network_opts.interface_name
))?;

let container_mac_address = get_mac_address(dev.attributes)?;
release_dhcp_lease(
&info
.network
.network_interface
.clone()
.unwrap_or_default(),
&info.per_network_opts.interface_name,
info.netns_path,
&container_mac_address,
)?
}
Ok(())
}
43 changes: 3 additions & 40 deletions src/network/vlan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{collections::HashMap, net::IpAddr};
use netlink_packet_route::link::{InfoData, InfoIpVlan, InfoKind, InfoMacVlan, LinkAttribute};
use rand::distributions::{Alphanumeric, DistString};

use crate::network::macvlan_dhcp::{get_dhcp_lease, release_dhcp_lease};
use crate::network::macvlan_dhcp::{get_dhcp_lease};
use crate::{
dns::aardvark::AardvarkEntry,
error::{ErrorWrap, NetavarkError, NetavarkResult},
Expand All @@ -18,7 +18,7 @@ use super::{
NO_CONTAINER_INTERFACE_ERROR, OPTION_BCLIM, OPTION_METRIC, OPTION_MODE, OPTION_MTU,
OPTION_NO_DEFAULT_ROUTE,
},
core_utils::{self, get_ipam_addresses, parse_option, CoreUtils},
core_utils::{self, get_ipam_addresses, get_mac_address, parse_option, CoreUtils},
driver::{self, DriverInfo},
internal_types::IPAMAddresses,
netlink::{self, CreateLinkOptions},
Expand Down Expand Up @@ -206,33 +206,7 @@ impl driver::NetworkDriver for Vlan<'_> {
&self,
netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket),
) -> NetavarkResult<()> {
let ipam = get_ipam_addresses(self.info.per_network_opts, self.info.network)?;
let if_name = self.info.per_network_opts.interface_name.clone();

// If we are using DHCP macvlan, we need to at least call to the proxy so that
// the proxy's cache can get updated and the current lease can be released.
if ipam.dhcp_enabled {
let dev = netlink_sockets
.1
.get_link(netlink::LinkID::Name(if_name))
.wrap(format!(
"get macvlan interface {}",
&self.info.per_network_opts.interface_name
))?;

let container_mac_address = get_mac_address(dev.attributes)?;
release_dhcp_lease(
&self
.info
.network
.network_interface
.clone()
.unwrap_or_default(),
&self.info.per_network_opts.interface_name,
self.info.netns_path,
&container_mac_address,
)?
}
core_utils::dhcp_teardown(&self.info, netlink_sockets.1)?;

let routes = core_utils::create_route_list(&self.info.network.routes)?;
for route in routes.iter() {
Expand Down Expand Up @@ -376,17 +350,6 @@ fn setup(
get_mac_address(dev.attributes)
}

fn get_mac_address(v: Vec<LinkAttribute>) -> NetavarkResult<String> {
for nla in v.into_iter() {
if let LinkAttribute::Address(ref addr) = nla {
return Ok(CoreUtils::encode_address_to_hex(addr));
}
}
Err(NetavarkError::msg(
"failed to get the the container mac address",
))
}

fn get_default_route_interface(host: &mut netlink::Socket) -> NetavarkResult<String> {
let routes = host.dump_routes().wrap("dump routes")?;

Expand Down

0 comments on commit 7e0eed9

Please sign in to comment.