Skip to content

Commit 9813c4f

Browse files
committed
fix error when deleting interface under netns
1 parent 4c15db4 commit 9813c4f

5 files changed

Lines changed: 132 additions & 91 deletions

File tree

aronet/src/command/daemon.rs

Lines changed: 81 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use crate::utils::netlink::Netlink;
55
use clap::{Args, ValueEnum};
66
use futures::join;
77
use log::{info, warn};
8+
use std::cell::{RefCell, RefMut};
89
use std::io::ErrorKind;
910
use std::net::IpAddr;
11+
use std::rc::Rc;
1012
use std::str::FromStr;
1113
use tokio::signal::unix::{SignalKind, signal};
1214
use tokio_util::sync::CancellationToken;
@@ -24,15 +26,28 @@ enum Actions {
2426
}
2527

2628
struct DaemonState<'a> {
27-
strongswan: Strongswan<'a>,
28-
bird: Bird<'a>,
29-
netlink: Netlink,
3029
cancel_token: CancellationToken,
3130
config: &'a Config,
31+
netlink: Rc<RefCell<Netlink>>,
3232
registries: &'a Registries,
33+
strongswan: Strongswan<'a>,
34+
bird: Bird<'a>,
3335
}
3436

3537
impl<'a> DaemonState<'a> {
38+
async fn new(config: &'a Config, registries: &'a Registries, token: CancellationToken) -> Self {
39+
let nl = Rc::new(RefCell::new(Netlink::new().await));
40+
41+
Self {
42+
config,
43+
registries,
44+
strongswan: Strongswan::new(config, registries, token.clone(), Rc::clone(&nl)),
45+
bird: Bird::new(config, token.clone()),
46+
cancel_token: token,
47+
netlink: nl,
48+
}
49+
}
50+
3651
async fn handle_signals(&self) {
3752
let mut sig_int = signal(SignalKind::interrupt()).unwrap();
3853
let mut sig_term = signal(SignalKind::terminate()).unwrap();
@@ -48,18 +63,21 @@ impl<'a> DaemonState<'a> {
4863
self.cancel_token.cancel();
4964
}
5065

51-
async fn clean_resources(&self) {
66+
async fn clean_resources(&mut self) {
67+
let netlink = Rc::clone(&self.netlink);
68+
let mut nl = netlink.borrow_mut();
69+
5270
info!("cleanup netlink resources of daemon...");
5371
if self.config.daemon.mode == DaemonMode::Netns {
5472
info!("trying to delete netns");
55-
if let Err(err) = self.netlink.delete_netns(&self.config.netns_name()).await {
73+
if let Err(err) = nl.delete_netns(&self.config.netns_name()).await {
5674
if !err.is_netlink_not_found() {
5775
warn!("failed to delete netns: {err}");
5876
}
5977
}
6078
} else {
6179
info!("trying to delete main interface");
62-
if let Err(err) = self.netlink.delete_link(self.config.ifname()).await {
80+
if let Err(err) = nl.delete_link(self.config.ifname(), None).await {
6381
if !err.is_netlink_not_found() {
6482
warn!("failed to delete main interface: {err}");
6583
}
@@ -70,8 +88,8 @@ impl<'a> DaemonState<'a> {
7088
pub async fn start(&mut self) {
7189
// clean previous netlink resources before start
7290
self.clean_resources().await;
73-
7491
self.setup().await;
92+
7593
join!(
7694
self.strongswan.runner(),
7795
self.bird.runner(),
@@ -83,6 +101,9 @@ impl<'a> DaemonState<'a> {
83101
}
84102

85103
pub async fn setup(&mut self) {
104+
let netlink = Rc::clone(&self.netlink);
105+
let mut nl = netlink.borrow_mut();
106+
86107
// swanctl is under runtime_dir, so this also creates runtime_dir
87108
tokio::fs::create_dir_all(self.config.swanctl_conf_dir().as_path())
88109
.await
@@ -106,57 +127,53 @@ impl<'a> DaemonState<'a> {
106127
match self.config.daemon.mode {
107128
// in netns mode, the main interface is a veth pair
108129
crate::utils::configuration::DaemonMode::Netns => {
109-
self.netlink
110-
.create_netns(&self.config.netns_name())
130+
info!("creating netns {}", self.config.netns_name());
131+
nl.create_netns(&self.config.netns_name())
111132
.await
112133
.expect("failed to create netns");
113134

114-
self.netlink
115-
.create_veth(
116-
self.config.ifname(),
117-
self.config.ifname(),
118-
Some(&self.config.netns_name()),
119-
Some(&if_ips),
120-
Some(&vec![self.config.peer_network()]),
121-
)
122-
.await
123-
.map_err(|e| format!("{e}"))
124-
.expect("cannot create veth");
135+
nl.create_veth(
136+
self.config.ifname(),
137+
self.config.ifname(),
138+
Some(&self.config.netns_name()),
139+
Some(&if_ips),
140+
Some(&vec![self.config.peer_network()]),
141+
)
142+
.await
143+
.map_err(|e| format!("{e}"))
144+
.expect("cannot create veth");
125145

126146
// direct traffic out of netns
127-
self.netlink
128-
.create_route(
129-
IpNetwork::from_str("::/0").unwrap(),
130-
self.config.ifname(),
131-
None,
132-
None,
133-
None,
134-
None,
135-
None,
136-
Some(&self.config.netns_name()),
137-
)
138-
.await
139-
.map_err(|e| format!("{e}"))
140-
.expect("creating default route for ipv6 in netns failed");
141-
142-
self.netlink
143-
.create_route(
144-
IpNetwork::from_str("0.0.0.0/0").unwrap(),
145-
self.config.ifname(),
146-
Some(self.config.main_network().ip),
147-
None,
148-
None,
149-
None,
150-
None,
151-
Some(&self.config.netns_name()),
152-
)
153-
.await
154-
.expect("creating default route for ipv4 in netns failed");
147+
nl.create_route(
148+
IpNetwork::from_str("::/0").unwrap(),
149+
self.config.ifname(),
150+
None,
151+
None,
152+
None,
153+
None,
154+
None,
155+
Some(&self.config.netns_name()),
156+
)
157+
.await
158+
.map_err(|e| format!("{e}"))
159+
.expect("creating default route for ipv6 in netns failed");
160+
161+
nl.create_route(
162+
IpNetwork::from_str("0.0.0.0/0").unwrap(),
163+
self.config.ifname(),
164+
Some(self.config.main_network().ip),
165+
None,
166+
None,
167+
None,
168+
None,
169+
Some(&self.config.netns_name()),
170+
)
171+
.await
172+
.expect("creating default route for ipv4 in netns failed");
155173
}
156174
crate::utils::configuration::DaemonMode::Vrf => {
157175
// in vrf mode, the main interface is a vrf device
158-
self.netlink
159-
.create_vrf(self.config.ifname(), self.config.route_table(), if_ips)
176+
nl.create_vrf(self.config.ifname(), self.config.route_table(), if_ips)
160177
.await
161178
.map_err(|e| format!("failed to create vrf {}: {e}", self.config.ifname()))
162179
.unwrap();
@@ -180,20 +197,19 @@ impl<'a> DaemonState<'a> {
180197
let mut networks = node.remarks.extra_network.clone();
181198
networks.push(node.remarks.network);
182199
for net in networks {
183-
self.netlink
184-
.create_route(
185-
net,
186-
self.config.ifname(),
187-
gateway,
188-
None,
189-
None,
190-
None,
191-
None,
192-
None,
193-
)
194-
.await
195-
.map_err(|e| format!("{e}"))
196-
.expect("creating route failed");
200+
nl.create_route(
201+
net,
202+
self.config.ifname(),
203+
gateway,
204+
None,
205+
None,
206+
None,
207+
None,
208+
None,
209+
)
210+
.await
211+
.map_err(|e| format!("{e}"))
212+
.expect("creating route failed");
197213
}
198214
}
199215
}
@@ -202,17 +218,9 @@ impl<'a> DaemonState<'a> {
202218

203219
#[tokio::main(flavor = "current_thread")]
204220
async fn _run(args: &DaemonArgs, config: &Config, registries: &Registries) {
205-
let nl = Netlink::new().await;
206221
let token = CancellationToken::new();
207222

208-
let mut state = DaemonState {
209-
strongswan: Strongswan::new(config, registries, token.clone()),
210-
bird: Bird::new(config, token.clone()),
211-
netlink: nl,
212-
cancel_token: token,
213-
config,
214-
registries,
215-
};
223+
let mut state = DaemonState::new(config, registries, token).await;
216224

217225
match args.action {
218226
Actions::Run => {

aronet/src/daemon/strongswan.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use std::cell::RefCell;
12
use std::fs;
3+
use std::rc::Rc;
24
use std::{path::PathBuf, process::Stdio};
35

46
use base64::Engine;
@@ -67,11 +69,17 @@ pub struct Strongswan<'a> {
6769
ifname: &'a str,
6870
daemon_mode: DaemonMode,
6971
netns: String,
72+
netlink: Rc<RefCell<Netlink>>,
7073
cancel_token: CancellationToken,
7174
}
7275

7376
impl<'a> Strongswan<'a> {
74-
pub fn new(config: &'a Config, registries: &'a Registries, token: CancellationToken) -> Self
77+
pub fn new(
78+
config: &'a Config,
79+
registries: &'a Registries,
80+
token: CancellationToken,
81+
netlink: Rc<RefCell<Netlink>>,
82+
) -> Self
7583
where
7684
Self: Sized,
7785
{
@@ -90,6 +98,7 @@ impl<'a> Strongswan<'a> {
9098
daemon_mode: config.daemon.mode,
9199
netns: config.netns_name(),
92100
cancel_token: token,
101+
netlink,
93102
}
94103
}
95104

@@ -155,9 +164,11 @@ impl<'a> Strongswan<'a> {
155164
vici
156165
}
157166

158-
pub async fn handle_updown_event(&self, event: &Updown, nl: &Netlink) {
167+
pub async fn handle_updown_event(&self, event: &Updown, nl_ref: &RefCell<Netlink>) {
159168
debug!("ike-updown: {:?}", event);
160169

170+
let nl = nl_ref.borrow();
171+
161172
for entry in &event.ike_sas {
162173
let sa = entry.1;
163174
let xfrm_name = format!("{}-{}", self.ifname, sa.if_id_in);
@@ -168,7 +179,6 @@ impl<'a> Strongswan<'a> {
168179
DaemonMode::Netns => {
169180
// must create xfrm in the netns which charon running, then move this
170181
// interface to another netns
171-
172182
let if_id = u32::from_str_radix(&sa.if_id_in, 16);
173183
if if_id.is_err() {
174184
warn!(
@@ -204,7 +214,12 @@ impl<'a> Strongswan<'a> {
204214
warn!("failed to create link {xfrm_name}: {e}");
205215
}
206216
} else {
207-
let r = nl.delete_link(&xfrm_name).await;
217+
let ns = if self.daemon_mode == DaemonMode::Netns {
218+
Some(self.netns.as_str())
219+
} else {
220+
None
221+
};
222+
let r = nl.delete_link(&xfrm_name, ns).await;
208223
if let Err(e) = r {
209224
warn!("failed to delete link {xfrm_name}: {e}");
210225
}
@@ -219,12 +234,13 @@ impl<'a> Strongswan<'a> {
219234

220235
let mut stream = Box::pin(vici.subscribe::<Updown>("ike-updown"));
221236

222-
let nl = Netlink::new().await;
237+
let netlink = Rc::clone(&self.netlink);
238+
if self.daemon_mode == DaemonMode::Netns {}
223239
loop {
224240
tokio::select! {
225241
v = stream.try_next() => {
226242
if let Some(event) = v.unwrap() {
227-
self.handle_updown_event(&event, &nl).await;
243+
self.handle_updown_event(&event, &netlink).await;
228244
}
229245
}
230246
_ = cancel_token.cancelled() => {

0 commit comments

Comments
 (0)