Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 35 additions & 10 deletions cli/src/cmd_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use oxide::{
types::{
Address, AddressConfig, BgpAnnounceSetCreate, BgpAnnouncementCreate, BgpPeer,
BgpPeerConfig, BgpPeerStatus, ImportExportPolicy, IpNet, LinkConfigCreate, LinkFec,
LinkSpeed, LldpLinkConfigCreate, Name, NameOrId, Route, RouteConfig,
LinkSpeed, LldpLinkConfigCreate, Name, NameOrId, Route, RouteConfig, RouterPeerType,
SwitchInterfaceConfigCreate, SwitchInterfaceKind, SwitchInterfaceKind2, SwitchPort,
SwitchPortConfigCreate, SwitchPortGeometry, SwitchPortGeometry2, SwitchPortRouteConfig,
SwitchPortSettingsCreate, SwitchSlot,
Expand Down Expand Up @@ -421,7 +421,10 @@ impl AuthenticatedCmd for CmdBgpFilter {
let peer = config
.peers
.iter_mut()
.find(|x| x.addr == Some(self.peer))
.find(|x| {
matches!( &x.addr,
RouterPeerType::Numbered { ip } if *ip == self.peer)
})
.ok_or(anyhow::anyhow!("specified peer does not exist"))?;

let list: Vec<IpNet> = self
Expand Down Expand Up @@ -502,7 +505,10 @@ impl AuthenticatedCmd for CmdBgpAuth {
let peer = config
.peers
.iter_mut()
.find(|x| x.addr == Some(self.peer))
.find(|x| {
matches!(&x.addr,
RouterPeerType::Numbered { ip } if *ip == self.peer)
})
.ok_or(anyhow::anyhow!("specified peer does not exist"))?;

peer.md5_auth_key = self.authstring.clone();
Expand Down Expand Up @@ -564,7 +570,10 @@ impl AuthenticatedCmd for CmdBgpLocalPref {
let peer = config
.peers
.iter_mut()
.find(|x| x.addr == Some(self.peer))
.find(|x| {
matches!(&x.addr,
RouterPeerType::Numbered { ip } if *ip == self.peer)
})
.ok_or(anyhow::anyhow!("specified peer does not exist"))?;

peer.local_pref = self.local_pref
Expand Down Expand Up @@ -1089,7 +1098,7 @@ impl AuthenticatedCmd for CmdBgpPeerSet {
let mut settings =
current_port_settings(client, &self.rack, self.switch.into(), &self.port).await?;
let peer = BgpPeer {
addr: Some(self.addr),
addr: RouterPeerType::Numbered { ip: self.addr },
allowed_import: if self.allowed_imports.is_empty() {
ImportExportPolicy::NoFiltering
} else {
Expand Down Expand Up @@ -1119,22 +1128,31 @@ impl AuthenticatedCmd for CmdBgpPeerSet {
enforce_first_as: self.enforce_first_as,
hold_time: self.hold_time,
idle_hold_time: self.idle_hold_time,
interface_name: PHY0.try_into().unwrap(),
keepalive: self.keepalive,
local_pref: self.local_pref,
md5_auth_key: self.authstring.clone(),
min_ttl: self.min_ttl,
multi_exit_discriminator: self.multi_exit_discriminator,
remote_asn: self.remote_asn,
vlan_id: self.vlan_id,
router_lifetime: self.router_lifetime.unwrap_or(0),
};
match settings
.bgp_peers
.iter_mut()
.find(|link| *link.link_name == PHY0)
{
Some(conf) => match conf.peers.iter_mut().find(|x| x.addr == peer.addr) {
Some(conf) => match conf.peers.iter_mut().find(|x| match (&x.addr, &peer.addr) {
(
RouterPeerType::Unnumbered { router_lifetime: a },
RouterPeerType::Unnumbered { router_lifetime: b },
) if **a == **b => true,
(RouterPeerType::Numbered { ip: a }, RouterPeerType::Numbered { ip: b })
if a == b =>
{
true
}
_ => false,
}) {
Some(p) => *p = peer,
None => conf.peers.push(peer),
},
Expand Down Expand Up @@ -1190,7 +1208,10 @@ impl AuthenticatedCmd for CmdBgpPeerDel {
.find(|link| *link.link_name == PHY0)
{
let before = config.peers.len();
config.peers.retain(|x| x.addr != Some(self.addr));
config.peers.retain(|x| {
matches!(&x.addr,
RouterPeerType::Numbered { ip } if *ip == self.addr)
});
let after = config.peers.len();
if before == after {
eprintln_nopipe!("no peers match the provided address");
Expand Down Expand Up @@ -1350,7 +1371,11 @@ impl AuthenticatedCmd for CmdPortConfig {
writeln!(
&mut tw,
"{}\t{}\t[{}]\t[{}]\t{:?}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
p.addr.map_or("-".to_string(), |a| a.to_string()),
match &p.addr {
RouterPeerType::Unnumbered { router_lifetime } =>
format!("({router_lifetime})"),
RouterPeerType::Numbered { ip } => ip.to_string(),
},
match &p.bgp_config {
NameOrId::Id(id) => bgp_configs[id].to_string(),
NameOrId::Name(name) => name.to_string(),
Expand Down
2 changes: 1 addition & 1 deletion cli/tests/data/test_switch_port_settings_show.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Address Lot VLAN
BGP Peer Config Export Import Communities Connect Retry Delay Open Enforce First AS Hold Time Idle Hold Time Keepalive Local Pref Md5 Auth Min TTL MED Remote ASN VLAN
169.254.20.1 as65547 [198.51.100.0/24] [no filtering] [] 3 3 false 6 3 2 - - - - - -
169.254.40.1 as65547 [203.0.113.0/24] [no filtering] [] 0 0 false 6 0 2 - - - - - 400
- as65547 [203.0.113.0/24] [no filtering] [] 0 0 false 6 0 2 - - - - - 400
(0) as65547 [203.0.113.0/24] [no filtering] [] 0 0 false 6 0 2 - - - - - 400

Destination Nexthop Vlan Preference

38 changes: 19 additions & 19 deletions cli/tests/test_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
// 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/.

// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use chrono::prelude::*;
use httpmock::MockServer;
use oxide::types::{
AddressLot, AddressLotBlock, AddressLotBlockResultsPage, AddressLotKind, AddressLotResultsPage,
BgpConfig, BgpConfigResultsPage, BgpPeer, ImportExportPolicy, LinkFec, LinkSpeed,
MaxPathConfig, Name, NameOrId, SwitchPort, SwitchPortAddressView, SwitchPortConfig,
SwitchPortGeometry2, SwitchPortLinkConfig, SwitchPortResultsPage, SwitchPortRouteConfig,
SwitchPortSettings, SwitchSlot,
MaxPathConfig, Name, NameOrId, RouterPeerType, SwitchPort, SwitchPortAddressView,
SwitchPortConfig, SwitchPortGeometry2, SwitchPortLinkConfig, SwitchPortResultsPage,
SwitchPortRouteConfig, SwitchPortSettings, SwitchSlot,
};
use oxide_httpmock::MockServerExt;
use uuid::Uuid;
Expand Down Expand Up @@ -130,8 +130,9 @@ fn test_port_config() {
],
bgp_peers: vec![
BgpPeer {
interface_name: "phy0".try_into().unwrap(),
addr: Some("169.254.10.1".parse().unwrap()),
addr: RouterPeerType::Numbered {
ip: "169.254.10.1".parse().unwrap(),
},
bgp_config: NameOrId::Id(bgp_configs.items[0].id),
allowed_export: ImportExportPolicy::Allow(vec!["198.51.100.0/24".parse().unwrap()]),
allowed_import: ImportExportPolicy::NoFiltering,
Expand All @@ -148,11 +149,11 @@ fn test_port_config() {
multi_exit_discriminator: None,
remote_asn: None,
vlan_id: None,
router_lifetime: 0,
},
BgpPeer {
interface_name: "phy0".try_into().unwrap(),
addr: Some("169.254.30.1".parse().unwrap()),
addr: RouterPeerType::Numbered {
ip: "169.254.30.1".parse().unwrap(),
},
bgp_config: NameOrId::Id(bgp_configs.items[0].id),
allowed_export: ImportExportPolicy::Allow(vec!["203.0.113.0/24".parse().unwrap()]),
allowed_import: ImportExportPolicy::NoFiltering,
Expand All @@ -169,7 +170,6 @@ fn test_port_config() {
multi_exit_discriminator: None,
remote_asn: None,
vlan_id: Some(300),
router_lifetime: 0,
},
],
groups: Vec::new(),
Expand Down Expand Up @@ -226,8 +226,9 @@ fn test_port_config() {
],
bgp_peers: vec![
BgpPeer {
interface_name: "phy0".try_into().unwrap(),
addr: Some("169.254.20.1".parse().unwrap()),
addr: RouterPeerType::Numbered {
ip: "169.254.20.1".parse().unwrap(),
},
bgp_config: NameOrId::Id(bgp_configs.items[0].id),
allowed_export: ImportExportPolicy::Allow(vec!["198.51.100.0/24".parse().unwrap()]),
allowed_import: ImportExportPolicy::NoFiltering,
Expand All @@ -244,11 +245,11 @@ fn test_port_config() {
multi_exit_discriminator: None,
remote_asn: None,
vlan_id: None,
router_lifetime: 0,
},
BgpPeer {
interface_name: "phy0".try_into().unwrap(),
addr: Some("169.254.40.1".parse().unwrap()),
addr: RouterPeerType::Numbered {
ip: "169.254.40.1".parse().unwrap(),
},
bgp_config: NameOrId::Id(bgp_configs.items[0].id),
allowed_export: ImportExportPolicy::Allow(vec!["203.0.113.0/24".parse().unwrap()]),
allowed_import: ImportExportPolicy::NoFiltering,
Expand All @@ -265,11 +266,11 @@ fn test_port_config() {
multi_exit_discriminator: None,
remote_asn: None,
vlan_id: Some(400),
router_lifetime: 0,
},
BgpPeer {
interface_name: "phy0".try_into().unwrap(),
addr: None,
addr: RouterPeerType::Unnumbered {
router_lifetime: 0.into(),
},
bgp_config: NameOrId::Id(bgp_configs.items[0].id),
allowed_export: ImportExportPolicy::Allow(vec!["203.0.113.0/24".parse().unwrap()]),
allowed_import: ImportExportPolicy::NoFiltering,
Expand All @@ -286,7 +287,6 @@ fn test_port_config() {
multi_exit_discriminator: None,
remote_asn: None,
vlan_id: Some(400),
router_lifetime: 0,
},
],
groups: Vec::new(),
Expand Down
Loading
Loading