Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package netavark for openSUSE:Factory checked in at 2026-02-26 18:50:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/netavark (Old) and /work/SRC/openSUSE:Factory/.netavark.new.29461 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "netavark" Thu Feb 26 18:50:18 2026 rev:23 rq:1334703 version:1.17.2 Changes: -------- --- /work/SRC/openSUSE:Factory/netavark/netavark.changes 2025-12-24 13:16:40.631364346 +0100 +++ /work/SRC/openSUSE:Factory/.netavark.new.29461/netavark.changes 2026-02-26 18:50:33.970307786 +0100 @@ -1,0 +2,13 @@ +Fri Feb 20 09:51:40 UTC 2026 - Madhankumar Chellamuthu <[email protected]> + +- Update to version 1.17.2: + * release v1.17.2 + * release notes for v1.17.2 + * netlink_route: remove NLM_F_ACK from dump requests + * netlink: validate buffer length + * netlink: zero out buffer before sending + * netlink: socket read logic + * bridge: read mtu from vrf table if set + * only consult main routing table for default interface + +------------------------------------------------------------------- Old: ---- netavark-1.17.1.tar.gz New: ---- netavark-1.17.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ netavark.spec ++++++ --- /var/tmp/diff_new_pack.nNAstp/_old 2026-02-26 18:50:44.022726994 +0100 +++ /var/tmp/diff_new_pack.nNAstp/_new 2026-02-26 18:50:44.038727661 +0100 @@ -1,7 +1,7 @@ # # spec file for package netavark # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define major_minor %((v=%{version}; echo ${v%.*})) Name: netavark -Version: 1.17.1 +Version: 1.17.2 Release: 0 Summary: Container network stack License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.nNAstp/_old 2026-02-26 18:50:44.354740840 +0100 +++ /var/tmp/diff_new_pack.nNAstp/_new 2026-02-26 18:50:44.410743175 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/containers/netavark.git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="scm">git</param> - <param name="revision">v1.17.1</param> + <param name="revision">v1.17.2</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> <param name="versionrewrite-replacement">\1</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.nNAstp/_old 2026-02-26 18:50:44.602751182 +0100 +++ /var/tmp/diff_new_pack.nNAstp/_new 2026-02-26 18:50:44.650753185 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/containers/netavark.git</param> - <param name="changesrevision">7ffb8ec4c2e490a3884451e20aa8ad0471d78579</param></service></servicedata> + <param name="changesrevision">bd7a464482bcc02dca4843c457db584ed7fe14e4</param></service></servicedata> (No newline at EOF) ++++++ netavark-1.17.1.tar.gz -> netavark-1.17.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/Cargo.lock new/netavark-1.17.2/Cargo.lock --- old/netavark-1.17.1/Cargo.lock 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/Cargo.lock 2026-02-05 17:57:22.000000000 +0100 @@ -1049,7 +1049,7 @@ [[package]] name = "netavark" -version = "1.17.1" +version = "1.17.2" dependencies = [ "anyhow", "chrono", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/Cargo.toml new/netavark-1.17.2/Cargo.toml --- old/netavark-1.17.1/Cargo.toml 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/Cargo.toml 2026-02-05 17:57:22.000000000 +0100 @@ -1,6 +1,6 @@ [package] name = "netavark" -version = "1.17.1" +version = "1.17.2" edition = "2021" authors = ["github.com/containers"] license = "Apache-2.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/RELEASE_NOTES.md new/netavark-1.17.2/RELEASE_NOTES.md --- old/netavark-1.17.1/RELEASE_NOTES.md 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/RELEASE_NOTES.md 2026-02-05 17:57:22.000000000 +0100 @@ -1,5 +1,11 @@ # Release Notes +## v1.17.2 + +* Fixed a bug from v1.16.0 where the default mtu detection might consult the wrong routing table and as such pick the incorrect mtu. ([#1381](https://github.com/containers/netavark/issues/1381)) +* If the bridge driver is configured to use an vrf interface then pick the routing table from that vrf instead for the mtu detection. +* Fixed a bug in the netlink code which may result in unexpected EINVAL errors due an incorrect netlink message serialization. + ## v1.17.1 * Fixes a regression where the DHCP proxy would fail when no Renewal or Rebinding time was included in the DHCP message. ([#1368](https://github.com/containers/netavark/issues/1368)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/src/network/bridge.rs new/netavark-1.17.2/src/network/bridge.rs --- old/netavark-1.17.1/src/network/bridge.rs 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/src/network/bridge.rs 2026-02-05 17:57:22.000000000 +0100 @@ -19,12 +19,15 @@ }; use ipnet::IpNet; use log::{debug, error}; -use netlink_packet_route::address::{AddressAttribute, AddressScope}; use netlink_packet_route::link::{ BridgeVlanInfoFlags, InfoBridge, InfoData, InfoKind, InfoVeth, LinkAttribute, LinkInfo, LinkMessage, }; use netlink_packet_route::AddressFamily; +use netlink_packet_route::{ + address::{AddressAttribute, AddressScope}, + link::InfoVrf, +}; use super::{ constants::{ @@ -705,10 +708,21 @@ InfoKind::Bridge, ); + let mut table = None; + if let Some(vrf_name) = &data.vrf { + let (vrf_id, vrf_table) = + match host.get_link(LinkID::Name(vrf_name.to_string())) { + Ok(vrf) => validate_vrf_link(vrf, vrf_name)?, + Err(err) => return Err(err).wrap("get vrf to set up bridge interface"), + }; + create_link_opts.primary_index = vrf_id; + table = vrf_table; + } + let mut mtu = data.mtu; if mtu == 0 { // if we have a default route, use its mtu as default - if let Ok(link) = get_default_route_interface(host) { + if let Ok(link) = get_default_route_interface(host, table) { match core_utils::get_mtu_from_iface_attributes(&link.attributes) { Ok(iface_mtu) => { debug!("Using mtu {iface_mtu} from default route interface for the network"); @@ -727,14 +741,6 @@ Some(InfoData::Bridge(vec![InfoBridge::VlanFiltering(true)])); } - if let Some(vrf_name) = &data.vrf { - let vrf = match host.get_link(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")?; // Note sysctls must be written after the bridge is created @@ -1015,22 +1021,39 @@ } /// make sure the LinkMessage is the kind VRF -fn check_link_is_vrf(msg: LinkMessage, vrf_name: &str) -> NetavarkResult<LinkMessage> { +/// Returns the interface id and the table id if found. +fn validate_vrf_link(msg: LinkMessage, vrf_name: &str) -> NetavarkResult<(u32, Option<u32>)> { + let mut id = None; + let mut table = None; for nla in msg.attributes.iter() { if let LinkAttribute::LinkInfo(info) = nla { for inf in info.iter() { if let LinkInfo::Kind(kind) = inf { if *kind == InfoKind::Vrf { - return Ok(msg); + id = Some(msg.header.index); } else { return Err(NetavarkError::Message(format!( "vrf {vrf_name} already exists but is a {kind:?} interface" ))); } } + + if let LinkInfo::Data(InfoData::Vrf(info_vrf)) = inf { + for vrf in info_vrf { + if let InfoVrf::TableId(id) = vrf { + debug!("Using routing table {id} from vrf {vrf_name} for default route lookup"); + table = Some(*id); + } + } + } } } } + + if let Some(id) = id { + return Ok((id, table)); + } + Err(NetavarkError::Message(format!( "could not determine namespace link kind for vrf {vrf_name}" ))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/src/network/core_utils.rs new/netavark-1.17.2/src/network/core_utils.rs --- old/netavark-1.17.1/src/network/core_utils.rs 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/src/network/core_utils.rs 2026-02-05 17:57:22.000000000 +0100 @@ -398,8 +398,12 @@ } /// Returns the *first* interface with a default route or an error if no default route interface exists. -pub fn get_default_route_interface(host: &mut Socket<NetlinkRoute>) -> NetavarkResult<LinkMessage> { - let routes = host.dump_routes().wrap("dump routes")?; +/// If no table is given we lokup in the main routing table otherwise use the given table id. +pub fn get_default_route_interface( + host: &mut Socket<NetlinkRoute>, + table: Option<u32>, +) -> NetavarkResult<LinkMessage> { + let routes = host.dump_routes(table).wrap("dump routes")?; for route in routes { let mut dest = false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/src/network/netlink.rs new/netavark-1.17.2/src/network/netlink.rs --- old/netavark-1.17.1/src/network/netlink.rs 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/src/network/netlink.rs 2026-02-05 17:57:22.000000000 +0100 @@ -16,11 +16,13 @@ type Message; } +const NLMSG_GOODSIZE: usize = 8192; + pub struct Socket<P: NetlinkFamily> { socket: netlink_sys::Socket, sequence_number: u32, /// buffer size for reading netlink messages, see NLMSG_GOODSIZE in the kernel - buffer: [u8; 8192], + buffer: [u8; NLMSG_GOODSIZE], _protocol: PhantomData<P>, } @@ -90,10 +92,22 @@ }; packet.finalize(); - packet.serialize(&mut self.buffer[..]); + let len = packet.buffer_len(); + let buffer = self.buffer.get_mut(..len).ok_or_else(|| { + NetavarkError::msg(format!( + "netlink request size {len} to large for buffer with len {}", + NLMSG_GOODSIZE + )) + })?; + + // Zero out buffer to work around a bug in the serialize call that does not overwrite all bytes. + // Can be removed again once https://github.com/rust-netlink/netlink-packet-route/pull/224 lands here. + buffer.fill(0); + + packet.serialize(buffer); trace!("send netlink packet: {packet:?}"); - self.socket.send(&self.buffer[..packet.buffer_len()], 0)?; + self.socket.send(buffer, 0)?; Ok(()) } @@ -101,7 +115,6 @@ where P::Message: NetlinkDeserializable + std::fmt::Debug, { - let mut offset = 0; let mut result = Vec::new(); // if multi is set we expect a multi part message @@ -111,9 +124,11 @@ "recv from netlink" )?; + // only use the amount of bytes we actually read + let mut buffer = &self.buffer[..size]; + loop { - let bytes = &self.buffer[offset..]; - let rx_packet: NetlinkMessage<P::Message> = NetlinkMessage::deserialize(bytes) + let rx_packet: NetlinkMessage<P::Message> = NetlinkMessage::deserialize(buffer) .map_err(|e| { NetavarkError::Message(format!( "failed to deserialize netlink message: {e}", @@ -155,11 +170,12 @@ _ => {} }; - offset += rx_packet.header.length as usize; - if offset == size || rx_packet.header.length == 0 { - offset = 0; + let len = rx_packet.header.length as usize; + if buffer.len() == len || len == 0 { break; } + // move the buffer to the next message + buffer = &buffer[len..]; } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/src/network/netlink_route.rs new/netavark-1.17.2/src/network/netlink_route.rs --- old/netavark-1.17.1/src/network/netlink_route.rs 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/src/network/netlink_route.rs 2026-02-05 17:57:22.000000000 +0100 @@ -311,16 +311,22 @@ Ok(()) } - pub fn dump_routes(&mut self) -> NetavarkResult<Vec<RouteMessage>> { - let mut msg = RouteMessage::default(); + /// dump all routes, if no table id is specified the default main table is used. + pub fn dump_routes(&mut self, table: Option<u32>) -> NetavarkResult<Vec<RouteMessage>> { + let mut msg: RouteMessage = RouteMessage::default(); - msg.header.table = libc::RT_TABLE_MAIN; + msg.header.table = libc::RT_TABLE_UNSPEC; msg.header.protocol = RouteProtocol::Unspec; msg.header.scope = RouteScope::Universe; msg.header.kind = RouteType::Unicast; - let results = - self.make_netlink_request(RouteNetlinkMessage::GetRoute(msg), NLM_F_DUMP | NLM_F_ACK)?; + msg.attributes + .push(netlink_packet_route::route::RouteAttribute::Table( + // default to the main table instead of dumping all tables + table.unwrap_or(libc::RT_TABLE_MAIN.into()), + )); + + let results = self.make_netlink_request(RouteNetlinkMessage::GetRoute(msg), NLM_F_DUMP)?; let mut routes = Vec::with_capacity(results.len()); @@ -345,8 +351,7 @@ let mut msg = LinkMessage::default(); msg.attributes.append(nlas); - let results = - self.make_netlink_request(RouteNetlinkMessage::GetLink(msg), NLM_F_DUMP | NLM_F_ACK)?; + let results = self.make_netlink_request(RouteNetlinkMessage::GetLink(msg), NLM_F_DUMP)?; let mut links = Vec::with_capacity(results.len()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/src/network/vlan.rs new/netavark-1.17.2/src/network/vlan.rs --- old/netavark-1.17.1/src/network/vlan.rs 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/src/network/vlan.rs 2026-02-05 17:57:22.000000000 +0100 @@ -245,7 +245,7 @@ kind_data: &KindData, ) -> NetavarkResult<String> { let link = match data.host_interface_name.as_ref() { - "" => get_default_route_interface(host)?, + "" => get_default_route_interface(host, None)?, host_name => host.get_link(LinkID::Name(host_name.to_string()))?, }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netavark-1.17.1/test/640-bridge-mtu.bats new/netavark-1.17.2/test/640-bridge-mtu.bats --- old/netavark-1.17.1/test/640-bridge-mtu.bats 2025-12-08 14:20:27.000000000 +0100 +++ new/netavark-1.17.2/test/640-bridge-mtu.bats 2026-02-05 17:57:22.000000000 +0100 @@ -27,11 +27,40 @@ function add_default_route() { - run_in_host_netns ip link add default_route type dummy - run_in_host_netns ip link set default_route mtu 9000 - run_in_host_netns ip addr add 192.168.0.0/24 dev default_route - run_in_host_netns ip link set default_route up - run_in_host_netns ip route add default via 192.168.0.0 + local ifname=default_route + local table="main" + local mtu=9000 + local vrf="" + # parse arguments + while [[ "$#" -gt 0 ]]; do + IFS='=' read -r arg value <<<"$1" + case "$arg" in + ifname) + ifname="$value" + ;; + table) + table="$value" + ;; + mtu) + mtu="$value" + ;; + vrf) + vrf="$value" + ;; + *) die "unknown argument for '$arg' test_port_fw" ;; + esac + shift + done + + run_in_host_netns ip link add $ifname type dummy + run_in_host_netns ip link set $ifname mtu $mtu + run_in_host_netns ip addr add 192.168.0.0/24 dev $ifname + if [[ -n "$vrf" ]]; then + # We must add the vrf before adding the route as this call would remove the route again. + run_in_host_netns ip link set $ifname master $vrf + fi + run_in_host_netns ip link set $ifname up + run_in_host_netns ip route add default via 192.168.0.0 dev $ifname table $table } function add_bridge() { @@ -46,6 +75,20 @@ check_mtu 9000 } +# check the we only use the main table by default +# https://github.com/containers/netavark/issues/1381 +@test "bridge - mtu from default route in different tables" { + # IMPORTANT: do not add the normal default route first or last + # My kernel did not reproduce the reported issue but I was able + # to reproduce on RHEL 10. + add_default_route mtu=1000 ifname=def-table10 table=10 + add_default_route mtu=2000 ifname=def1 + add_default_route mtu=3000 ifname=def-table900 table=900 + + run_netavark --file ${TESTSDIR}/testfiles/bridge-managed.json setup $(get_container_netns_path) + check_mtu 2000 +} + @test "bridge - mtu from existing bridge" { add_bridge run_netavark --file ${TESTSDIR}/testfiles/bridge-managed.json setup $(get_container_netns_path) @@ -66,3 +109,20 @@ # The existing bridge MTU should not be overriden. check_iface_mtu host podman0 9001 } + +@test bridge - mtu from vrf default vrf interface routing table { + run_in_host_netns ip link add test-vrf type vrf table 100 + run_in_host_netns ip link set dev test-vrf up + + add_default_route mtu=9000 + add_default_route mtu=3000 ifname=eth-vrf vrf=test-vrf table=100 + + 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" ".[].master" "==" "test-vrf" "Bridge has the correct vrf set" + + check_mtu 3000 +} ++++++ netavark.obsinfo ++++++ --- /var/tmp/diff_new_pack.nNAstp/_old 2026-02-26 18:50:45.914805898 +0100 +++ /var/tmp/diff_new_pack.nNAstp/_new 2026-02-26 18:50:45.954807566 +0100 @@ -1,5 +1,5 @@ name: netavark -version: 1.17.1 -mtime: 1765200027 -commit: 7ffb8ec4c2e490a3884451e20aa8ad0471d78579 +version: 1.17.2 +mtime: 1770310642 +commit: bd7a464482bcc02dca4843c457db584ed7fe14e4 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/netavark/vendor.tar.gz /work/SRC/openSUSE:Factory/.netavark.new.29461/vendor.tar.gz differ: char 6834, line 24
