Skip to content

Commit 1427344

Browse files
hawkwmkeeter
andauthored
Add Sidecar image for Reverso (#2401)
> [!NOTE] > This is just @mkeeter's PR #2226, but rebased onto the latest > `master`, since [it turns out we actually do need this][1]. I had > wanted to just re-open Matt's original PR but [github would not let > me do this for some kind of reason I really don't fully understand][2]. > Anyway, heeeeeere's Matt Keeeeeeeterrrr!!! "Reverso" is a board with the same form factor as a Gimlet which loops back the two backplane connectors. In this configuration, packets leaving the VSC7448 destined for SP _i_ instead arrive at the peer Sidecar, appearing to have originated at SP _i_. In the unlocked VLAN configuration, this is a problem: packets can arrive at one tech port and emerge from the other tech port, which creates a routing loop. When this happens, our CM's network unceremoniously turns off the offending network port, and we have to manually get it re-enabled. This PR adds a `VlanTargets` parameter to unlock-related code: - `VlanTargets::EverySp` is our existing behavior, where the technician port can communicate with every cubby - `VlanTargets::ScrimletOnly` limits technician ports to only communicate with Scrimlet cubbies, which are guaranteed to be populated By preventing the technician port from talking to cubbies with Reverso installed, we can avoid network loops. The switch zone in the scrimlet can still communicate with every cubby; indeed, this is how we expect to test connectivity with Reverso installed. [1]: #2226 (comment) [2]: #2226 (comment) Co-authored-by: Matt Keeter <matt@oxide.computer>
1 parent 3bf48d4 commit 1427344

7 files changed

Lines changed: 92 additions & 10 deletions

File tree

app/sidecar/rev-c-reverso.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name = "sidecar-c-reverso"
2+
inherit = ["rev-c-dev.toml", "reverso.toml"]

app/sidecar/rev-d-reverso.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name = "sidecar-d-reverso"
2+
inherit = ["rev-d-dev.toml", "reverso.toml"]

app/sidecar/reverso.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[tasks.monorail]
2+
features = ["reverso"]

drv/vsc7448/src/lib.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ pub struct Vsc7448<'a, R> {
112112
refclk_2: Option<RefClockFreq>,
113113
}
114114

115+
/// Selects which SPs should be accessible from tech ports with unlocked VLANs
116+
#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
117+
pub enum VlanTargets {
118+
/// Every SP should be accessible from the tech port
119+
///
120+
/// This is the typical unlocked behavior
121+
EverySp,
122+
123+
/// Only Scrimlet SPs should be accessible from the tech port
124+
///
125+
/// If cubbies are populated with loopback connections (instead of sleds),
126+
/// this behavior prevents network loops; otherwise, packets can enter one
127+
/// tech port and exit the other.
128+
ScrimletOnly,
129+
}
130+
115131
impl<R: Vsc7448Rw> Vsc7448Rw for Vsc7448<'_, R> {
116132
/// Write a register to the VSC7448
117133
fn write<T>(
@@ -866,8 +882,11 @@ impl<'a, R: Vsc7448Rw> Vsc7448<'a, R> {
866882
///
867883
/// To switch between locked and unlocked later, use
868884
/// `sidecar_vlan_lock/unlock` (instead of calling this function again)
869-
pub fn configure_vlan_sidecar_unlocked(&self) -> Result<(), VscError> {
870-
self.sidecar_vlan_unlock()?;
885+
pub fn configure_vlan_sidecar_unlocked(
886+
&self,
887+
targets: VlanTargets,
888+
) -> Result<(), VscError> {
889+
self.sidecar_vlan_unlock(targets)?;
871890
self.configure_port_tagged(|p| {
872891
p == sidecar::UPLINK || p == sidecar::LOCAL_SP
873892
})?;
@@ -891,11 +910,22 @@ impl<'a, R: Vsc7448Rw> Vsc7448<'a, R> {
891910
})
892911
}
893912

894-
/// Configures the VLANs to the unlocked state, per RFD 492
913+
/// Configures the VLANs to an unlocked state, selected by `VlanTargets`
914+
pub fn sidecar_vlan_unlock(
915+
&self,
916+
targets: VlanTargets,
917+
) -> Result<(), VscError> {
918+
match targets {
919+
VlanTargets::EverySp => self.sidecar_vlan_unlock_all(),
920+
VlanTargets::ScrimletOnly => self.sidecar_vlan_unlock_scrimlet(),
921+
}
922+
}
923+
924+
/// Configures the VLANs to the standard unlocked state, per RFD 492
895925
///
896926
/// The technician ports can talk to any SP; SPs may talk to the Tofino or
897927
/// to the technician ports.
898-
pub fn sidecar_vlan_unlock(&self) -> Result<(), VscError> {
928+
fn sidecar_vlan_unlock_all(&self) -> Result<(), VscError> {
899929
self.configure_vlans(|p| match p {
900930
sidecar::UPLINK => None,
901931
sidecar::TECHNICIAN_1 => {
@@ -918,6 +948,35 @@ impl<'a, R: Vsc7448Rw> Vsc7448<'a, R> {
918948
})
919949
}
920950

951+
/// Configures the VLANs to an unlocked state with only Scrimlets accessible
952+
///
953+
/// This state is useful for racks with the Reverso™ board installed, which
954+
/// loops back the two backplane connections within a cubby. In this
955+
/// configuration, we don't want for technician ports to communicate with
956+
/// cubbies (other than Scrimlets), because that creates a routing loop
957+
/// (packets can enter via one tech port and leave via the other).
958+
fn sidecar_vlan_unlock_scrimlet(&self) -> Result<(), VscError> {
959+
self.configure_vlans(|p| match p {
960+
sidecar::UPLINK => None,
961+
// Technician ports are connected to uplink and scrimlets
962+
sidecar::TECHNICIAN_1 | sidecar::TECHNICIAN_2 => Some(
963+
(1 << p)
964+
| (1 << sidecar::UPLINK)
965+
| (1 << sidecar::CUBBY_14)
966+
| (1 << sidecar::CUBBY_16),
967+
),
968+
// Scrimlet SPs are connected to the Tofino and technician ports
969+
sidecar::CUBBY_14 | sidecar::CUBBY_16 => Some(
970+
(1 << p)
971+
| (1 << sidecar::UPLINK)
972+
| (1 << sidecar::TECHNICIAN_1)
973+
| (1 << sidecar::TECHNICIAN_2),
974+
),
975+
// Other SPs are only connected to the uplink port
976+
_ => Some((1 << p) | (1 << sidecar::UPLINK)),
977+
})
978+
}
979+
921980
/// Checks the 10GBASE-KR autonegotiation state machine for the given dev.
922981
///
923982
/// If it is stuck in `WAIT_RATE_DONE`, restarts autonegotiation and returns
@@ -966,6 +1025,12 @@ mod sidecar {
9661025

9671026
/// Technician port 2 (front IO board)
9681027
pub const TECHNICIAN_2: u8 = 45;
1028+
1029+
/// Scrimlet 1
1030+
pub const CUBBY_14: u8 = 8;
1031+
1032+
/// Scrimlet 2
1033+
pub const CUBBY_16: u8 = 4;
9691034
}
9701035

9711036
mod minibar {

task/monorail-server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ leds = ["drv-user-leds-api"]
3434
medusa = ["drv-medusa-seq-api", "drv-sidecar-front-io"]
3535
mgmt = ["task-net-api"]
3636
sidecar = ["drv-sidecar-seq-api", "drv-sidecar-front-io"]
37+
reverso = []
3738
minibar = []
3839
vlan = ["task-net-api?/vlan"]
3940
no-ipc-counters = ["idol/no-counters"]

task/monorail-server/src/bsp/medusa_a.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ impl<'a, R: Vsc7448Rw> Bsp<'a, R> {
210210
self.phy_vsc8504_init()?;
211211

212212
self.vsc7448.configure_ports_from_map(&PORT_MAP)?;
213-
self.vsc7448.configure_vlan_sidecar_unlocked()?;
213+
self.vsc7448
214+
.configure_vlan_sidecar_unlocked(vsc7448::VlanTargets::EverySp)?;
214215
self.vsc7448_postconfig()?;
215216

216217
// Some front IO boards have a faulty oscillator driving the PHY,

task/monorail-server/src/bsp/sidecar_bcd.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ enum VLanMode {
4848
UnlockedUntil(u64),
4949
}
5050

51+
const VLAN_UNLOCK_TARGETS: vsc7448::VlanTargets = if cfg!(feature = "reverso") {
52+
vsc7448::VlanTargets::ScrimletOnly
53+
} else {
54+
vsc7448::VlanTargets::EverySp
55+
};
56+
5157
////////////////////////////////////////////////////////////////////////////////
5258

5359
pub struct Bsp<'a, R> {
@@ -240,7 +246,8 @@ impl<'a, R: Vsc7448Rw> Bsp<'a, R> {
240246
VLanMode::UnlockedUntil(t) => {
241247
let now = userlib::sys_get_timer().now;
242248
if now < t {
243-
self.vsc7448.configure_vlan_sidecar_unlocked()?;
249+
self.vsc7448
250+
.configure_vlan_sidecar_unlocked(VLAN_UNLOCK_TARGETS)?;
244251
} else {
245252
ringbuf_entry!(Trace::AutomaticLock);
246253
self.vsc7448.configure_vlan_sidecar_locked()?;
@@ -595,10 +602,12 @@ impl<'a, R: Vsc7448Rw> Bsp<'a, R> {
595602
unlock_until: u64,
596603
) -> Result<(), RequestError<MonorailError>> {
597604
ringbuf_entry!(Trace::UnlockUntil(unlock_until));
598-
self.vsc7448.sidecar_vlan_unlock().map_err(|e| {
599-
ringbuf_entry!(Trace::UnlockError(e));
600-
MonorailError::from(e)
601-
})?;
605+
self.vsc7448
606+
.sidecar_vlan_unlock(VLAN_UNLOCK_TARGETS)
607+
.map_err(|e| {
608+
ringbuf_entry!(Trace::UnlockError(e));
609+
MonorailError::from(e)
610+
})?;
602611
self.vlan_mode = VLanMode::UnlockedUntil(unlock_until);
603612
Ok(())
604613
}

0 commit comments

Comments
 (0)