From 77749e3aecc22d14803c021d8dee967101355c3e Mon Sep 17 00:00:00 2001 From: Adam Leventhal Date: Tue, 25 Jun 2024 09:17:18 -0700 Subject: [PATCH] migrate net/prefix types to oxnet (#266) In addition, this cleans up some of the features to ensure that illumos-only dependencies aren't pulled in when they aren't needed. --- Cargo.lock | 5 ++ Cargo.toml | 1 + ddm-admin-client/Cargo.toml | 7 +- ddm-admin-client/build.rs | 3 - ddm-admin-client/src/lib.rs | 63 +--------------- ddm/Cargo.toml | 1 + ddm/src/admin.rs | 9 ++- ddm/src/db.rs | 66 ++++++---------- ddm/src/discovery.rs | 10 +-- ddm/src/exchange.rs | 13 ++-- ddm/src/sm.rs | 7 +- ddm/src/sys.rs | 38 +++++----- ddmadm/Cargo.toml | 15 ++-- ddmadm/src/main.rs | 80 +++----------------- mg-admin-client/build.rs | 3 - mg-common/Cargo.toml | 11 ++- mg-common/src/net.rs | 146 +----------------------------------- mg-lower/Cargo.toml | 1 + mg-lower/src/ddm.rs | 25 +++--- mgadm/src/static_routing.rs | 14 ++-- mgd/Cargo.toml | 3 +- mgd/src/main.rs | 2 +- openapi/ddm-admin.json | 105 +++++++++++--------------- tests/src/ddm.rs | 102 +++++++------------------ 24 files changed, 200 insertions(+), 530 deletions(-) delete mode 100644 ddm-admin-client/build.rs delete mode 100644 mg-admin-client/build.rs diff --git a/Cargo.lock b/Cargo.lock index 279ffe07..5c5341d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -733,6 +733,7 @@ dependencies = [ "oxide-vpc", "oximeter", "oximeter-producer", + "oxnet 0.1.0 (git+https://github.com/oxidecomputer/oxnet)", "pretty_assertions", "schemars", "serde", @@ -750,6 +751,7 @@ dependencies = [ name = "ddm-admin-client" version = "0.1.0" dependencies = [ + "oxnet 0.1.0 (git+https://github.com/oxidecomputer/oxnet)", "percent-encoding", "progenitor", "reqwest", @@ -770,6 +772,7 @@ dependencies = [ "ddm", "ddm-admin-client", "mg-common", + "oxnet 0.1.0 (git+https://github.com/oxidecomputer/oxnet)", "slog", "slog-async", "slog-envlogger", @@ -2110,6 +2113,7 @@ dependencies = [ "omicron-common", "oximeter", "oximeter-producer", + "oxnet 0.1.0 (git+https://github.com/oxidecomputer/oxnet)", "schemars", "serde", "slog", @@ -2141,6 +2145,7 @@ dependencies = [ "http 0.2.12", "libnet 0.1.0 (git+https://github.com/oxidecomputer/netadm-sys?branch=main)", "mg-common", + "oxnet 0.1.0 (git+https://github.com/oxidecomputer/oxnet)", "rdb", "slog", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 43a2d1e7..1b24435c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ mg-common = { path = "mg-common" } chrono = { version = "0.4.38", features = ["serde"] } oximeter = { git = "https://github.com/oxidecomputer/omicron", branch = "main"} oximeter-producer = { git = "https://github.com/oxidecomputer/omicron", branch = "main"} +oxnet = { git = "https://github.com/oxidecomputer/oxnet" } omicron-common = { git = "https://github.com/oxidecomputer/omicron", branch = "main"} internal-dns = { git = "https://github.com/oxidecomputer/omicron", branch = "main"} uuid = { version = "1.8", features = ["serde", "v4"] } diff --git a/ddm-admin-client/Cargo.toml b/ddm-admin-client/Cargo.toml index 264386b3..cd422eaa 100644 --- a/ddm-admin-client/Cargo.toml +++ b/ddm-admin-client/Cargo.toml @@ -4,10 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +oxnet.workspace = true +percent-encoding.workspace = true +progenitor.workspace = true +reqwest.workspace = true serde.workspace = true serde_json.workspace = true slog.workspace = true -percent-encoding.workspace = true -reqwest.workspace = true -progenitor.workspace = true uuid.workspace = true diff --git a/ddm-admin-client/build.rs b/ddm-admin-client/build.rs deleted file mode 100644 index 08898a76..00000000 --- a/ddm-admin-client/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=../openapi/ddm-admin.json"); -} diff --git a/ddm-admin-client/src/lib.rs b/ddm-admin-client/src/lib.rs index 38ee46fe..7676826c 100644 --- a/ddm-admin-client/src/lib.rs +++ b/ddm-admin-client/src/lib.rs @@ -12,71 +12,14 @@ progenitor::generate_api!( "body" => ?&request.body(), ); }), + crates = { + "oxnet" = "0.1.0", + }, post_hook = (|log: &slog::Logger, result: &Result<_, _>| { slog::trace!(log, "client response"; "result" => ?result); }) ); -impl Copy for types::Ipv4Prefix {} -impl Copy for types::Ipv6Prefix {} -impl Copy for types::IpPrefix {} - -impl std::cmp::PartialEq for types::Ipv4Prefix { - fn eq(&self, other: &Self) -> bool { - self.addr.eq(&other.addr) && self.len.eq(&other.len) - } -} - -impl std::cmp::Eq for types::Ipv4Prefix {} - -impl std::hash::Hash for types::Ipv4Prefix { - fn hash(&self, state: &mut H) { - self.addr.hash(state); - self.len.hash(state); - } -} - -impl std::cmp::PartialEq for types::Ipv6Prefix { - fn eq(&self, other: &Self) -> bool { - self.addr.eq(&other.addr) && self.len.eq(&other.len) - } -} - -impl std::cmp::Eq for types::Ipv6Prefix {} - -impl std::hash::Hash for types::Ipv6Prefix { - fn hash(&self, state: &mut H) { - self.addr.hash(state); - self.len.hash(state); - } -} - -impl std::cmp::PartialEq for types::IpPrefix { - fn eq(&self, other: &Self) -> bool { - match self { - types::IpPrefix::V4(x) => match other { - types::IpPrefix::V4(y) => x.eq(y), - _ => false, - }, - types::IpPrefix::V6(x) => match other { - types::IpPrefix::V6(y) => x.eq(y), - _ => false, - }, - } - } -} - -impl std::hash::Hash for types::IpPrefix { - fn hash(&self, state: &mut H) { - match self { - types::IpPrefix::V4(x) => x.hash(state), - types::IpPrefix::V6(x) => x.hash(state), - } - } -} - -impl std::cmp::Eq for types::IpPrefix {} - impl std::cmp::PartialEq for types::TunnelOrigin { fn eq(&self, other: &Self) -> bool { self.overlay_prefix.eq(&other.overlay_prefix) diff --git a/ddm/Cargo.toml b/ddm/Cargo.toml index e65af040..0a57ea77 100644 --- a/ddm/Cargo.toml +++ b/ddm/Cargo.toml @@ -31,4 +31,5 @@ chrono.workspace = true omicron-common.workspace = true oximeter.workspace = true oximeter-producer.workspace = true +oxnet.workspace = true uuid.workspace = true diff --git a/ddm/src/admin.rs b/ddm/src/admin.rs index 4825fff6..2722d5bf 100644 --- a/ddm/src/admin.rs +++ b/ddm/src/admin.rs @@ -17,7 +17,8 @@ use dropshot::HttpServerStarter; use dropshot::Path; use dropshot::RequestContext; use dropshot::TypedBody; -use mg_common::net::{Ipv6Prefix, TunnelOrigin}; +use mg_common::net::TunnelOrigin; +use oxnet::Ipv6Net; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use slog::{error, info, warn, Logger}; @@ -125,7 +126,7 @@ type PrefixMap = BTreeMap>; #[endpoint { method = GET, path = "/originated" }] async fn get_originated( ctx: RequestContext>>, -) -> Result>, HttpError> { +) -> Result>, HttpError> { let ctx = ctx.context().lock().unwrap(); let originated = ctx .db @@ -186,7 +187,7 @@ async fn get_tunnel_endpoints( #[endpoint { method = PUT, path = "/prefix" }] async fn advertise_prefixes( ctx: RequestContext>>, - request: TypedBody>, + request: TypedBody>, ) -> Result { let ctx = ctx.context().lock().unwrap(); let prefixes = request.into_inner(); @@ -258,7 +259,7 @@ async fn advertise_tunnel_endpoints( #[endpoint { method = DELETE, path = "/prefix" }] async fn withdraw_prefixes( ctx: RequestContext>>, - request: TypedBody>, + request: TypedBody>, ) -> Result { let ctx = ctx.context().lock().unwrap(); let prefixes = request.into_inner(); diff --git a/ddm/src/db.rs b/ddm/src/db.rs index f3edc674..b788ddad 100644 --- a/ddm/src/db.rs +++ b/ddm/src/db.rs @@ -2,7 +2,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use mg_common::net::{IpPrefix, Ipv6Prefix, TunnelOrigin}; +use mg_common::net::TunnelOrigin; +use oxnet::{IpNet, Ipv6Net}; use schemars::{JsonSchema, JsonSchema_repr}; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -105,10 +106,7 @@ impl Db { } } - pub fn originate( - &self, - prefixes: &HashSet, - ) -> Result<(), Error> { + pub fn originate(&self, prefixes: &HashSet) -> Result<(), Error> { let tree = self.persistent_data.open_tree(ORIGINATE)?; for p in prefixes { tree.insert(p.db_key(), "")?; @@ -130,7 +128,7 @@ impl Db { Ok(()) } - pub fn originated(&self) -> Result, Error> { + pub fn originated(&self) -> Result, Error> { let tree = self.persistent_data.open_tree(ORIGINATE)?; let result = tree .scan_prefix(vec![]) @@ -145,7 +143,7 @@ impl Db { return None; } }; - Some(match Ipv6Prefix::from_db_key(&key) { + Some(match Ipv6Net::from_db_key(&key) { Ok(item) => item, Err(e) => { error!( @@ -200,10 +198,7 @@ impl Db { Ok(self.originated_tunnel()?.len()) } - pub fn withdraw( - &self, - prefixes: &HashSet, - ) -> Result<(), Error> { + pub fn withdraw(&self, prefixes: &HashSet) -> Result<(), Error> { let tree = self.persistent_data.open_tree(ORIGINATE)?; for p in prefixes { tree.remove(p.db_key())?; @@ -269,7 +264,7 @@ impl Db { pub fn routes_by_vector( &self, - dst: Ipv6Prefix, + dst: Ipv6Net, nexthop: Ipv6Addr, ) -> Vec { let data = self.data.lock().unwrap(); @@ -356,7 +351,7 @@ pub struct TunnelRoute { Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, )] pub struct Route { - pub destination: Ipv6Prefix, + pub destination: Ipv6Net, pub nexthop: Ipv6Addr, pub ifname: String, pub path: Vec, @@ -390,7 +385,7 @@ impl EffectiveTunnelRouteSet { pub fn effective_route_set( full: &HashSet, ) -> HashSet { - let mut sets = HashMap::::new(); + let mut sets = HashMap::::new(); for x in full.iter() { match sets.get_mut(&x.origin.overlay_prefix) { Some(set) => { @@ -458,24 +453,25 @@ trait DbKey: Sized { fn from_db_key(v: &[u8]) -> Result; } -impl DbKey for Ipv6Prefix { +impl DbKey for Ipv6Net { fn db_key(&self) -> Vec { - let mut buf: Vec = self.addr.octets().into(); - buf.push(self.len); + let mut buf: Vec = self.addr().octets().into(); + buf.push(self.width()); buf } fn from_db_key(v: &[u8]) -> Result { if v.len() < 17 { Err(Error::DbKey(format!( - "buffer to short for prefix 6 key {} < 17", + "buffer too short for prefix 6 key {} < 17", v.len() ))) } else { - Ok(Self { - addr: Ipv6Addr::from(<[u8; 16]>::try_from(&v[..16]).unwrap()), - len: v[16], - }) + Self::new( + Ipv6Addr::from(<[u8; 16]>::try_from(&v[..16]).unwrap()), + v[16], + ) + .map_err(|e| Error::DbKey(e.to_string())) } } } @@ -494,7 +490,6 @@ impl From for TunnelOrigin { #[cfg(test)] mod test { use super::*; - use mg_common::net::{IpPrefix, Ipv4Prefix}; use pretty_assertions::assert_eq; use std::collections::HashSet; @@ -503,10 +498,7 @@ mod test { let mut before = HashSet::::new(); before.insert(TunnelRoute { origin: TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "0.0.0.0".parse().unwrap(), - len: 0, - }), + overlay_prefix: "0.0.0.0/0".parse().unwrap(), boundary_addr: "fd00:a::1".parse().unwrap(), vni: 99, metric: 0, @@ -515,10 +507,7 @@ mod test { }); before.insert(TunnelRoute { origin: TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "0.0.0.0".parse().unwrap(), - len: 0, - }), + overlay_prefix: "0.0.0.0/0".parse().unwrap(), boundary_addr: "fd00:b::1".parse().unwrap(), vni: 99, metric: 0, @@ -530,10 +519,7 @@ mod test { let mut after = HashSet::::new(); after.insert(TunnelRoute { origin: TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "0.0.0.0".parse().unwrap(), - len: 0, - }), + overlay_prefix: "0.0.0.0/0".parse().unwrap(), boundary_addr: "fd00:a::1".parse().unwrap(), vni: 99, metric: 0, @@ -542,10 +528,7 @@ mod test { }); after.insert(TunnelRoute { origin: TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "0.0.0.0".parse().unwrap(), - len: 0, - }), + overlay_prefix: "0.0.0.0/0".parse().unwrap(), boundary_addr: "fd00:b::1".parse().unwrap(), vni: 99, metric: 100, @@ -570,10 +553,7 @@ mod test { let mut expected_del = HashSet::::new(); expected_del.insert(TunnelRoute { origin: TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "0.0.0.0".parse().unwrap(), - len: 0, - }), + overlay_prefix: "0.0.0.0/0".parse().unwrap(), boundary_addr: "fd00:a::1".parse().unwrap(), vni: 99, metric: 0, diff --git a/ddm/src/discovery.rs b/ddm/src/discovery.rs index f4d00c81..d3a6818e 100644 --- a/ddm/src/discovery.rs +++ b/ddm/src/discovery.rs @@ -2,7 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -//! This file implements the ddm router discovery mechanisms. These mechanisims +//! This file implements the ddm router discovery mechanisms. These mechanisms //! are responsible for three primary things //! //! 1. Soliciting other routers through UDP/IPv6 link local multicast. @@ -49,11 +49,11 @@ //! That solicitation is received by piano and piano respons with an //! advertisement to violin's link-local unicast address. From this point //! forward solicitations and responses continue. Each time violin gets a -//! response from piano, it updates the last seeen timestamp for piano. If at +//! response from piano, it updates the last seen timestamp for piano. If at //! some point piano stops responding to solicitations and the last seen //! timestamp is older than the expiration threshold, violin will expire the //! session and send out a notification to the ddm state machine that started -//! it. Violin will continue to send out solicitaions in case piano comes back. +//! it. Violin will continue to send out solicitations in case piano comes back. //! //! In the event that piano undergoes renumbering e.g. it's link-local unicast //! address changes, this will be detected by violin and an advertisement update @@ -78,9 +78,9 @@ //! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //! //! The first byte indicates the version. The only valid version at present is -//! version 1. The second byte is a flags bifield. The first position `S` +//! version 1. The second byte is a flags bitfield. The first position `S` //! indicates a solicitation. The second position `A` indicates and -//! advertisement. All other positions are reserved for future use. The thrid +//! advertisement. All other positions are reserved for future use. The third //! byte indicates the kind of router. Current values are 0 for a server router //! and 1 for a transit routers. The fourth byte is a hostname length followed //! directly by a hostname of up to 255 bytes in length. diff --git a/ddm/src/exchange.rs b/ddm/src/exchange.rs index 986262ec..2d1a52cc 100644 --- a/ddm/src/exchange.rs +++ b/ddm/src/exchange.rs @@ -31,7 +31,8 @@ use dropshot::HttpServerStarter; use dropshot::RequestContext; use dropshot::TypedBody; use hyper::body::Bytes; -use mg_common::net::{Ipv6Prefix, TunnelOrigin}; +use mg_common::net::TunnelOrigin; +use oxnet::Ipv6Net; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use slog::Logger; @@ -131,7 +132,7 @@ impl From> for PullResponse { Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, JsonSchema, )] pub struct PathVector { - pub destination: Ipv6Prefix, + pub destination: Ipv6Net, pub path: Vec, } @@ -772,8 +773,8 @@ fn handle_underlay_update(update: &UnderlayUpdate, ctx: &HandlerContext) { path: prefix.path.clone(), }); let mut r = crate::sys::Route::new( - prefix.destination.addr.into(), - prefix.destination.len, + prefix.destination.addr().into(), + prefix.destination.width(), ctx.peer.into(), ); r.ifname.clone_from(&ctx.ctx.config.if_name); @@ -810,8 +811,8 @@ fn handle_underlay_update(update: &UnderlayUpdate, ctx: &HandlerContext) { for w in &withdraw { if db.routes_by_vector(w.destination, w.nexthop).is_empty() { let mut r = crate::sys::Route::new( - w.destination.addr.into(), - w.destination.len, + w.destination.addr().into(), + w.destination.width(), w.nexthop.into(), ); r.ifname.clone_from(&ctx.ctx.config.if_name); diff --git a/ddm/src/sm.rs b/ddm/src/sm.rs index 3a5a9583..857c9581 100644 --- a/ddm/src/sm.rs +++ b/ddm/src/sm.rs @@ -7,7 +7,8 @@ use crate::discovery::Version; use crate::exchange::{PathVector, TunnelUpdate, UnderlayUpdate, Update}; use crate::{dbg, discovery, err, exchange, inf, wrn}; use libnet::get_ipaddr_info; -use mg_common::net::{Ipv6Prefix, TunnelOrigin}; +use libnet::Ipv6Net; +use mg_common::net::TunnelOrigin; use slog::Logger; use std::collections::HashSet; use std::net::{IpAddr, Ipv6Addr}; @@ -36,7 +37,7 @@ pub enum AdminEvent { #[derive(Debug)] pub enum PrefixSet { - Underlay(HashSet), + Underlay(HashSet), Tunnel(HashSet), } @@ -91,7 +92,7 @@ pub enum EventError { #[derive(Debug)] pub enum EventResponse { Success, - Prefixes(Vec), + Prefixes(Vec), } #[derive(Error, Debug)] diff --git a/ddm/src/sys.rs b/ddm/src/sys.rs index 62663f4f..547c0d4d 100644 --- a/ddm/src/sys.rs +++ b/ddm/src/sys.rs @@ -11,7 +11,7 @@ use dendrite_common::ports::RearPort; use dpd_client::types; use dpd_client::Client; use dpd_client::ClientState; -use libnet::{IpNet, Ipv4Net, Ipv6Net}; +use oxnet::{IpNet, Ipv4Net, Ipv6Net}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use slog::Logger; @@ -51,9 +51,8 @@ impl Route { impl From for Route { fn from(r: crate::db::Route) -> Self { Self { - dest: r.destination.addr.into(), - //TODO libnet should return a u8, as nothing > 128 is a valid mask - prefix_len: r.destination.len, + dest: r.destination.addr().into(), + prefix_len: r.destination.width(), gw: r.nexthop.into(), egress_port: 0, ifname: r.ifname, @@ -65,7 +64,6 @@ impl From for Route { fn from(r: libnet::route::Route) -> Self { Self { dest: r.dest, - //TODO libnet should return a u8, as nothing > 128 is a valid mask prefix_len: r.mask.try_into().unwrap(), gw: r.gw, egress_port: 0, @@ -78,7 +76,6 @@ impl From for libnet::route::Route { fn from(r: Route) -> libnet::route::Route { libnet::route::Route { dest: r.dest, - //TODO libnet should return a u8 as nothing > 128 is a valid mask mask: r.prefix_len as u32, gw: r.gw, delay: 0, @@ -232,9 +229,8 @@ pub fn add_routes_dendrite( #[cfg(target_os = "illumos")] fn tunnel_route_update_map( routes: &HashSet, -) -> HashMap> { - let mut m: HashMap> = - HashMap::new(); +) -> HashMap> { + let mut m: HashMap> = HashMap::new(); for r in routes { let pfx = r.origin.overlay_prefix; let tep = TunnelEndpoint { @@ -286,13 +282,13 @@ pub fn add_tunnel_routes( ); } let vip = match pfx { - mg_common::net::IpPrefix::V4(p) => IpCidr::Ip4(Ipv4Cidr::new( - p.addr.into(), - Ipv4PrefixLen::new(p.len).unwrap(), + IpNet::V4(p) => IpCidr::Ip4(Ipv4Cidr::new( + p.addr().into(), + Ipv4PrefixLen::new(p.width()).unwrap(), )), - mg_common::net::IpPrefix::V6(p) => IpCidr::Ip6(Ipv6Cidr::new( - p.addr.into(), - Ipv6PrefixLen::new(p.len).unwrap(), + IpNet::V6(p) => IpCidr::Ip6(Ipv6Cidr::new( + p.addr().into(), + Ipv6PrefixLen::new(p.width()).unwrap(), )), }; let req = SetVirt2BoundaryReq { vip, tep }; @@ -336,13 +332,13 @@ pub fn remove_tunnel_routes( ); } let vip = match pfx { - mg_common::net::IpPrefix::V4(p) => IpCidr::Ip4(Ipv4Cidr::new( - p.addr.into(), - Ipv4PrefixLen::new(p.len).unwrap(), + IpNet::V4(p) => IpCidr::Ip4(Ipv4Cidr::new( + p.addr().into(), + Ipv4PrefixLen::new(p.width()).unwrap(), )), - mg_common::net::IpPrefix::V6(p) => IpCidr::Ip6(Ipv6Cidr::new( - p.addr.into(), - Ipv6PrefixLen::new(p.len).unwrap(), + IpNet::V6(p) => IpCidr::Ip6(Ipv6Cidr::new( + p.addr().into(), + Ipv6PrefixLen::new(p.width()).unwrap(), )), }; let req = ClearVirt2BoundaryReq { vip, tep }; diff --git a/ddmadm/Cargo.toml b/ddmadm/Cargo.toml index 703629e4..02ae3dda 100644 --- a/ddmadm/Cargo.toml +++ b/ddmadm/Cargo.toml @@ -7,13 +7,14 @@ edition = "2021" ddm = { path = "../ddm" } mg-common = { path = "../mg-common" } ddm-admin-client = { path = "../ddm-admin-client" } +anstyle.workspace = true +anyhow.workspace = true clap.workspace = true -slog.workspace = true -slog-term.workspace = true -slog-envlogger.workspace = true +colored.workspace = true +oxnet.workspace = true slog-async.workspace = true -tokio.workspace = true +slog-envlogger.workspace = true +slog-term.workspace = true +slog.workspace = true tabwriter.workspace = true -colored.workspace = true -anyhow.workspace = true -anstyle.workspace = true +tokio.workspace = true diff --git a/ddmadm/src/main.rs b/ddmadm/src/main.rs index 46005cb5..6c5f10ac 100644 --- a/ddmadm/src/main.rs +++ b/ddmadm/src/main.rs @@ -7,7 +7,7 @@ use clap::Parser; use colored::*; use ddm_admin_client::{types, Client}; use mg_common::cli::oxide_cli_style; -use mg_common::net::{IpPrefix, Ipv4Prefix, Ipv6Prefix}; +use oxnet::{IpNet, Ipv6Net}; use slog::{Drain, Logger}; use std::io::{stdout, Write}; use std::net::{IpAddr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; @@ -66,13 +66,13 @@ enum SubCommand { #[derive(Debug, Parser)] struct Prefixes { - prefixes: Vec, + prefixes: Vec, } #[derive(Debug, Parser)] struct TunnelEndpoint { #[arg(short, long)] - pub overlay_prefix: IpPrefix, + pub overlay_prefix: IpNet, #[arg(short, long)] pub boundary_addr: Ipv6Addr, @@ -156,9 +156,7 @@ async fn run() -> Result<()> { writeln!( &mut tw, "{}\t{}\t{}", - to_ipv6_prefix(&pv.destination), - nexthop, - strpath, + &pv.destination, nexthop, strpath, )?; } } @@ -169,29 +167,15 @@ async fn run() -> Result<()> { let mut tw = TabWriter::new(stdout()); writeln!(&mut tw, "{}", "Prefix".dimmed(),)?; for prefix in msg.into_inner() { - writeln!(&mut tw, "{}", to_ipv6_prefix(&prefix))?; + writeln!(&mut tw, "{}", &prefix)?; } tw.flush()?; } SubCommand::AdvertisePrefixes(ac) => { - let mut prefixes: Vec = Vec::new(); - for p in ac.prefixes { - prefixes.push(types::Ipv6Prefix { - addr: p.addr, - len: p.len, - }); - } - client.advertise_prefixes(&prefixes).await?; + client.advertise_prefixes(&ac.prefixes).await?; } SubCommand::WithdrawPrefixes(ac) => { - let mut prefixes: Vec = Vec::new(); - for p in ac.prefixes { - prefixes.push(types::Ipv6Prefix { - addr: p.addr, - len: p.len, - }); - } - client.withdraw_prefixes(&prefixes).await?; + client.withdraw_prefixes(&ac.prefixes).await?; } SubCommand::TunnelImported => { let msg = client.get_tunnel_endpoints().await?; @@ -208,7 +192,7 @@ async fn run() -> Result<()> { writeln!( &mut tw, "{}\t{}\t{}\t{}", - to_ip_prefix(&endpoint.origin.overlay_prefix), + &endpoint.origin.overlay_prefix, endpoint.origin.boundary_addr, endpoint.origin.vni, endpoint.origin.metric, @@ -231,7 +215,7 @@ async fn run() -> Result<()> { writeln!( &mut tw, "{}\t{}\t{}\t{}", - to_ip_prefix(&endpoint.overlay_prefix), + &endpoint.overlay_prefix, endpoint.boundary_addr, endpoint.vni, endpoint.metric, @@ -242,7 +226,7 @@ async fn run() -> Result<()> { SubCommand::TunnelAdvertise(ep) => { client .advertise_tunnel_endpoints(&vec![types::TunnelOrigin { - overlay_prefix: to_types_ip_prefix(&ep.overlay_prefix), + overlay_prefix: ep.overlay_prefix, boundary_addr: ep.boundary_addr, vni: ep.vni, metric: ep.metric, @@ -252,7 +236,7 @@ async fn run() -> Result<()> { SubCommand::TunnelWithdraw(ep) => { client .withdraw_tunnel_endpoints(&vec![types::TunnelOrigin { - overlay_prefix: to_types_ip_prefix(&ep.overlay_prefix), + overlay_prefix: ep.overlay_prefix, boundary_addr: ep.boundary_addr, vni: ep.vni, metric: ep.metric, @@ -274,45 +258,3 @@ fn init_logger() -> Logger { let drain = slog_async::Async::new(drain).build().fuse(); slog::Logger::root(drain, slog::o!()) } - -fn to_ipv6_prefix(x: &types::Ipv6Prefix) -> Ipv6Prefix { - Ipv6Prefix { - addr: x.addr, - len: x.len, - } -} - -fn to_ipv4_prefix(x: &types::Ipv4Prefix) -> Ipv4Prefix { - Ipv4Prefix { - addr: x.addr, - len: x.len, - } -} - -fn to_ip_prefix(x: &types::IpPrefix) -> IpPrefix { - match x { - types::IpPrefix::V4(p) => IpPrefix::V4(to_ipv4_prefix(p)), - types::IpPrefix::V6(p) => IpPrefix::V6(to_ipv6_prefix(p)), - } -} - -fn to_types_ipv6_prefix(x: &Ipv6Prefix) -> types::Ipv6Prefix { - types::Ipv6Prefix { - addr: x.addr, - len: x.len, - } -} - -fn to_types_ipv4_prefix(x: &Ipv4Prefix) -> types::Ipv4Prefix { - types::Ipv4Prefix { - addr: x.addr, - len: x.len, - } -} - -fn to_types_ip_prefix(x: &IpPrefix) -> types::IpPrefix { - match x { - IpPrefix::V4(p) => types::IpPrefix::V4(to_types_ipv4_prefix(p)), - IpPrefix::V6(p) => types::IpPrefix::V6(to_types_ipv6_prefix(p)), - } -} diff --git a/mg-admin-client/build.rs b/mg-admin-client/build.rs deleted file mode 100644 index df355f75..00000000 --- a/mg-admin-client/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=../openapi/mg-admin.json"); -} diff --git a/mg-common/Cargo.toml b/mg-common/Cargo.toml index 5f3abccb..b6d46bab 100644 --- a/mg-common/Cargo.toml +++ b/mg-common/Cargo.toml @@ -16,7 +16,16 @@ internal-dns.workspace = true tokio.workspace = true oximeter-producer.workspace = true oximeter.workspace = true +oxnet.workspace = true backoff.workspace = true smf.workspace = true uuid.workspace = true -libnet.workspace = true + +# We need this on illumos, but must omit it on other platforms +[dependencies.libnet] +workspace = true +optional = true + +[features] +default = ["libnet"] +libnet = ["dep:libnet"] diff --git a/mg-common/src/net.rs b/mg-common/src/net.rs index c490f8dd..5c1c1470 100644 --- a/mg-common/src/net.rs +++ b/mg-common/src/net.rs @@ -1,153 +1,13 @@ +use oxnet::IpNet; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::{ - net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr}, - num::ParseIntError, -}; -use thiserror::Error; - -#[derive( - Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, -)] -pub enum IpPrefix { - V4(Ipv4Prefix), - V6(Ipv6Prefix), -} - -impl std::fmt::Display for IpPrefix { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::V4(p) => p.fmt(f), - Self::V6(p) => p.fmt(f), - } - } -} - -impl IpPrefix { - pub fn addr(&self) -> IpAddr { - match self { - Self::V4(s) => s.addr.into(), - Self::V6(s) => s.addr.into(), - } - } - - pub fn length(&self) -> u8 { - match self { - Self::V4(s) => s.len, - Self::V6(s) => s.len, - } - } -} - -#[derive(Debug, Error)] -pub enum IpPrefixParseError { - #[error("v4 address parse error: {0}")] - V4(#[from] Ipv4PrefixParseError), - - #[error("v4 address parse error: {0}")] - V6(#[from] Ipv6PrefixParseError), -} - -impl std::str::FromStr for IpPrefix { - type Err = IpPrefixParseError; - - fn from_str(s: &str) -> Result { - if let Ok(result) = Ipv4Prefix::from_str(s) { - return Ok(IpPrefix::V4(result)); - } - Ok(IpPrefix::V6(Ipv6Prefix::from_str(s)?)) - } -} - -#[derive( - Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, -)] -pub struct Ipv4Prefix { - pub addr: Ipv4Addr, - pub len: u8, -} - -impl std::fmt::Display for Ipv4Prefix { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}/{}", self.addr, self.len) - } -} - -#[derive(Debug, Error)] -pub enum Ipv4PrefixParseError { - #[error("expected CIDR representation /")] - Cidr, - - #[error("address parse error: {0}")] - Addr(#[from] AddrParseError), - - #[error("mask parse error: {0}")] - Mask(#[from] ParseIntError), -} - -impl std::str::FromStr for Ipv4Prefix { - type Err = Ipv4PrefixParseError; - - fn from_str(s: &str) -> Result { - let parts: Vec<&str> = s.split('/').collect(); - if parts.len() < 2 { - return Err(Ipv4PrefixParseError::Cidr); - } - - Ok(Ipv4Prefix { - addr: Ipv4Addr::from_str(parts[0])?, - len: u8::from_str(parts[1])?, - }) - } -} - -#[derive( - Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, -)] -pub struct Ipv6Prefix { - pub addr: Ipv6Addr, - pub len: u8, -} - -impl std::fmt::Display for Ipv6Prefix { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}/{}", self.addr, self.len) - } -} - -#[derive(Debug, Error)] -pub enum Ipv6PrefixParseError { - #[error("expected CIDR representation /")] - Cidr, - - #[error("address parse error: {0}")] - Addr(#[from] AddrParseError), - - #[error("mask parse error: {0}")] - Mask(#[from] ParseIntError), -} - -impl std::str::FromStr for Ipv6Prefix { - type Err = Ipv6PrefixParseError; - - fn from_str(s: &str) -> Result { - let parts: Vec<&str> = s.split('/').collect(); - if parts.len() < 2 { - return Err(Ipv6PrefixParseError::Cidr); - } - - Ok(Ipv6Prefix { - addr: Ipv6Addr::from_str(parts[0])?, - len: u8::from_str(parts[1])?, - }) - } -} +use std::net::Ipv6Addr; #[derive( Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, )] pub struct TunnelOrigin { - pub overlay_prefix: IpPrefix, + pub overlay_prefix: IpNet, pub boundary_addr: Ipv6Addr, pub vni: u32, #[serde(default)] diff --git a/mg-lower/Cargo.toml b/mg-lower/Cargo.toml index 1df2faae..ae948ec1 100644 --- a/mg-lower/Cargo.toml +++ b/mg-lower/Cargo.toml @@ -15,3 +15,4 @@ tokio.workspace = true thiserror.workspace = true http.workspace = true mg-common.workspace = true +oxnet.workspace = true diff --git a/mg-lower/src/ddm.rs b/mg-lower/src/ddm.rs index 54c87b02..632f8a66 100644 --- a/mg-lower/src/ddm.rs +++ b/mg-lower/src/ddm.rs @@ -2,9 +2,10 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use ddm_admin_client::types::{Ipv6Prefix, TunnelOrigin}; +use ddm_admin_client::types::TunnelOrigin; use ddm_admin_client::Client; use dpd_client::Cidr; +use oxnet::Ipv6Net; use rdb::db::Rib; use rdb::{Prefix, Prefix4, Prefix6, DEFAULT_ROUTE_PRIORITY}; use slog::{error, info, Logger}; @@ -52,7 +53,7 @@ fn ensure_tep_underlay_origin( rt: &Arc, log: &Logger, ) { - let current: Vec = match rt + let current: Vec = match rt .block_on(async { client.get_originated().await }) .map(|x| x.into_inner()) { @@ -65,7 +66,7 @@ fn ensure_tep_underlay_origin( .into_iter() .collect(); - let target = Ipv6Prefix { addr: tep, len: 64 }; + let target = Ipv6Net::new(tep, 64).unwrap(); if current.contains(&target) { return; @@ -82,12 +83,9 @@ fn route_to_tunnel(tep: Ipv6Addr, prefix: &Prefix) -> TunnelOrigin { match prefix { Prefix::V4(p) => { TunnelOrigin { - overlay_prefix: ddm_admin_client::types::IpPrefix::V4( - ddm_admin_client::types::Ipv4Prefix { - addr: p.value, - len: p.length, - }, - ), + overlay_prefix: oxnet::Ipv4Net::new(p.value, p.length) + .unwrap() + .into(), boundary_addr: tep, vni: BOUNDARY_SERVICES_VNI, //TODO? metric: DEFAULT_ROUTE_PRIORITY, //TODO @@ -95,12 +93,9 @@ fn route_to_tunnel(tep: Ipv6Addr, prefix: &Prefix) -> TunnelOrigin { } Prefix::V6(p) => { TunnelOrigin { - overlay_prefix: ddm_admin_client::types::IpPrefix::V6( - ddm_admin_client::types::Ipv6Prefix { - addr: p.value, - len: p.length, - }, - ), + overlay_prefix: oxnet::Ipv6Net::new(p.value, p.length) + .unwrap() + .into(), boundary_addr: tep, vni: BOUNDARY_SERVICES_VNI, //TODO? metric: DEFAULT_ROUTE_PRIORITY, //TODO diff --git a/mgadm/src/static_routing.rs b/mgadm/src/static_routing.rs index 5d182be7..f5fa9662 100644 --- a/mgadm/src/static_routing.rs +++ b/mgadm/src/static_routing.rs @@ -18,7 +18,7 @@ pub enum Commands { } #[derive(Debug, Error)] -pub enum Ipv4PrefixParseError { +pub enum Ipv4NetParseError { #[error("expected CIDR representation /")] Cidr, @@ -31,27 +31,27 @@ pub enum Ipv4PrefixParseError { #[derive(Debug, Args)] pub struct StaticRoute4 { - pub destination: Ipv4Prefix, + pub destination: Ipv4Net, pub nexthop: Ipv4Addr, pub vlan_id: Option, } #[derive(Debug, Clone, Copy)] -pub struct Ipv4Prefix { +pub struct Ipv4Net { pub addr: Ipv4Addr, pub len: u8, } -impl std::str::FromStr for Ipv4Prefix { - type Err = Ipv4PrefixParseError; +impl std::str::FromStr for Ipv4Net { + type Err = Ipv4NetParseError; fn from_str(s: &str) -> Result { let parts: Vec<&str> = s.split('/').collect(); if parts.len() < 2 { - return Err(Ipv4PrefixParseError::Cidr); + return Err(Ipv4NetParseError::Cidr); } - Ok(Ipv4Prefix { + Ok(Ipv4Net { addr: Ipv4Addr::from_str(parts[0])?, len: u8::from_str(parts[1])?, }) diff --git a/mgd/Cargo.toml b/mgd/Cargo.toml index d42d8c85..71027508 100644 --- a/mgd/Cargo.toml +++ b/mgd/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] mg-lower = { path = "../mg-lower", optional = true } -mg-common = { path = "../mg-common" } +mg-common = { path = "../mg-common", default-features = false} bfd = { path = "../bfd" } bgp = { path = "../bgp" } rdb = { path = "../rdb" } @@ -32,3 +32,4 @@ smf.workspace = true [features] default = ["mg-lower"] +mg-lower = ["dep:mg-lower"] diff --git a/mgd/src/main.rs b/mgd/src/main.rs index 184fcefa..5d095b3f 100644 --- a/mgd/src/main.rs +++ b/mgd/src/main.rs @@ -124,7 +124,7 @@ async fn run(args: RunArgs) { error!(log, "send context to signal handler {e}"); } - #[cfg(feature = "default")] + #[cfg(feature = "mg-lower")] { let rt = Arc::new(tokio::runtime::Handle::current()); let ctx = context.clone(); diff --git a/openapi/ddm-admin.json b/openapi/ddm-admin.json index 0fa17ba7..5427a31a 100644 --- a/openapi/ddm-admin.json +++ b/openapi/ddm-admin.json @@ -56,10 +56,10 @@ "content": { "application/json": { "schema": { - "title": "Set_of_Ipv6Prefix", + "title": "Set_of_Ipv6Net", "type": "array", "items": { - "$ref": "#/components/schemas/Ipv6Prefix" + "$ref": "#/components/schemas/Ipv6Net" }, "uniqueItems": true } @@ -164,10 +164,10 @@ "content": { "application/json": { "schema": { - "title": "Set_of_Ipv6Prefix", + "title": "Set_of_Ipv6Net", "type": "array", "items": { - "$ref": "#/components/schemas/Ipv6Prefix" + "$ref": "#/components/schemas/Ipv6Net" }, "uniqueItems": true } @@ -193,10 +193,10 @@ "content": { "application/json": { "schema": { - "title": "Set_of_Ipv6Prefix", + "title": "Set_of_Ipv6Net", "type": "array", "items": { - "$ref": "#/components/schemas/Ipv6Prefix" + "$ref": "#/components/schemas/Ipv6Net" }, "uniqueItems": true } @@ -403,75 +403,60 @@ "request_id" ] }, - "IpPrefix": { + "IpNet": { + "x-rust-type": { + "crate": "oxnet", + "path": "oxnet::IpNet", + "version": "0.1.0" + }, "oneOf": [ { - "type": "object", - "properties": { - "V4": { - "$ref": "#/components/schemas/Ipv4Prefix" + "title": "v4", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Net" } - }, - "required": [ - "V4" - ], - "additionalProperties": false + ] }, { - "type": "object", - "properties": { - "V6": { - "$ref": "#/components/schemas/Ipv6Prefix" + "title": "v6", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" } - }, - "required": [ - "V6" - ], - "additionalProperties": false + ] } ] }, - "Ipv4Prefix": { - "type": "object", - "properties": { - "addr": { - "type": "string", - "format": "ipv4" - }, - "len": { - "type": "integer", - "format": "uint8", - "minimum": 0 - } + "Ipv4Net": { + "example": "192.168.1.0/24", + "title": "An IPv4 subnet", + "description": "An IPv4 subnet, including prefix and prefix length", + "x-rust-type": { + "crate": "oxnet", + "path": "oxnet::Ipv4Net", + "version": "0.1.0" }, - "required": [ - "addr", - "len" - ] + "type": "string", + "pattern": "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([0-9]|1[0-9]|2[0-9]|3[0-2])$" }, - "Ipv6Prefix": { - "type": "object", - "properties": { - "addr": { - "type": "string", - "format": "ipv6" - }, - "len": { - "type": "integer", - "format": "uint8", - "minimum": 0 - } + "Ipv6Net": { + "example": "fd12:3456::/64", + "title": "An IPv6 subnet", + "description": "An IPv6 subnet, including prefix and subnet mask", + "x-rust-type": { + "crate": "oxnet", + "path": "oxnet::Ipv6Net", + "version": "0.1.0" }, - "required": [ - "addr", - "len" - ] + "type": "string", + "pattern": "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$" }, "PathVector": { "type": "object", "properties": { "destination": { - "$ref": "#/components/schemas/Ipv6Prefix" + "$ref": "#/components/schemas/Ipv6Net" }, "path": { "type": "array", @@ -538,7 +523,7 @@ "minimum": 0 }, "overlay_prefix": { - "$ref": "#/components/schemas/IpPrefix" + "$ref": "#/components/schemas/IpNet" }, "vni": { "type": "integer", @@ -582,4 +567,4 @@ } } } -} \ No newline at end of file +} diff --git a/tests/src/ddm.rs b/tests/src/ddm.rs index a64c0696..cd99a607 100644 --- a/tests/src/ddm.rs +++ b/tests/src/ddm.rs @@ -3,7 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use anyhow::{anyhow, Result}; -use ddm_admin_client::types::{IpPrefix, Ipv4Prefix, Ipv6Prefix, TunnelOrigin}; +use ddm_admin_client::types::TunnelOrigin; use ddm_admin_client::Client; use slog::{Drain, Logger}; use std::env; @@ -450,11 +450,8 @@ async fn run_trio_tests( println!("initial peering test passed"); - s1.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s1.advertise_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; wait_for_eq!(prefix_count(&s1).await?, 0); wait_for_eq!(prefix_count(&s2).await?, 1); @@ -462,11 +459,8 @@ async fn run_trio_tests( println!("advertise from one passed"); - s2.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:2::".parse().unwrap(), - len: 64, - }]) - .await?; + s2.advertise_prefixes(&vec!["fd00:2::/64".parse().unwrap()]) + .await?; wait_for_eq!(prefix_count(&s1).await?, 1); wait_for_eq!(prefix_count(&s2).await?, 1); @@ -505,11 +499,8 @@ async fn run_trio_tests( wait_for_eq!(prefix_count(&t1).await?, 2); } - s1.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s1.advertise_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; wait_for_eq!(prefix_count(&s1).await?, 1); wait_for_eq!(prefix_count(&s2).await?, 1); @@ -532,21 +523,15 @@ async fn run_trio_tests( wait_for_eq!(prefix_count(&s2).await?, 1); wait_for_eq!(prefix_count(&t1).await?, 2); - s2.withdraw_prefixes(&vec![Ipv6Prefix { - addr: "fd00:2::".parse().unwrap(), - len: 64, - }]) - .await?; + s2.withdraw_prefixes(&vec!["fd00:2::/64".parse().unwrap()]) + .await?; wait_for_eq!(prefix_count(&s1).await?, 0); wait_for_eq!(prefix_count(&s2).await?, 1); wait_for_eq!(prefix_count(&t1).await?, 1); - s2.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:2::".parse().unwrap(), - len: 64, - }]) - .await?; + s2.advertise_prefixes(&vec!["fd00:2::/64".parse().unwrap()]) + .await?; wait_for_eq!(prefix_count(&s1).await?, 1); wait_for_eq!(prefix_count(&s2).await?, 1); @@ -557,18 +542,9 @@ async fn run_trio_tests( // ensure that when an advertisement with a duplicate route is made, all // routes make it in the kernel of receivers. s2.advertise_prefixes(&vec![ - Ipv6Prefix { - addr: "fd00:2::".parse().unwrap(), - len: 64, - }, - Ipv6Prefix { - addr: "fd00:3::".parse().unwrap(), - len: 64, - }, - Ipv6Prefix { - addr: "fd00:4::".parse().unwrap(), - len: 64, - }, + "fd00:2::/64".parse().unwrap(), + "fd00:3::/64".parse().unwrap(), + "fd00:4::/64".parse().unwrap(), ]) .await?; wait_for_eq!(prefix_count(&s1).await?, 3); @@ -582,10 +558,7 @@ async fn run_trio_tests( wait_for_eq!(tunnel_originated_endpoint_count(&t1).await?, 0); t1.advertise_tunnel_endpoints(&vec![TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "203.0.113.0".parse().unwrap(), - len: 24, - }), + overlay_prefix: "203.0.113.0/24".parse().unwrap(), boundary_addr: "fd00:1701::1".parse().unwrap(), vni: 47, metric: 0, @@ -602,10 +575,7 @@ async fn run_trio_tests( // redudant advertise should not change things t1.advertise_tunnel_endpoints(&vec![TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "203.0.113.0".parse().unwrap(), - len: 24, - }), + overlay_prefix: "203.0.113.0/24".parse().unwrap(), boundary_addr: "fd00:1701::1".parse().unwrap(), vni: 47, metric: 0, @@ -631,10 +601,7 @@ async fn run_trio_tests( println!("tunnel router restart passed"); t1.withdraw_tunnel_endpoints(&vec![TunnelOrigin { - overlay_prefix: IpPrefix::V4(Ipv4Prefix { - addr: "203.0.113.0".parse().unwrap(), - len: 24, - }), + overlay_prefix: "203.0.113.0/24".parse().unwrap(), boundary_addr: "fd00:1701::1".parse().unwrap(), vni: 47, metric: 0, @@ -779,17 +746,11 @@ async fn run_quartet_tests( println!("initial peering test passed"); - s1.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s1.advertise_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; - s3.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:3::".parse().unwrap(), - len: 64, - }]) - .await?; + s3.advertise_prefixes(&vec!["fd00:3::/64".parse().unwrap()]) + .await?; // s1/s3 should now have 1 prefix wait_for_eq!(prefix_count(&s1).await?, 1); @@ -799,30 +760,21 @@ async fn run_quartet_tests( zs3.zexec("ping fd00:1::1")?; // s2 hijacks s1's prefix - s2.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s2.advertise_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; // s3 should now have 2 prefixes wait_for_eq!(prefix_count(&s3).await?, 2); - s2.withdraw_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s2.withdraw_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; // wait for withdraw propagation sleep(Duration::from_secs(5)); // unhijack - s1.advertise_prefixes(&vec![Ipv6Prefix { - addr: "fd00:1::".parse().unwrap(), - len: 64, - }]) - .await?; + s1.advertise_prefixes(&vec!["fd00:1::/64".parse().unwrap()]) + .await?; sleep(Duration::from_secs(5)); // s3 should still have 1 prefix left