From 492329fc02c82edfa7ebb31acab2ec959a36a975 Mon Sep 17 00:00:00 2001 From: Fupan Li Date: Fri, 2 May 2025 21:18:16 +0800 Subject: [PATCH] runtime: add the mtu support for updating routes Some cni plugins will set the MTU of some routes, such as cilium will modify the MTU of the default route. If the mtu of the route is not set correctly, it may cause excessive fragmentation or even packet loss of network packets. Therefore, this PR adds the setting of the MTU of the route. First, when obtaining the route, if the MTU is set, the MTU will also be obtained and set to the route in the guest. Signed-off-by: Fupan Li --- src/agent/src/netlink.rs | 21 ++++++++++++++++++- src/libs/protocols/protos/types.proto | 1 + src/runtime-rs/crates/agent/src/kata/trans.rs | 2 ++ src/runtime-rs/crates/agent/src/types.rs | 1 + .../crates/resource/src/network/dan.rs | 6 +++++- .../network_info/network_info_from_dan.rs | 3 +++ .../network_info/network_info_from_link.rs | 10 ++++++++- src/runtime/virtcontainers/network.go | 2 ++ .../pkg/agent/protocols/types.pb.go | 1 + 9 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/agent/src/netlink.rs b/src/agent/src/netlink.rs index 29119149c3..0674aeb996 100644 --- a/src/agent/src/netlink.rs +++ b/src/agent/src/netlink.rs @@ -6,10 +6,13 @@ use anyhow::{anyhow, Context, Result}; use futures::{future, StreamExt, TryStreamExt}; use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; -use netlink_packet_route::address::{AddressAttribute, AddressMessage}; use netlink_packet_route::link::{LinkAttribute, LinkMessage}; use netlink_packet_route::neighbour::{self, NeighbourFlag}; use netlink_packet_route::route::{RouteFlag, RouteHeader, RouteProtocol, RouteScope, RouteType}; +use netlink_packet_route::{ + address::{AddressAttribute, AddressMessage}, + route::RouteMetric, +}; use netlink_packet_route::{ neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourState}, route::{RouteAddress, RouteAttribute, RouteMessage}, @@ -388,6 +391,15 @@ impl Handle { .unwrap_or_default(); } + if let RouteAttribute::Metrics(metrics) = attribute { + for m in metrics { + if let RouteMetric::Mtu(mtu) = m { + route.mtu = *mtu; + break; + } + } + } + if let RouteAttribute::Oif(index) = attribute { route.device = self.find_link(LinkFilter::Index(*index)).await?.name(); } @@ -453,6 +465,13 @@ impl Handle { message.header.flags = flags; + if route.mtu != 0 { + let route_metrics = vec![RouteMetric::Mtu(route.mtu)]; + message + .attributes + .push(RouteAttribute::Metrics(route_metrics)); + } + // `rtnetlink` offers a separate request builders for different IP versions (IP v4 and v6). // This if branch is a bit clumsy because it does almost the same. if route.family() == IPFamily::v6 { diff --git a/src/libs/protocols/protos/types.proto b/src/libs/protocols/protos/types.proto index a45b15f610..db9a914e57 100644 --- a/src/libs/protocols/protos/types.proto +++ b/src/libs/protocols/protos/types.proto @@ -59,6 +59,7 @@ message Route { uint32 scope = 5; IPFamily family = 6; uint32 flags = 7; + uint32 mtu = 8; } message ARPNeighbor { diff --git a/src/runtime-rs/crates/agent/src/kata/trans.rs b/src/runtime-rs/crates/agent/src/kata/trans.rs index 08b46fca36..d76417e547 100644 --- a/src/runtime-rs/crates/agent/src/kata/trans.rs +++ b/src/runtime-rs/crates/agent/src/kata/trans.rs @@ -230,6 +230,7 @@ impl From for types::Route { scope: from.scope, family: protobuf::EnumOrUnknown::new(from.family.into()), flags: from.flags, + mtu: from.mtu, ..Default::default() } } @@ -245,6 +246,7 @@ impl From for Route { scope: src.scope, family: src.family.unwrap().into(), flags: src.flags, + mtu: src.mtu, } } } diff --git a/src/runtime-rs/crates/agent/src/types.rs b/src/runtime-rs/crates/agent/src/types.rs index 86edf1e716..e6bb71b119 100644 --- a/src/runtime-rs/crates/agent/src/types.rs +++ b/src/runtime-rs/crates/agent/src/types.rs @@ -114,6 +114,7 @@ pub struct Route { pub scope: u32, pub family: IPFamily, pub flags: u32, + pub mtu: u32, } #[derive(Deserialize, Debug, PartialEq, Clone, Default)] diff --git a/src/runtime-rs/crates/resource/src/network/dan.rs b/src/runtime-rs/crates/resource/src/network/dan.rs index 7c8025da34..5cb71b2ab4 100644 --- a/src/runtime-rs/crates/resource/src/network/dan.rs +++ b/src/runtime-rs/crates/resource/src/network/dan.rs @@ -292,6 +292,8 @@ pub(crate) struct Route { pub scope: u32, #[serde(default)] pub flags: u32, + #[serde(default)] + pub mtu: u32, } impl Route { @@ -369,7 +371,8 @@ mod tests { "source": "172.18.0.1", "gateway": "172.18.31.1", "scope": 0, - "flags": 0 + "flags": 0, + "mtu": 1450 }], "neighbors": [{ "ip_address": "192.168.0.3/16", @@ -402,6 +405,7 @@ mod tests { gateway: "172.18.31.1".to_owned(), scope: 0, flags: 0, + mtu: 1450, }], neighbors: vec![ARPNeighbor { ip_address: Some("192.168.0.3/16".to_owned()), diff --git a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs index 9d2adfed0d..368a6481b2 100644 --- a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs +++ b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_dan.rs @@ -75,6 +75,7 @@ impl NetworkInfoFromDan { scope: route.scope, family, flags: route.flags, + mtu: route.mtu, }) }) .collect(); @@ -161,6 +162,7 @@ mod tests { gateway: "172.18.31.1".to_owned(), scope: 0, flags: 0, + mtu: 1450, }], neighbors: vec![DanARPNeighbor { ip_address: Some("192.168.0.3/16".to_owned()), @@ -197,6 +199,7 @@ mod tests { scope: 0, family: IPFamily::V4, flags: 0, + mtu: 1450, }]; assert_eq!(routes, network_info.routes().await.unwrap()); diff --git a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs index f1a17cc245..59458a3464 100644 --- a/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs +++ b/src/runtime-rs/crates/resource/src/network/network_info/network_info_from_link.rs @@ -13,7 +13,7 @@ use futures::stream::TryStreamExt; use netlink_packet_route::{ self, neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourMessage}, - route::{RouteAddress, RouteAttribute, RouteMessage}, + route::{RouteAddress, RouteAttribute, RouteMessage, RouteMetric}, }; use super::NetworkInfo; @@ -201,6 +201,14 @@ fn generate_route(name: &str, route_msg: &RouteMessage) -> Result> route.source = dest.to_string(); } + RouteAttribute::Metrics(metrics) => { + for m in metrics { + if let RouteMetric::Mtu(mtu) = m { + route.mtu = *mtu; + break; + } + } + } _ => {} } } diff --git a/src/runtime/virtcontainers/network.go b/src/runtime/virtcontainers/network.go index 3dd3bbc318..0960d47d37 100644 --- a/src/runtime/virtcontainers/network.go +++ b/src/runtime/virtcontainers/network.go @@ -310,6 +310,8 @@ func generateVCNetworkStructures(ctx context.Context, endpoints []Endpoint) ([]* r.Scope = uint32(route.Scope) r.Family = utils.ConvertAddressFamily((int32)(route.Family)) r.Flags = uint32(route.Flags) + r.Mtu = uint32(route.MTU) + routes = append(routes, &r) } diff --git a/src/runtime/virtcontainers/pkg/agent/protocols/types.pb.go b/src/runtime/virtcontainers/pkg/agent/protocols/types.pb.go index 4626f982b1..db698ff4c4 100644 --- a/src/runtime/virtcontainers/pkg/agent/protocols/types.pb.go +++ b/src/runtime/virtcontainers/pkg/agent/protocols/types.pb.go @@ -308,6 +308,7 @@ type Route struct { Scope uint32 `protobuf:"varint,5,opt,name=scope,proto3" json:"scope,omitempty"` Family IPFamily `protobuf:"varint,6,opt,name=family,proto3,enum=types.IPFamily" json:"family,omitempty"` Flags uint32 `protobuf:"varint,7,opt,name=flags,proto3" json:"flags,omitempty"` + Mtu uint32 `protobuf:"varint,8,opt,name=mtu,proto3" json:"mtu,omitempty"` } func (x *Route) Reset() {