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}