1
0
mirror of https://github.com/containers/netavark.git synced 2026-02-05 06:45:56 +01:00

Add vrf support for bridges

Signed-off-by: André Cirne <dumahk21@gmail.com>
This commit is contained in:
André Cirne
2023-09-24 09:31:39 +01:00
parent d93d03c276
commit 4b6d5ab263
4 changed files with 104 additions and 1 deletions

View File

@@ -19,7 +19,7 @@ use super::{
constants::{
ISOLATE_OPTION_FALSE, ISOLATE_OPTION_STRICT, ISOLATE_OPTION_TRUE,
NO_CONTAINER_INTERFACE_ERROR, OPTION_ISOLATE, OPTION_METRIC, OPTION_MTU,
OPTION_NO_DEFAULT_ROUTE,
OPTION_NO_DEFAULT_ROUTE, OPTION_VRF,
},
core_utils::{self, get_ipam_addresses, join_netns, parse_option, CoreUtils},
driver::{self, DriverInfo},
@@ -50,6 +50,8 @@ struct InternalData {
metric: Option<u32>,
/// if set, no default gateway will be added
no_default_route: bool,
/// sef vrf for bridge
vrf: Option<String>,
// TODO: add vlan
}
@@ -81,6 +83,7 @@ impl driver::NetworkDriver for Bridge<'_> {
let metric: u32 = parse_option(&self.info.network.options, OPTION_METRIC)?.unwrap_or(100);
let no_default_route: bool =
parse_option(&self.info.network.options, OPTION_NO_DEFAULT_ROUTE)?.unwrap_or(false);
let vrf: Option<String> = parse_option(&self.info.network.options, OPTION_VRF)?;
let static_mac = match &self.info.per_network_opts.static_mac {
Some(mac) => Some(CoreUtils::decode_address_from_hex(mac)?),
@@ -96,6 +99,7 @@ impl driver::NetworkDriver for Bridge<'_> {
isolate,
metric: Some(metric),
no_default_route,
vrf,
});
Ok(())
}
@@ -494,6 +498,15 @@ fn create_interfaces(
InfoKind::Bridge,
);
create_link_opts.mtu = data.mtu;
if let Some(vrf_name) = &data.vrf {
let vrf = match host.get_link(netlink::LinkID::Name(vrf_name.to_string())) {
Ok(vrf) => check_link_is_vrf(vrf, vrf_name)?,
Err(err) => return Err(err).wrap("get vrf to set up bridge interface"),
};
create_link_opts.primary_index = vrf.header.index;
}
host.create_link(create_link_opts).wrap("create bridge")?;
if data.ipam.ipv6_enabled {
@@ -672,6 +685,30 @@ fn check_link_is_bridge(msg: LinkMessage, br_name: &str) -> NetavarkResult<LinkM
)))
}
/// make sure the LinkMessage is the kind VRF
fn check_link_is_vrf(msg: LinkMessage, vrf_name: &str) -> NetavarkResult<LinkMessage> {
for nla in msg.nlas.iter() {
if let Nla::Info(info) = nla {
for inf in info.iter() {
if let Info::Kind(kind) = inf {
if *kind == InfoKind::Vrf {
return Ok(msg);
} else {
return Err(NetavarkError::Message(format!(
"vrf {} already exists but is a {:?} interface",
vrf_name, kind
)));
}
}
}
}
}
Err(NetavarkError::Message(format!(
"could not determine namespace link kind for vrf {}",
vrf_name
)))
}
fn remove_link(
host: &mut netlink::Socket,
netns: &mut netlink::Socket,

View File

@@ -21,6 +21,7 @@ pub const OPTION_MODE: &str = "mode";
pub const OPTION_METRIC: &str = "metric";
pub const OPTION_NO_DEFAULT_ROUTE: &str = "no_default_route";
pub const OPTION_BCLIM: &str = "bclim";
pub const OPTION_VRF: &str = "vrf";
/// 100 is the default metric for most Linux networking tools.
pub const DEFAULT_METRIC: u32 = 100;

33
test/600-bridge-vrf.bats Normal file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bats -*- bats -*-
#
# bridge driver tests with vrf
#
load helpers
@test vrf - bridge with vrf {
run_in_host_netns ip link add test-vrf type vrf table 10
run_in_host_netns ip link set dev test-vrf up
run_netavark --file ${TESTSDIR}/testfiles/simplebridge-vrf.json setup $(get_container_netns_path)
# check if vrf exists
run_in_host_netns ip -j --details link show podman0
result="$output"
assert_json "$result" ".[].linkinfo.info_slave_kind" "==" "vrf" "Bridge has a vrf set"
assert_json "$result" ".[].master" "==" "test-vrf" "Bridge has the correct vrf set"
}
@test vrf - simple bridge {
run_netavark --file ${TESTSDIR}/testfiles/simplebridge.json setup $(get_container_netns_path)
run_in_host_netns ip -j --details link show podman0
result="$output"
assert_json "$result" ".[].linkinfo.info_slave_kind" "==" "null" "VRF is not set"
}
@test vrf - non existent vrf {
expected_rc=1 run_netavark --file ${TESTSDIR}/testfiles/simplebridge-vrf.json setup $(get_container_netns_path)
result="$output"
assert_json "$result" ".error" "==" "get vrf to set up bridge interface: Netlink error: No such device (os error 19)" "Attempt to set a non existent vrf"
}

View File

@@ -0,0 +1,32 @@
{
"container_id": "6ce776ea58b5",
"container_name": "testcontainer",
"networks": {
"podman": {
"interface_name": "eth0",
"static_ips": [
"10.88.0.2"
]
}
},
"network_info": {
"podman": {
"dns_enabled": false,
"driver": "bridge",
"id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e",
"internal": false,
"ipv6_enabled": false,
"name": "podman",
"network_interface": "podman0",
"subnets": [
{
"gateway": "10.88.0.1",
"subnet": "10.88.0.0/16"
}
],
"options": {
"vrf": "test-vrf"
}
}
}
}