mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-14 21:57:24 +08:00
Add support for IPv6 within VPN (#1061)
* add flake.nix with nix based dev shell * add support for IPv6 * update thunk --------- Co-authored-by: sijie.sun <sijie.sun@smartx.com>
This commit is contained in:
66
easytier/src/tests/ipv6_test.rs
Normal file
66
easytier/src/tests/ipv6_test.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use std::net::Ipv6Addr;
|
||||
|
||||
use crate::{
|
||||
common::config::{ConfigLoader, TomlConfigLoader},
|
||||
common::global_ctx::tests::get_mock_global_ctx,
|
||||
peers::peer_manager::RouteAlgoType,
|
||||
proto::peer_rpc::RoutePeerInfo,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_ipv6_config_support() {
|
||||
let config = TomlConfigLoader::default();
|
||||
|
||||
// Test IPv6 configuration setting and getting
|
||||
let ipv6_cidr = "fd00::1/64".parse().unwrap();
|
||||
config.set_ipv6(Some(ipv6_cidr));
|
||||
|
||||
assert_eq!(config.get_ipv6(), Some(ipv6_cidr));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_global_ctx_ipv6() {
|
||||
let global_ctx = get_mock_global_ctx();
|
||||
|
||||
// Test setting and getting IPv6 from global context
|
||||
let ipv6_cidr = "fd00::1/64".parse().unwrap();
|
||||
global_ctx.set_ipv6(Some(ipv6_cidr));
|
||||
|
||||
assert_eq!(global_ctx.get_ipv6(), Some(ipv6_cidr));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_route_peer_info_ipv6() {
|
||||
let global_ctx = get_mock_global_ctx();
|
||||
|
||||
// Set IPv6 address in global context
|
||||
let ipv6_cidr = "fd00::1/64".parse().unwrap();
|
||||
global_ctx.set_ipv6(Some(ipv6_cidr));
|
||||
|
||||
// Create RoutePeerInfo with IPv6 support
|
||||
let peer_info = RoutePeerInfo::new();
|
||||
let updated_info = peer_info.update_self(123, 456, &global_ctx);
|
||||
|
||||
// Verify IPv6 address is included
|
||||
assert!(updated_info.ipv6_addr.is_some());
|
||||
let ipv6_addr: Ipv6Addr = updated_info.ipv6_addr.unwrap().address.unwrap().into();
|
||||
assert_eq!(ipv6_addr, ipv6_cidr.address());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_peer_manager_ipv6() {
|
||||
let global_ctx = get_mock_global_ctx();
|
||||
let (packet_sender, _packet_receiver) = tokio::sync::mpsc::channel(100);
|
||||
let peer_mgr = crate::peers::peer_manager::PeerManager::new(
|
||||
RouteAlgoType::Ospf,
|
||||
global_ctx.clone(),
|
||||
packet_sender,
|
||||
);
|
||||
|
||||
// Test IPv6 address lookup for unknown address
|
||||
let ipv6_addr = Ipv6Addr::new(0xfd00, 0, 0, 0, 0, 0, 0, 2);
|
||||
let (peers, _is_self) = peer_mgr.get_msg_dst_peer_ipv6(&ipv6_addr).await;
|
||||
|
||||
// Should return empty peers list for unknown IPv6
|
||||
assert!(peers.is_empty());
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#[cfg(target_os = "linux")]
|
||||
mod three_node;
|
||||
|
||||
mod ipv6_test;
|
||||
|
||||
use crate::common::PeerId;
|
||||
use crate::peers::peer_manager::PeerManager;
|
||||
|
||||
|
||||
@@ -51,11 +51,17 @@ pub fn prepare_linux_namespaces() {
|
||||
add_ns_to_bridge("br_b", "net_d");
|
||||
}
|
||||
|
||||
pub fn get_inst_config(inst_name: &str, ns: Option<&str>, ipv4: &str) -> TomlConfigLoader {
|
||||
pub fn get_inst_config(
|
||||
inst_name: &str,
|
||||
ns: Option<&str>,
|
||||
ipv4: &str,
|
||||
ipv6: &str,
|
||||
) -> TomlConfigLoader {
|
||||
let config = TomlConfigLoader::default();
|
||||
config.set_inst_name(inst_name.to_owned());
|
||||
config.set_netns(ns.map(|s| s.to_owned()));
|
||||
config.set_ipv4(Some(ipv4.parse().unwrap()));
|
||||
config.set_ipv6(Some(ipv6.parse().unwrap()));
|
||||
config.set_listeners(vec![
|
||||
"tcp://0.0.0.0:11010".parse().unwrap(),
|
||||
"udp://0.0.0.0:11010".parse().unwrap(),
|
||||
@@ -82,16 +88,19 @@ pub async fn init_three_node_ex<F: Fn(TomlConfigLoader) -> TomlConfigLoader>(
|
||||
"inst1",
|
||||
Some("net_a"),
|
||||
"10.144.144.1",
|
||||
"fd00::1/64",
|
||||
)));
|
||||
let mut inst2 = Instance::new(cfg_cb(get_inst_config(
|
||||
"inst2",
|
||||
Some("net_b"),
|
||||
"10.144.144.2",
|
||||
"fd00::2/64",
|
||||
)));
|
||||
let mut inst3 = Instance::new(cfg_cb(get_inst_config(
|
||||
"inst3",
|
||||
Some("net_c"),
|
||||
"10.144.144.3",
|
||||
"fd00::3/64",
|
||||
)));
|
||||
|
||||
inst1.run().await.unwrap();
|
||||
@@ -232,6 +241,30 @@ async fn ping_test(from_netns: &str, target_ip: &str, payload_size: Option<usize
|
||||
code.code().unwrap() == 0
|
||||
}
|
||||
|
||||
async fn ping6_test(from_netns: &str, target_ip: &str, payload_size: Option<usize>) -> bool {
|
||||
let _g = NetNS::new(Some(ROOT_NETNS_NAME.to_owned())).guard();
|
||||
let code = tokio::process::Command::new("ip")
|
||||
.args(&[
|
||||
"netns",
|
||||
"exec",
|
||||
from_netns,
|
||||
"ping6",
|
||||
"-c",
|
||||
"1",
|
||||
"-s",
|
||||
payload_size.unwrap_or(56).to_string().as_str(),
|
||||
"-W",
|
||||
"1",
|
||||
target_ip.to_string().as_str(),
|
||||
])
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
.await
|
||||
.unwrap();
|
||||
code.code().unwrap() == 0
|
||||
}
|
||||
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
@@ -250,12 +283,26 @@ pub async fn basic_three_node_test(#[values("tcp", "udp", "wg", "ws", "wss")] pr
|
||||
insts[0].get_peer_manager().list_routes().await,
|
||||
);
|
||||
|
||||
// Test IPv4 connectivity
|
||||
wait_for_condition(
|
||||
|| async { ping_test("net_c", "10.144.144.1", None).await },
|
||||
Duration::from_secs(5000),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Test IPv6 connectivity
|
||||
wait_for_condition(
|
||||
|| async { ping6_test("net_c", "fd00::1", None).await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
|
||||
wait_for_condition(
|
||||
|| async { ping6_test("net_a", "fd00::3", None).await },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
|
||||
drop_insts(insts).await;
|
||||
}
|
||||
|
||||
@@ -562,7 +609,12 @@ pub async fn proxy_three_node_disconnect_test(#[values("tcp", "wg")] proto: &str
|
||||
};
|
||||
|
||||
let insts = init_three_node(proto).await;
|
||||
let mut inst4 = Instance::new(get_inst_config("inst4", Some("net_d"), "10.144.144.4"));
|
||||
let mut inst4 = Instance::new(get_inst_config(
|
||||
"inst4",
|
||||
Some("net_d"),
|
||||
"10.144.144.4",
|
||||
"fd00::4/64",
|
||||
));
|
||||
if proto == "tcp" {
|
||||
inst4
|
||||
.get_conn_manager()
|
||||
@@ -627,16 +679,7 @@ pub async fn proxy_three_node_disconnect_test(#[values("tcp", "wg")] proto: &str
|
||||
.iter()
|
||||
.find(|r| **r == inst4.peer_id())
|
||||
.is_none();
|
||||
if !ret {
|
||||
println!(
|
||||
"conn info: {:?}",
|
||||
insts[2]
|
||||
.get_peer_manager()
|
||||
.get_peer_map()
|
||||
.list_peer_conns(inst4.peer_id())
|
||||
.await
|
||||
);
|
||||
}
|
||||
|
||||
ret
|
||||
},
|
||||
// 0 down, assume last packet is recv in -0.01
|
||||
@@ -726,13 +769,23 @@ pub async fn udp_broadcast_test() {
|
||||
pub async fn foreign_network_forward_nic_data() {
|
||||
prepare_linux_namespaces();
|
||||
|
||||
let center_node_config = get_inst_config("inst1", Some("net_a"), "10.144.144.1");
|
||||
let center_node_config = get_inst_config("inst1", Some("net_a"), "10.144.144.1", "fd00::1/64");
|
||||
center_node_config
|
||||
.set_network_identity(NetworkIdentity::new("center".to_string(), "".to_string()));
|
||||
let mut center_inst = Instance::new(center_node_config);
|
||||
|
||||
let mut inst1 = Instance::new(get_inst_config("inst1", Some("net_b"), "10.144.145.1"));
|
||||
let mut inst2 = Instance::new(get_inst_config("inst2", Some("net_c"), "10.144.145.2"));
|
||||
let mut inst1 = Instance::new(get_inst_config(
|
||||
"inst1",
|
||||
Some("net_b"),
|
||||
"10.144.145.1",
|
||||
"fd00:1::1/64",
|
||||
));
|
||||
let mut inst2 = Instance::new(get_inst_config(
|
||||
"inst2",
|
||||
Some("net_c"),
|
||||
"10.144.145.2",
|
||||
"fd00:1::2/64",
|
||||
));
|
||||
|
||||
center_inst.run().await.unwrap();
|
||||
inst1.run().await.unwrap();
|
||||
@@ -940,21 +993,26 @@ pub async fn foreign_network_functional_cluster() {
|
||||
crate::set_global_var!(OSPF_UPDATE_MY_GLOBAL_FOREIGN_NETWORK_INTERVAL_SEC, 1);
|
||||
prepare_linux_namespaces();
|
||||
|
||||
let center_node_config1 = get_inst_config("inst1", Some("net_a"), "10.144.144.1");
|
||||
let center_node_config1 = get_inst_config("inst1", Some("net_a"), "10.144.144.1", "fd00::1/64");
|
||||
center_node_config1
|
||||
.set_network_identity(NetworkIdentity::new("center".to_string(), "".to_string()));
|
||||
let mut center_inst1 = Instance::new(center_node_config1);
|
||||
|
||||
let center_node_config2 = get_inst_config("inst2", Some("net_b"), "10.144.144.2");
|
||||
let center_node_config2 = get_inst_config("inst2", Some("net_b"), "10.144.144.2", "fd00::2/64");
|
||||
center_node_config2
|
||||
.set_network_identity(NetworkIdentity::new("center".to_string(), "".to_string()));
|
||||
let mut center_inst2 = Instance::new(center_node_config2);
|
||||
|
||||
let inst1_config = get_inst_config("inst1", Some("net_c"), "10.144.145.1");
|
||||
let inst1_config = get_inst_config("inst1", Some("net_c"), "10.144.145.1", "fd00:2::1/64");
|
||||
inst1_config.set_listeners(vec![]);
|
||||
let mut inst1 = Instance::new(inst1_config);
|
||||
|
||||
let mut inst2 = Instance::new(get_inst_config("inst2", Some("net_d"), "10.144.145.2"));
|
||||
let mut inst2 = Instance::new(get_inst_config(
|
||||
"inst2",
|
||||
Some("net_d"),
|
||||
"10.144.145.2",
|
||||
"fd00:2::2/64",
|
||||
));
|
||||
|
||||
center_inst1.run().await.unwrap();
|
||||
center_inst2.run().await.unwrap();
|
||||
@@ -1011,18 +1069,23 @@ pub async fn foreign_network_functional_cluster() {
|
||||
pub async fn manual_reconnector(#[values(true, false)] is_foreign: bool) {
|
||||
prepare_linux_namespaces();
|
||||
|
||||
let center_node_config = get_inst_config("inst1", Some("net_a"), "10.144.144.1");
|
||||
let center_node_config = get_inst_config("inst1", Some("net_a"), "10.144.144.1", "fd00::1/64");
|
||||
if is_foreign {
|
||||
center_node_config
|
||||
.set_network_identity(NetworkIdentity::new("center".to_string(), "".to_string()));
|
||||
}
|
||||
let mut center_inst = Instance::new(center_node_config);
|
||||
|
||||
let inst1_config = get_inst_config("inst1", Some("net_b"), "10.144.145.1");
|
||||
let inst1_config = get_inst_config("inst1", Some("net_b"), "10.144.145.1", "fd00:1::1/64");
|
||||
inst1_config.set_listeners(vec![]);
|
||||
let mut inst1 = Instance::new(inst1_config);
|
||||
|
||||
let mut inst2 = Instance::new(get_inst_config("inst2", Some("net_c"), "10.144.145.2"));
|
||||
let mut inst2 = Instance::new(get_inst_config(
|
||||
"inst2",
|
||||
Some("net_c"),
|
||||
"10.144.145.2",
|
||||
"fd00:1::2/64",
|
||||
));
|
||||
|
||||
center_inst.run().await.unwrap();
|
||||
inst1.run().await.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user