Skip to content

Commit a3d26fb

Browse files
TheRayquazaclaude
andcommitted
[datadog] runtime-rs: add netkit endpoint support
Port the Go runtime netkit endpoint to runtime-rs. Add NetkitEndpoint modeled after VethEndpoint with L3-mode detection. Handle InfoKind::Netkit and InfoData::Netkit in link_info() to avoid "unsupported link type: device" errors on netkit interfaces (kernel sends [Kind, Data] in LIFO order via pop(), Data arm must be handled before Kind fires). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ee627e3 commit a3d26fb

5 files changed

Lines changed: 155 additions & 1 deletion

File tree

src/runtime-rs/crates/resource/src/network/endpoint/endpoint_persist.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ pub struct VethEndpointState {
3333
pub network_qos: bool,
3434
}
3535

36+
#[derive(Serialize, Deserialize, Clone, Default)]
37+
pub struct NetkitEndpointState {
38+
pub if_name: String,
39+
pub network_qos: bool,
40+
}
41+
3642
#[derive(Serialize, Deserialize, Clone, Default)]
3743
pub struct IpVlanEndpointState {
3844
pub if_name: String,
@@ -54,6 +60,7 @@ pub struct VhostUserEndpointState {
5460
pub struct EndpointState {
5561
pub physical_endpoint: Option<PhysicalEndpointState>,
5662
pub veth_endpoint: Option<VethEndpointState>,
63+
pub netkit_endpoint: Option<NetkitEndpointState>,
5764
pub ipvlan_endpoint: Option<IpVlanEndpointState>,
5865
pub macvlan_endpoint: Option<MacvlanEndpointState>,
5966
pub vlan_endpoint: Option<VlanEndpointState>,

src/runtime-rs/crates/resource/src/network/endpoint/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ mod physical_endpoint;
88
pub use physical_endpoint::PhysicalEndpoint;
99
mod veth_endpoint;
1010
pub use veth_endpoint::VethEndpoint;
11+
mod netkit_endpoint;
12+
pub use netkit_endpoint::NetkitEndpoint;
1113
mod ipvlan_endpoint;
1214
pub use ipvlan_endpoint::IPVlanEndpoint;
1315
mod vlan_endpoint;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) 2019-2022 Alibaba Cloud
2+
// Copyright (c) 2019-2022 Ant Group
3+
//
4+
// SPDX-License-Identifier: Apache-2.0
5+
//
6+
7+
use std::io::{self, Error};
8+
use std::sync::Arc;
9+
10+
use anyhow::{Context, Result};
11+
use async_trait::async_trait;
12+
use hypervisor::device::device_manager::{do_handle_device, DeviceManager};
13+
use hypervisor::device::driver::NetworkConfig;
14+
use hypervisor::device::{DeviceConfig, DeviceType};
15+
use hypervisor::{Hypervisor, NetworkDevice};
16+
use tokio::sync::RwLock;
17+
18+
use super::endpoint_persist::{EndpointState, NetkitEndpointState};
19+
use super::Endpoint;
20+
use crate::network::{utils, NetworkPair};
21+
22+
#[derive(Debug)]
23+
pub struct NetkitEndpoint {
24+
pub(crate) net_pair: NetworkPair,
25+
pub(crate) d: Arc<RwLock<DeviceManager>>,
26+
}
27+
28+
impl NetkitEndpoint {
29+
pub async fn new(
30+
d: &Arc<RwLock<DeviceManager>>,
31+
handle: &rtnetlink::Handle,
32+
name: &str,
33+
idx: u32,
34+
model: &str,
35+
queues: usize,
36+
) -> Result<Self> {
37+
let net_pair = NetworkPair::new(handle, idx, name, model, queues)
38+
.await
39+
.context("new network interface pair failed.")?;
40+
41+
Ok(NetkitEndpoint {
42+
net_pair,
43+
d: d.clone(),
44+
})
45+
}
46+
47+
fn get_network_config(&self) -> Result<NetworkConfig> {
48+
let iface = &self.net_pair.tap.tap_iface;
49+
let guest_mac = utils::parse_mac(&iface.hard_addr).ok_or_else(|| {
50+
Error::new(
51+
io::ErrorKind::InvalidData,
52+
format!("hard_addr {}", &iface.hard_addr),
53+
)
54+
})?;
55+
56+
Ok(NetworkConfig {
57+
host_dev_name: iface.name.clone(),
58+
virt_iface_name: self.net_pair.virt_iface.name.clone(),
59+
guest_mac: Some(guest_mac),
60+
..Default::default()
61+
})
62+
}
63+
}
64+
65+
#[async_trait]
66+
impl Endpoint for NetkitEndpoint {
67+
async fn name(&self) -> String {
68+
self.net_pair.virt_iface.name.clone()
69+
}
70+
71+
async fn hardware_addr(&self) -> String {
72+
self.net_pair.tap.tap_iface.hard_addr.clone()
73+
}
74+
75+
async fn attach(&self) -> Result<()> {
76+
self.net_pair
77+
.add_network_model()
78+
.await
79+
.context("add network model")?;
80+
81+
let config = self.get_network_config().context("get network config")?;
82+
do_handle_device(&self.d, &DeviceConfig::NetworkCfg(config))
83+
.await
84+
.context("do handle network netkit endpoint device failed.")?;
85+
86+
Ok(())
87+
}
88+
89+
async fn detach(&self, h: &dyn Hypervisor) -> Result<()> {
90+
self.net_pair
91+
.del_network_model()
92+
.await
93+
.context("del network model failed.")?;
94+
95+
let config = self.get_network_config().context("get network config")?;
96+
h.remove_device(DeviceType::Network(NetworkDevice {
97+
config,
98+
..Default::default()
99+
}))
100+
.await
101+
.context("remove netkit endpoint device by hypervisor failed.")?;
102+
103+
Ok(())
104+
}
105+
106+
async fn save(&self) -> Option<EndpointState> {
107+
Some(EndpointState {
108+
netkit_endpoint: Some(NetkitEndpointState {
109+
if_name: self.net_pair.virt_iface.name.clone(),
110+
network_qos: self.net_pair.network_qos,
111+
}),
112+
..Default::default()
113+
})
114+
}
115+
}

src/runtime-rs/crates/resource/src/network/network_with_netns.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use tokio::sync::RwLock;
2424

2525
use super::{
2626
endpoint::{
27-
Endpoint, IPVlanEndpoint, MacVlanEndpoint, PhysicalEndpoint, VethEndpoint, VlanEndpoint,
27+
Endpoint, IPVlanEndpoint, MacVlanEndpoint, NetkitEndpoint, PhysicalEndpoint, VethEndpoint,
28+
VlanEndpoint,
2829
},
2930
network_entity::NetworkEntity,
3031
network_info::network_info_from_link::{handle_addresses, NetworkInfoFromLink},
@@ -312,6 +313,26 @@ async fn create_endpoint(
312313
.context("macvlan endpoint")?;
313314
Arc::new(ret)
314315
}
316+
"netkit" => {
317+
// L3 mode netkit devices have no MAC address and are not supported.
318+
if attrs.hardware_addr.is_empty() {
319+
return Err(anyhow!(
320+
"netkit device {} has no MAC address (L3 mode not supported - use L2 mode or veth)",
321+
attrs.name
322+
));
323+
}
324+
let ret = NetkitEndpoint::new(
325+
&d,
326+
handle,
327+
&attrs.name,
328+
idx,
329+
&config.network_model,
330+
config.queues,
331+
)
332+
.await
333+
.context("netkit endpoint")?;
334+
Arc::new(ret)
335+
}
315336
_ => return Err(anyhow!("unsupported link type: {}", link_type)),
316337
}
317338
};

src/runtime-rs/crates/resource/src/network/utils/link/manager.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ fn link_info(mut infos: Vec<LinkInfo>) -> Box<dyn Link> {
120120
link = Some(Box::new(Bridge::default()));
121121
}
122122
}
123+
InfoKind::Netkit => {
124+
if link.is_none() {
125+
link = Some(Box::new(Netkit::default()));
126+
}
127+
}
123128
_ => {
124129
if link.is_none() {
125130
link = Some(Box::new(Device::default()));
@@ -145,6 +150,9 @@ fn link_info(mut infos: Vec<LinkInfo>) -> Box<dyn Link> {
145150
InfoData::Bridge(ibs) => {
146151
link = Some(Box::new(parse_bridge(ibs)));
147152
}
153+
InfoData::Netkit(_) => {
154+
link = Some(Box::new(Netkit::default()));
155+
}
148156
_ => {
149157
link = Some(Box::new(Device::default()));
150158
}
@@ -214,6 +222,7 @@ macro_rules! define_and_impl_network_dev {
214222
define_and_impl_network_dev!("device", Device);
215223
define_and_impl_network_dev!("tuntap", Tuntap);
216224
define_and_impl_network_dev!("veth", Veth);
225+
define_and_impl_network_dev!("netkit", Netkit);
217226
define_and_impl_network_dev!("ipvlan", IpVlan);
218227
define_and_impl_network_dev!("macvlan", MacVlan);
219228
define_and_impl_network_dev!("vlan", Vlan);

0 commit comments

Comments
 (0)