From 7e0eed9326e2541702ac3e75eddb73f61ce3d926 Mon Sep 17 00:00:00 2001 From: Jim Paris Date: Thu, 21 Dec 2023 22:57:46 -0500 Subject: [PATCH] bridge: support DHCP ipam driver Support DHCP for bridge driver, like macvlan. Signed-off-by: Jim Paris --- src/network/bridge.rs | 19 ++++++++++++++- src/network/core_utils.rs | 51 ++++++++++++++++++++++++++++++++++++++- src/network/vlan.rs | 43 +++------------------------------ 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/network/bridge.rs b/src/network/bridge.rs index 2d514887f..88fba6c75 100644 --- a/src/network/bridge.rs +++ b/src/network/bridge.rs @@ -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}, @@ -150,9 +151,23 @@ impl driver::NetworkDriver for Bridge<'_> { // interfaces map, but we only ever expect one, for response let mut interfaces: HashMap = 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); @@ -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 diff --git a/src/network/core_utils.rs b/src/network/core_utils.rs index 8638f98f4..b5deced07 100644 --- a/src/network/core_utils.rs +++ b/src/network/core_utils.rs @@ -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; @@ -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; @@ -446,3 +452,46 @@ pub fn disable_ipv6_autoconf(if_name: &str) -> NetavarkResult<()> { }; Ok(()) } + +pub fn get_mac_address(v: Vec) -> NetavarkResult { + 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(()) +} diff --git a/src/network/vlan.rs b/src/network/vlan.rs index 83e84c214..8d60012f7 100644 --- a/src/network/vlan.rs +++ b/src/network/vlan.rs @@ -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}, @@ -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}, @@ -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() { @@ -376,17 +350,6 @@ fn setup( get_mac_address(dev.attributes) } -fn get_mac_address(v: Vec) -> NetavarkResult { - 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 { let routes = host.dump_routes().wrap("dump routes")?;