rtnetlink/link/
netkit.rs

1// SPDX-License-Identifier: MIT
2
3use crate::{
4    packet_route::link::{
5        InfoData, InfoKind, InfoNetkit, NetkitMode, NetkitPolicy, NetkitScrub,
6    },
7    LinkMessageBuilder, LinkUnspec,
8};
9
10#[derive(Debug)]
11/// Represent netkit virtual interface.
12/// Netkit devices are used for container networking and BPF programs.
13///
14/// Example code on creating a netkit pair:
15/// ```no_run
16/// use rtnetlink::{new_connection, LinkNetkit, packet_route::link::NetkitMode};
17/// #[tokio::main]
18/// async fn main() -> Result<(), String> {
19///     let (connection, handle, _) = new_connection().unwrap();
20///     tokio::spawn(connection);
21///
22///     handle
23///         .link()
24///         .add(LinkNetkit::new("netkit0", "netkit0-peer", NetkitMode::L3).build())
25///         .execute()
26///         .await
27///         .map_err(|e| format!("{e}"))
28/// }
29/// ```
30///
31/// Please check LinkMessageBuilder::<LinkNetkit> for more detail.
32pub struct LinkNetkit;
33
34impl LinkNetkit {
35    /// Equal to `LinkMessageBuilder::<LinkNetkit>::new(name, peer, mode)`
36    pub fn new(
37        name: &str,
38        peer: &str,
39        mode: NetkitMode,
40    ) -> LinkMessageBuilder<Self> {
41        LinkMessageBuilder::<LinkNetkit>::new(name, peer, mode)
42    }
43}
44
45impl LinkMessageBuilder<LinkNetkit> {
46    /// Create [LinkMessageBuilder] for netkit
47    pub fn new(name: &str, peer: &str, mode: NetkitMode) -> Self {
48        LinkMessageBuilder::<LinkNetkit>::new_with_info_kind(InfoKind::Netkit)
49            .name(name.to_string())
50            .mode(mode)
51            .peer(peer)
52    }
53
54    /// Set the peer interface name
55    pub fn peer(self, peer: &str) -> Self {
56        let peer_msg = LinkMessageBuilder::<LinkUnspec>::new()
57            .name(peer.to_string())
58            .build();
59
60        self.append_info_data(InfoNetkit::Peer(peer_msg))
61    }
62
63    /// Set the netkit mode (L2 or L3)
64    pub fn mode(self, mode: NetkitMode) -> Self {
65        self.append_info_data(InfoNetkit::Mode(mode))
66    }
67
68    /// Set the primary interface flag
69    pub fn primary(self, primary: bool) -> Self {
70        self.append_info_data(InfoNetkit::Primary(primary))
71    }
72
73    /// Set the policy for the primary interface
74    pub fn policy(self, policy: NetkitPolicy) -> Self {
75        self.append_info_data(InfoNetkit::Policy(policy))
76    }
77
78    /// Set the policy for the peer interface
79    pub fn peer_policy(self, policy: NetkitPolicy) -> Self {
80        self.append_info_data(InfoNetkit::PeerPolicy(policy))
81    }
82
83    /// Set the scrub settings for the primary interface
84    pub fn scrub(self, scrub: NetkitScrub) -> Self {
85        self.append_info_data(InfoNetkit::Scrub(scrub))
86    }
87
88    /// Set the scrub settings for the peer interface
89    pub fn peer_scrub(self, scrub: NetkitScrub) -> Self {
90        self.append_info_data(InfoNetkit::PeerScrub(scrub))
91    }
92
93    /// Set the desired headroom
94    pub fn headroom(self, headroom: u16) -> Self {
95        self.append_info_data(InfoNetkit::Headroom(headroom))
96    }
97
98    /// Set the desired tailroom
99    pub fn tailroom(self, tailroom: u16) -> Self {
100        self.append_info_data(InfoNetkit::Tailroom(tailroom))
101    }
102
103    /// Helper to append netkit-specific info data
104    fn append_info_data(mut self, info: InfoNetkit) -> Self {
105        if let InfoData::Netkit(ref mut infos) = self
106            .info_data
107            .get_or_insert_with(|| InfoData::Netkit(Vec::new()))
108        {
109            infos.push(info);
110        }
111        self
112    }
113}