1
0
mirror of https://github.com/containers/netavark.git synced 2026-02-05 15:45:47 +01:00
Files
netavark/examples/host-device-plugin.rs
Shivang K Raghuvanshi b83903b0ea refactor(netlink): Generalize socket for multi-protocol support
The existing `netlink.rs` was specific to `NETLINK_ROUTE`. To prepare for adding `NETLINK_NETFILTER` support for conntrack, this commit refactors the netlink socket implementation to be generic.

- A new generic `Socket<P>` is introduced in `src/network/netlink.rs` to handle common send/receive logic.
- All routing-specific code, types, and functions are moved to a new `src/network/netlink_route.rs`, which now uses `Socket<NetlinkRoute>`.
- All imports and type signatures across the codebase have been updated to use this new structure.

This is a pure refactoring with no functional changes.

Signed-off-by: Shivang K Raghuvanshi <shivangraghuvanshi2005@gmail.com>
2025-11-09 13:04:32 +05:30

112 lines
3.2 KiB
Rust

//! This is just an example plugin, do not use it in production!
use std::{collections::HashMap, os::fd::AsFd};
use netavark::{
network::{
core_utils::{open_netlink_sockets, CoreUtils},
netlink_route, types,
},
new_error,
plugin::{Info, Plugin, PluginExec, API_VERSION},
};
use netlink_packet_route::{address::AddressAttribute, link::LinkAttribute};
fn main() {
let info = Info::new("0.1.0-dev".to_owned(), API_VERSION.to_owned(), None);
PluginExec::new(Exec {}, info).exec();
}
struct Exec {}
impl Plugin for Exec {
fn create(
&self,
network: types::Network,
) -> Result<types::Network, Box<dyn std::error::Error>> {
if network.network_interface.as_deref().unwrap_or_default() == "" {
return Err(new_error!("no network interface is specified"));
}
Ok(network)
}
fn setup(
&self,
netns: String,
opts: types::NetworkPluginExec,
) -> Result<types::StatusBlock, Box<dyn std::error::Error>> {
let (mut host, netns) = open_netlink_sockets(&netns)?;
let name = opts.network.network_interface.unwrap_or_default();
let link = host
.netlink
.get_link(netlink_route::LinkID::Name(name.clone()))?;
let mut mac_address = String::from("");
for nla in link.attributes {
if let LinkAttribute::Address(ref addr) = nla {
mac_address = CoreUtils::encode_address_to_hex(addr);
}
}
let addresses = host.netlink.dump_addresses(None)?;
let mut subnets = Vec::new();
for address in addresses {
if address.header.index == link.header.index {
for nla in address.attributes {
if let AddressAttribute::Address(ip) = &nla {
let net = ipnet::IpNet::new(*ip, address.header.prefix_len)?;
subnets.push(types::NetAddress {
gateway: None,
ipnet: net,
})
}
}
}
}
host.netlink
.set_link_ns(link.header.index, netns.file.as_fd())?;
// interfaces map, but we only ever expect one, for response
let mut interfaces: HashMap<String, types::NetInterface> = HashMap::new();
let interface = types::NetInterface {
mac_address,
subnets: Option::from(subnets),
};
interfaces.insert(name, interface);
// StatusBlock response
let response = types::StatusBlock {
dns_server_ips: None,
dns_search_domains: None,
interfaces: Some(interfaces),
};
Ok(response)
}
fn teardown(
&self,
netns: String,
opts: types::NetworkPluginExec,
) -> Result<(), Box<dyn std::error::Error>> {
// on teardown revert what was done in setup
let (host, mut netns) = open_netlink_sockets(&netns)?;
let name = opts.network.network_interface.unwrap_or_default();
let link = netns.netlink.get_link(netlink_route::LinkID::Name(name))?;
netns
.netlink
.set_link_ns(link.header.index, host.file.as_fd())?;
Ok(())
}
}