Skip to main content

ftth_rtnl/
lib.rs

1pub mod address;
2pub mod link;
3pub mod neighbor;
4pub mod route;
5pub mod virtual_interface;
6
7use std::any::Any;
8use std::sync::{Arc, Mutex, OnceLock};
9
10pub use ipnet::{IpNet, Ipv4Net, Ipv6Net};
11pub use neighbor::{NeighborDelete, NeighborEntry};
12pub use netlink_packet_route::address::AddressScope;
13pub use netlink_packet_route::neighbour::{NeighbourFlags, NeighbourState};
14pub use netlink_packet_route::route::RouteNextHopFlags;
15pub use route::{Ipv4Route, Ipv6Route, RouteNextHopInfo};
16pub use virtual_interface::{
17    Gre6Config, GreConfig, Ip6TnlConfig, IpIpConfig, VirtualInterfaceDelete, VirtualInterfaceKind,
18    VirtualInterfaceSpec, VirtualInterfaceUpdate, VlanConfig,
19};
20
21use ftth_common::channel::create_pair;
22
23use futures::{FutureExt, future::join_all};
24
25
26static CLIENT: OnceLock<RtnlClient> = OnceLock::new();
27
28#[derive(Debug, Clone)]
29pub struct RtnlClient {
30    address: address::RtnlAddressClient,
31    link: link::RtnlLinkClient,
32    neighbor: neighbor::RtnlNeighborClient,
33    route: route::RtnlRouteClient,
34    virtual_interface: virtual_interface::RtnlVirtualInterfaceClient,
35    
36    #[allow(dead_code)]
37    receiver: Arc<Mutex<Option<Box<dyn Any + Send>>>>,
38}
39
40impl RtnlClient {
41    pub fn new() -> Self {
42        CLIENT.get_or_init(|| Self::new_inner()).clone()
43    }
44
45    pub(crate) fn new_inner() -> Self {
46        let (address_tx, address_rx) = create_pair();
47        let (link_tx, link_rx) = create_pair();
48        let (neighbor_tx, neighbor_rx) = create_pair();
49        let (route_tx, route_rx) = create_pair();
50        let (virtual_interface_tx, virtual_interface_rx) = create_pair();
51
52        let receiver_container = Arc::new(Mutex::new(None));
53        let receiver_container_clone = receiver_container.clone();
54
55        std::thread::spawn(move || {
56            let rt = match tokio::runtime::Builder::new_multi_thread()
57                .enable_all()
58                .build()
59            {
60                Ok(rt) => rt,
61                Err(e) => {
62                    tracing::error!("Tokio runtime building error: {}", e);
63                    return;
64                }
65            };
66
67            let _ = rt.block_on(async {
68                let (connection, handle, receiver) = rtnetlink::new_connection()?;
69
70                {
71                    *(receiver_container_clone.lock().map_err(|_e| std::io::Error::other("Poison error"))?) = Some(Box::new(receiver) as Box<dyn Any + Send>);
72                }
73
74                tokio::spawn(connection);
75
76                let mut futures = Vec::new();
77                futures.push(address::run_server(address_rx, handle.address()).boxed());
78                futures.push(link::run_server(link_rx, handle.link()).boxed());
79                futures.push(neighbor::run_server(neighbor_rx, handle.neighbours()).boxed());
80                futures.push(route::run_server(route_rx, handle.route()).boxed());
81                futures.push(
82                    virtual_interface::run_server(virtual_interface_rx, handle.link()).boxed(),
83                );
84
85                join_all(futures).await;
86
87
88
89                Ok::<(), std::io::Error>(())
90            });
91        });
92
93        Self {
94            address: address::RtnlAddressClient::new(address_tx),
95            link: link::RtnlLinkClient::new(link_tx),
96            neighbor: neighbor::RtnlNeighborClient::new(neighbor_tx),
97            route: route::RtnlRouteClient::new(route_tx),
98            virtual_interface: virtual_interface::RtnlVirtualInterfaceClient::new(
99                virtual_interface_tx,
100            ),
101            receiver: receiver_container,
102        }
103    }
104
105    pub fn address(&self) -> address::RtnlAddressClient {
106        self.address.clone()
107    }
108
109    pub fn link(&self) -> link::RtnlLinkClient {
110        self.link.clone()
111    }
112
113    pub fn neighbor(&self) -> neighbor::RtnlNeighborClient {
114        self.neighbor.clone()
115    }
116
117    pub fn route(&self) -> route::RtnlRouteClient {
118        self.route.clone()
119    }
120
121    pub fn virtual_interface(&self) -> virtual_interface::RtnlVirtualInterfaceClient {
122        self.virtual_interface.clone()
123    }
124}