From c01bc55b685c222c586c26adc7a0d479ba10a41e Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Sun, 25 Jan 2026 19:39:16 +0000 Subject: [PATCH 1/4] is h29 corrupt? --- dpd/p4/sidecar.p4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpd/p4/sidecar.p4 b/dpd/p4/sidecar.p4 index 4981c73..ed38d5a 100644 --- a/dpd/p4/sidecar.p4 +++ b/dpd/p4/sidecar.p4 @@ -876,7 +876,7 @@ control NatEgress ( } apply { - if (meta.nat_egress_hit) { + if (meta.nat_egress_hit && !meta.nat_ingress_hit) { nat_egress.apply(); } } From ed1651c4e727a51eab236aeb19adf6754b295574 Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Tue, 27 Jan 2026 23:02:12 +0000 Subject: [PATCH 2/4] lot fishing --- Cargo.lock | 1 + aal/src/lib.rs | 1 + asic/src/lib.rs | 7 +++++++ asic/src/tofino_asic/mod.rs | 6 ++++++ dpd-types/src/switch_identifiers.rs | 2 ++ dpd/src/oxstats.rs | 1 + dpd/src/switch_identifiers.rs | 3 +++ swadm/Cargo.toml | 1 + swadm/src/main.rs | 16 ++++++++++++++++ 9 files changed, 38 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 8612eae..189b47f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6458,6 +6458,7 @@ dependencies = [ "oxnet", "slog", "tabwriter", + "tofino", "tokio", ] diff --git a/aal/src/lib.rs b/aal/src/lib.rs index f61a9b2..c63172b 100644 --- a/aal/src/lib.rs +++ b/aal/src/lib.rs @@ -43,6 +43,7 @@ pub trait SidecarIdentifiers { fn asic_backend(&self) -> &str; fn fab(&self) -> Option; fn lot(&self) -> Option; + fn lotnum(&self) -> Option<[char; 4]>; fn wafer(&self) -> Option; fn wafer_loc(&self) -> Option<(i16, i16)>; } diff --git a/asic/src/lib.rs b/asic/src/lib.rs index 29d4930..b6fb0be 100644 --- a/asic/src/lib.rs +++ b/asic/src/lib.rs @@ -36,6 +36,8 @@ pub struct Identifiers { fab: Option, /// Lot identifier. lot: Option, + /// Lot number + lotnum: Option<[char; 4]>, /// Wafer number within the lot. wafer: Option, /// The wafer location as (x, y) coordinates on the wafer, represented as @@ -49,6 +51,7 @@ impl Default for Identifiers { id: Uuid::new_v4(), asic_backend: "chaos".to_string(), fab: None, + lotnum: None, lot: None, wafer: None, wafer_loc: None, @@ -73,6 +76,10 @@ impl aal::SidecarIdentifiers for Identifiers { self.lot } + fn lotnum(&self) -> Option<[char; 4]> { + self.lotnum + } + fn wafer(&self) -> Option { self.wafer } diff --git a/asic/src/tofino_asic/mod.rs b/asic/src/tofino_asic/mod.rs index c85d5c5..58e5355 100644 --- a/asic/src/tofino_asic/mod.rs +++ b/asic/src/tofino_asic/mod.rs @@ -224,6 +224,12 @@ impl AsicOps for Handle { asic_backend: "tofino_asic".to_string(), fab: Some(chip_id.fab), lot: Some(chip_id.lot), + lotnum: Some([ + chip_id.lotnum0, + chip_id.lotnum1, + chip_id.lotnum2, + chip_id.lotnum3, + ]), wafer: Some(chip_id.wafer), wafer_loc: Some(wafer_loc_from_coords( chip_id.xsign, diff --git a/dpd-types/src/switch_identifiers.rs b/dpd-types/src/switch_identifiers.rs index c4fa7f9..0d86a5e 100644 --- a/dpd-types/src/switch_identifiers.rs +++ b/dpd-types/src/switch_identifiers.rs @@ -19,6 +19,8 @@ pub struct SwitchIdentifiers { pub fab: Option, /// Lot identifier. pub lot: Option, + /// Lot number + pub lotnum: Option<[char; 4]>, /// Wafer number within the lot. pub wafer: Option, /// The wafer location as (x, y) coordinates on the wafer, represented as diff --git a/dpd/src/oxstats.rs b/dpd/src/oxstats.rs index 292291f..1cb5140 100644 --- a/dpd/src/oxstats.rs +++ b/dpd/src/oxstats.rs @@ -593,6 +593,7 @@ async fn wait_for_switch_identifiers( asic_backend: switch_identifiers.asic_backend.clone(), fab: switch_identifiers.fab, lot: switch_identifiers.lot, + lotnum: switch_identifiers.lotnum, wafer: switch_identifiers.wafer, wafer_loc: switch_identifiers.wafer_loc, model: switch_identifiers.model.clone(), diff --git a/dpd/src/switch_identifiers.rs b/dpd/src/switch_identifiers.rs index 6203fcd..20ffdc1 100644 --- a/dpd/src/switch_identifiers.rs +++ b/dpd/src/switch_identifiers.rs @@ -84,6 +84,7 @@ pub(crate) async fn fetch_switch_identifiers_loop( asic_backend: sidecar_idents.asic_backend().to_string(), fab: sidecar_idents.fab(), lot: sidecar_idents.lot(), + lotnum: sidecar_idents.lotnum(), wafer: sidecar_idents.wafer(), wafer_loc: sidecar_idents.wafer_loc().map(|(x, y)| [x, y]), model: sp.model, @@ -107,10 +108,12 @@ pub(crate) async fn fetch_switch_identifiers_loop( ) .await .expect("infinite retry loop fetching switch identifiers"); + let chip_id = sidecar_id.as_u128() as u64; info!( log, "fetched switch identifiers from MGS"; "identifiers" => ?idents, + "chip_id" => format!("{chip_id:x}"), ); Ok(idents) diff --git a/swadm/Cargo.toml b/swadm/Cargo.toml index beeaa60..bc14da0 100644 --- a/swadm/Cargo.toml +++ b/swadm/Cargo.toml @@ -18,3 +18,4 @@ oxnet.workspace = true slog.workspace = true tabwriter.workspace = true tokio.workspace = true +tofino.workspace = true diff --git a/swadm/src/main.rs b/swadm/src/main.rs index 2a20f05..59f7c38 100644 --- a/swadm/src/main.rs +++ b/swadm/src/main.rs @@ -91,6 +91,7 @@ enum Commands { #[command(subcommand)] cmd: compliance::Compliance, }, + Identifiers, } // A LinkPath or "loopback", used when either is appropriate. @@ -231,5 +232,20 @@ async fn main_impl() -> anyhow::Result<()> { Commands::Compliance { cmd: compliance } => { compliance::compliance_cmd(&client, compliance).await } + Commands::Identifiers => identifiers(), } } + +fn identifiers() -> anyhow::Result<()> { + /* + let t = tofino::get_tofino().unwrap().unwrap(); + let pci = t.open_pci().unwrap(); + */ + let pci = + tofino::pci::Pci::new("/dev/tofino/1", tofino::REGISTER_SIZE).unwrap(); + let fuse = tofino::fuse::Fuse::read(&pci).unwrap(); + let chip_id: tofino::fuse::ChipId = fuse.chip_id.into(); + println!("chip id: {:016x}", fuse.chip_id); + println!("{}", chip_id); + Ok(()) +} From 80b6b2972d4ae0ee455a81b20ddd603fc1fc6044 Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Fri, 30 Jan 2026 22:36:19 +0000 Subject: [PATCH 3/4] doc on ras registers --- docs/ras-registers.md | 73 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 docs/ras-registers.md diff --git a/docs/ras-registers.md b/docs/ras-registers.md new file mode 100644 index 0000000..1339dc4 --- /dev/null +++ b/docs/ras-registers.md @@ -0,0 +1,73 @@ +# RAS Registers + +## Address Calculation + +Base formula + +``` +0x4000000 + pipe*0x1000000 + stage*0x80000 + block_offset + reg_offset +``` + +- Pipes: 0-3 +- Stages: 0-19 +- Tofino2 has 12 SRAM rows per stage (0-11) + +## TCAM Parity Error Latch + +Register: intr_status_mau_tcam_array +Block offset: 0x40800 (tcams) +Register offset: 0x640 + +### All 20 stages, pipe 0 +```bash +for s in $(seq 0 19); do + addr=$(printf "0x%x" $((0x4000000 + s*0x80000 + 0x40800 + 0x640))) + echo "Pipe 0 Stage $s TCAM: $(tftool reg read $addr)" +done +``` + +### All 20 stages, pipe 1 +```bash +for s in $(seq 0 19); do + addr=$(printf "0x%x" $((0x5000000 + s*0x80000 + 0x40800 + 0x640))) + echo "Pipe 1 Stage $s TCAM: $(tftool reg read $addr)" +done +``` + +Bits: 16-bit, one bit per TCAM column pair (8 pairs) + +## SRAM (Unit RAM) ECC Error Latch + +Register: intr_status_mau_unit_ram_row +Block offset: 0x68000 (rams.array) + row*0x1000 +Register offset: 0xF30 + +### Stages 10-12, all 12 rows, pipe 0 +```bash +for s in 10 11 12; do + for r in $(seq 0 11); do + addr=$(printf "0x%x" $((0x4000000 + s*0x80000 + 0x68000 + r*0x1000 + 0xF30))) + echo "Pipe 0 Stage $s Row $r SRAM: $(tftool reg read $addr)" + done +done +``` + +Bits: 24-bit +- Bits 0-11: SBE (single-bit errors) columns 0-11 +- Bits 12-23: MBE (multi-bit errors) columns 0-11 + +## Quick Reference - Key Addresses (Pipe 0) + +``` +┌───────┬─────────────┬───────────────────┐ +│ Stage │ TCAM Status │ SRAM Row 0 Status │ +├───────┼─────────────┼───────────────────┤ +│ 10 │ 0x4540E40 │ 0x4568F30 │ +├───────┼─────────────┼───────────────────┤ +│ 11 │ 0x45C0E40 │ 0x45E8F30 │ +├───────┼─────────────┼───────────────────┤ +│ 12 │ 0x4640E40 │ 0x4668F30 │ +└───────┴─────────────┴───────────────────┘ +``` + +For pipe 1, add 0x1000000 to all addresses. From 03905c27ba748b9f3370b6c82d2594da1d876f27 Mon Sep 17 00:00:00 2001 From: Ryan Goodfellow Date: Fri, 30 Jan 2026 22:49:01 +0000 Subject: [PATCH 4/4] memtest mode, tcam scrub, interrupt plumbing --- .helix/languages.toml | 2 +- Cargo.lock | 1 + asic/src/tofino_asic/bf_wrapper.rs | 6 +- asic/src/tofino_asic/c/bf_wrapper.h | 112 + asic/src/tofino_asic/imported_bf_functions | 12 + asic/src/tofino_asic/interrupt_monitor.rs | 112 + asic/src/tofino_asic/memtest.rs | 182 + asic/src/tofino_asic/mod.rs | 15 +- dpd-api/src/lib.rs | 56 + dpd-types/src/switch_identifiers.rs | 3 + dpd/misc/dpd.xml | 1 + dpd/p4/metadata.p4 | 3 + dpd/p4/sidecar.p4 | 10 +- dpd/src/api_server.rs | 23 + dpd/src/config.rs | 9 + dpd/src/main.rs | 60 +- dpd/src/memtest.rs | 18 + openapi/dpd/dpd-5.0.0-8b201d.json | 10171 +++++++++++++++++++ openapi/dpd/dpd-latest.json | 2 +- swadm/Cargo.toml | 1 + swadm/src/main.rs | 65 +- 21 files changed, 10847 insertions(+), 17 deletions(-) create mode 100644 asic/src/tofino_asic/interrupt_monitor.rs create mode 100644 asic/src/tofino_asic/memtest.rs create mode 100644 dpd/src/memtest.rs create mode 100644 openapi/dpd/dpd-5.0.0-8b201d.json diff --git a/.helix/languages.toml b/.helix/languages.toml index 83ce526..d831603 100644 --- a/.helix/languages.toml +++ b/.helix/languages.toml @@ -4,4 +4,4 @@ name = "rust" # default to tofino_sde, can change this to any other feature such as softnpu # as needed during development but in source control this should probably # remain as tofino_sde -features = [ "tofino_sde" ] +features = [ "tofino_asic" ] diff --git a/Cargo.lock b/Cargo.lock index 189b47f..eb1e668 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6456,6 +6456,7 @@ dependencies = [ "futures", "oxide-tokio-rt", "oxnet", + "reqwest", "slog", "tabwriter", "tofino", diff --git a/asic/src/tofino_asic/bf_wrapper.rs b/asic/src/tofino_asic/bf_wrapper.rs index e7f1e96..9dabcd2 100644 --- a/asic/src/tofino_asic/bf_wrapper.rs +++ b/asic/src/tofino_asic/bf_wrapper.rs @@ -356,6 +356,7 @@ pub fn bf_init( devpath: &Option, p4_dir: &str, sidecar_revision: &str, + skip_p4: bool, ) -> AsicResult { // Initialize the global callback state { @@ -388,7 +389,10 @@ pub fn bf_init( rev.as_ptr(), &mut ctx, ) { - 0 => Box::new(ctx), + 0 => { + ctx.skip_p4 = skip_p4; + Box::new(ctx) + } rval => { return Err(crate::tofino_asic::sde_error( "initializing bf context", diff --git a/asic/src/tofino_asic/c/bf_wrapper.h b/asic/src/tofino_asic/c/bf_wrapper.h index c3fcd44..190aa3f 100644 --- a/asic/src/tofino_asic/c/bf_wrapper.h +++ b/asic/src/tofino_asic/c/bf_wrapper.h @@ -27,6 +27,117 @@ int32_t bfw_init(const char *, bfw_common_t *hdl); int32_t bfw_register(); void bfw_fini(bfw_common_t *hdl); +/* + * Memory test machinery + */ + +typedef enum bf_diag_test_type_ { + BF_DIAG_TEST_TYPE_PIO, + BF_DIAG_TEST_TYPE_DMA, +} bf_diag_test_type_t; + +typedef enum bf_diag_test_pattern_ { + BF_DIAG_TEST_PATTERN_RANDOM, + BF_DIAG_TEST_PATTERN_ZEROES, + BF_DIAG_TEST_PATTERN_ONES, + BF_DIAG_TEST_PATTERN_CHECKERBOARD, + BF_DIAG_TEST_PATTERN_INV_CHECKERBOARD, + BF_DIAG_TEST_PATTERN_PRBS, + BF_DIAG_TEST_PATTERN_USER_DEFINED, +} bf_diag_test_pattern_t; + +typedef struct bf_diag_mem_data_error_ { + uint64_t addr; + uint64_t exp_0; + uint64_t exp_1; + uint64_t data_0; + uint64_t data_1; + uint64_t mask_0; + uint64_t mask_1; +} bf_diag_mem_data_error_t; + +#define BF_DIAG_MEM_MAX_DATA_ERR 400 +typedef struct bf_diag_mem_results_ { + bool overall_success; + bool ind_write_error; + bool ind_read_error; + bool write_list_error; + bool write_block_error; + uint64_t ind_write_error_addr; + uint64_t ind_read_error_addr; + uint32_t num_data_errors; + bf_diag_mem_data_error_t data_error[BF_DIAG_MEM_MAX_DATA_ERR]; + uint32_t num_dma_msgs_sent; + uint32_t num_dma_cmplts_rcvd; +} bf_diag_mem_results_t; + +bf_status_t +bf_diag_mem_test_mau( + bf_dev_id_t dev_id, + bf_diag_test_type_t test_type, + bool quick, + uint32_t pipe_bmp, + bf_diag_test_pattern_t pattern, + uint64_t pattern_data0, + uint64_t pattern_data1 + ); + +bf_status_t +bf_diag_mem_test_result_get( + bf_dev_id_t dev_id, + bf_diag_mem_results_t *results, + bool *pass +); + +pipe_status_t +pipe_mgr_tcam_scrub_timer_set( + bf_dev_id_t dev, + uint32_t msec_timer +); + +uint32_t +pipe_mgr_tcam_scrub_timer_get( + bf_dev_id_t dev +); + +bf_status_t +lld_enable_all_ints( + bf_dev_id_t dev_id, + bf_subdev_id_t subdev_id +); + +bf_status_t +lld_dump_new_ints( + bf_dev_id_t dev_id, + bf_subdev_id_t subdev_id +); + +bf_status_t +lld_int_poll( + bf_dev_id_t dev_id, + bf_subdev_id_t subdev_id, + bool all_ints +); + +bf_status_t +bf_err_interrupt_handling_mode_set( + bf_dev_id_t dev_id, + bool enable +); + +int +lld_write_register( + bf_dev_id_t dev_id, + uint32_t reg, + uint32_t data +); + +bool +pipe_mgr_is_device_locked( + bf_dev_id_t dev_id +); + + /* * The SDE doesn't export this interface, so we define it here, */ @@ -43,4 +154,5 @@ struct driver_version { uint32_t patch; }; + #endif /* BF_WRAPPER_H */ diff --git a/asic/src/tofino_asic/imported_bf_functions b/asic/src/tofino_asic/imported_bf_functions index 54775dd..6b5554c 100644 --- a/asic/src/tofino_asic/imported_bf_functions +++ b/asic/src/tofino_asic/imported_bf_functions @@ -160,3 +160,15 @@ bf_pm_fsm_transition_callback bf_sys_log_callback lld_sku_map_dev_port_id_to_mac_ch + +# memory testing +bf_diag_mem_test_result_get +bf_diag_mem_test_mau +pipe_mgr_tcam_scrub_timer_set +pipe_mgr_tcam_scrub_timer_get +lld_enable_all_ints +lld_dump_new_ints +lld_int_poll +bf_err_interrupt_handling_mode_set +lld_write_register +pipe_mgr_is_device_locked diff --git a/asic/src/tofino_asic/interrupt_monitor.rs b/asic/src/tofino_asic/interrupt_monitor.rs new file mode 100644 index 0000000..f4af2c3 --- /dev/null +++ b/asic/src/tofino_asic/interrupt_monitor.rs @@ -0,0 +1,112 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// 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 2026 Oxide Computer Company + +use std::{thread::sleep, time::Duration}; + +use crate::tofino_asic::{ + BF_INVALID_ARG, BF_SUCCESS, + bf_wrapper::bf_error_str, + genpd::{ + bf_dev_id_t, bf_err_interrupt_handling_mode_set, bf_subdev_id_t, + lld_dump_new_ints, lld_enable_all_ints, lld_int_poll, + pipe_mgr_is_device_locked, pipe_mgr_tcam_scrub_timer_set, + }, +}; +use slog::{Logger, info, warn}; + +const DEV_ID: bf_dev_id_t = 0; +const SUBDEV_ID: bf_subdev_id_t = 0; +const INTERVAL: Duration = Duration::from_secs(5); + +pub fn monitor_interrupts(log: Logger) -> ! { + let log = log.new(slog::o!("unit" => "interrupt monitor")); + info!(log, "starring interrupt monitor"); + + wait_for_unlock(&log); + enable_tcam_scrub(&log); + set_interrupt_handling_mode(&log); + enable_lld_interrupts(&log); + + monitoring_loop(&log) +} + +fn wait_for_unlock(log: &Logger) { + loop { + if unsafe { pipe_mgr_is_device_locked(DEV_ID) } { + warn!(log, "asic is locked, cannot start"); + sleep(INTERVAL); + continue; + } + info!(log, "asic is unlocked starting interrupt monitor"); + break; + } +} + +fn enable_tcam_scrub(log: &Logger) { + loop { + let rc = unsafe { pipe_mgr_tcam_scrub_timer_set(DEV_ID, 5000) }; + if rc == BF_SUCCESS { + info!(log, "tcam scrub set to 5 second interval"); + break; + } + warn!( + log, + "failed to enable tcam scrub"; + "error" => bf_error_str(rc) + ); + sleep(INTERVAL) + } +} + +fn set_interrupt_handling_mode(log: &Logger) { + loop { + let rc = unsafe { bf_err_interrupt_handling_mode_set(DEV_ID, true) }; + if rc == BF_SUCCESS { + info!(log, "interrupt handling mode set"); + break; + } + warn!( + log, + "failed to set interrupt handling mode"; + "error" => bf_error_str(rc) + ); + sleep(INTERVAL); + } +} + +fn enable_lld_interrupts(log: &Logger) { + loop { + let rc = unsafe { lld_enable_all_ints(DEV_ID, SUBDEV_ID) }; + if rc == BF_SUCCESS { + info!(log, "enabled lld interrupts"); + break; + } + warn!( + log, + "failed to enable lld interrupts"; + "error" => bf_error_str(rc) + ); + sleep(INTERVAL); + } +} + +fn monitoring_loop(log: &Logger) -> ! { + loop { + let rc = unsafe { lld_int_poll(DEV_ID, SUBDEV_ID, true) }; + if rc != BF_SUCCESS { + warn!(log, "lld_int_poll: {}", bf_error_str(rc)); + } + + let rc = unsafe { lld_dump_new_ints(DEV_ID, SUBDEV_ID) }; + // BF_INVALID_ARG means interrupts were found and dumped (yes, really) + // BF_SUCCESS means no new interrupts + // Anything else is an actual error + if rc != BF_SUCCESS && rc != BF_INVALID_ARG { + warn!(log, "lld_dump_new_ints: {}", bf_error_str(rc)); + } + sleep(INTERVAL); + } +} diff --git a/asic/src/tofino_asic/memtest.rs b/asic/src/tofino_asic/memtest.rs new file mode 100644 index 0000000..cf80576 --- /dev/null +++ b/asic/src/tofino_asic/memtest.rs @@ -0,0 +1,182 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// 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 2026 Oxide Computer Company + +use crate::tofino_asic::bf_wrapper::{BF_SUCCESS, bf_error_str}; +use crate::tofino_asic::genpd::{ + bf_diag_mem_data_error_t, bf_diag_mem_results_t, bf_diag_mem_test_mau, + bf_diag_mem_test_result_get, bf_diag_test_type__BF_DIAG_TEST_TYPE_PIO, + bf_err_interrupt_handling_mode_set, lld_dump_new_ints, lld_enable_all_ints, + lld_int_poll, pipe_mgr_is_device_locked, pipe_mgr_tcam_scrub_timer_get, + pipe_mgr_tcam_scrub_timer_set, +}; +use anyhow::{Result, anyhow}; +use dpd_api::{ + TofinoMemoryErrorDiagnostic, TofinoMemoryTestPattern, TofinoMemtestResult, +}; +use slog::{Logger, info, warn}; + +pub fn run_memtest( + pattern: TofinoMemoryTestPattern, + log: &Logger, +) -> Result { + unsafe { + let locked = pipe_mgr_is_device_locked(0); + if locked { + return Err(anyhow!("cannot run memtest while device is locked")); + } + + let scrub_timer = pipe_mgr_tcam_scrub_timer_get(0); + info!(log, "scrub timer was {scrub_timer}ms prior to test"); + + let rc = lld_enable_all_ints(0, 0); + if rc != BF_SUCCESS { + return Err(anyhow!("lld_enable_all_ints: {}", bf_error_str(rc))); + } + + let rc = bf_err_interrupt_handling_mode_set(0, true); + if rc != BF_SUCCESS { + return Err(anyhow!( + "bf_err_interrupt_handling_mode_set true: {}", + bf_error_str(rc) + )); + } + + let rc = pipe_mgr_tcam_scrub_timer_set(0, 0); + if rc != BF_SUCCESS { + return Err(anyhow!( + "pipe_mgr_tcam_scrub_timer_set: {}", + bf_error_str(rc) + )); + } + let rc = bf_diag_mem_test_mau( + 0, + bf_diag_test_type__BF_DIAG_TEST_TYPE_PIO, + false, + 0xF, // all pipes 4 pipes + pattern as u32, + 0x0, + 0x0, + ); + if rc != BF_SUCCESS { + warn!(log, "bf_diag_mem_test_mau: {}", bf_error_str(rc)); + } + + let mut result = bf_diag_mem_results_t { + overall_success: false, + ind_write_error: false, + ind_read_error: false, + write_list_error: false, + write_block_error: false, + ind_write_error_addr: 0, + ind_read_error_addr: 0, + num_data_errors: 0, + data_error: [bf_diag_mem_data_error_t { + addr: 0, + exp_0: 0, + exp_1: 0, + data_0: 0, + data_1: 0, + mask_0: 0, + mask_1: 0, + }; 400], + num_dma_msgs_sent: 0, + num_dma_cmplts_rcvd: 0, + }; + let mut pass = false; + let rc = bf_diag_mem_test_result_get( + 0, + &mut result as *mut bf_diag_mem_results_t, + &mut pass as *mut bool, + ); + if rc != BF_SUCCESS { + return Err(anyhow!( + "bf_diag_mem_test_result_get: {}", + bf_error_str(rc) + )); + } + + let rc = lld_int_poll(0, 0, true); + if rc != BF_SUCCESS { + warn!(log, "lld_int_poll: {}", bf_error_str(rc)); + } + + let rc = lld_dump_new_ints(0, 0); + if rc != BF_SUCCESS { + warn!(log, "lld_dump_new_ints: {}", bf_error_str(rc)); + } + + /* + let rc = bf_err_interrupt_handling_mode_set(0, false); + if rc != BF_SUCCESS { + warn!( + log, + "bf_err_interrupt_handling_mode_set false: {}", + bf_error_str(rc) + ); + } + */ + + let rc = pipe_mgr_tcam_scrub_timer_set(0, 800); + if rc != BF_SUCCESS { + return Err(anyhow!( + "pipe_mgr_tcam_scrub_timer_set: (100) {}", + bf_error_str(rc) + )); + } + + for _ in 0..20 { + info!(log, "checking for tcam errors"); + std::thread::sleep(std::time::Duration::from_secs(1)); + let rc = lld_int_poll(0, 0, true); + if rc != BF_SUCCESS { + warn!(log, "lld_int_poll: {}", bf_error_str(rc)); + } + + let rc = lld_dump_new_ints(0, 0); + if rc != BF_SUCCESS { + warn!(log, "lld_dump_new_ints: {}", bf_error_str(rc)); + } + } + + Ok(result) + } +} + +impl From for TofinoMemoryErrorDiagnostic { + fn from(value: bf_diag_mem_data_error_t) -> Self { + Self { + addr: value.addr, + exp_0: value.exp_0, + exp_1: value.exp_1, + data_0: value.data_0, + data_1: value.data_1, + mask_0: value.mask_0, + mask_1: value.mask_1, + } + } +} + +impl From for TofinoMemtestResult { + fn from(value: bf_diag_mem_results_t) -> Self { + Self { + overall_success: value.overall_success, + ind_write_error: value.ind_write_error, + ind_read_error: value.ind_read_error, + write_list_error: value.write_list_error, + write_block_error: value.write_block_error, + ind_write_error_addr: value.ind_write_error_addr, + ind_read_error_addr: value.ind_read_error_addr, + num_data_errors: value.num_data_errors, + data_error: value.data_error[..value.num_data_errors as usize] + .to_vec() + .into_iter() + .map(TofinoMemoryErrorDiagnostic::from) + .collect(), + num_dma_msgs_sent: value.num_dma_msgs_sent, + num_dma_cmplts_rcvd: value.num_dma_cmplts_rcvd, + } + } +} diff --git a/asic/src/tofino_asic/mod.rs b/asic/src/tofino_asic/mod.rs index 58e5355..b2b1e62 100644 --- a/asic/src/tofino_asic/mod.rs +++ b/asic/src/tofino_asic/mod.rs @@ -18,8 +18,10 @@ use common::ports::*; mod bf_wrapper; mod genpd; +pub mod interrupt_monitor; mod link_fsm; pub mod mcast; +pub mod memtest; pub mod ports; pub mod qsfp; mod sde_log; @@ -59,11 +61,21 @@ pub struct AsicConfig { /// /// The default value is "B". pub board_rev: String, + + /// Skip loading P4 program. + /// + /// Used for memory testing. + pub skip_p4: bool, } impl Default for AsicConfig { fn default() -> Self { - Self { devpath: None, xcvr_iface: None, board_rev: String::from("B") } + Self { + devpath: None, + xcvr_iface: None, + board_rev: String::from("B"), + skip_p4: false, + } } } @@ -334,6 +346,7 @@ impl Handle { &config.devpath, &p4_dir, &config.board_rev, + config.skip_p4, )?; let rt = tofino_common::BfRt::init(&p4_dir)?; let domains = Mutex::new(HashMap::new()); diff --git a/dpd-api/src/lib.rs b/dpd-api/src/lib.rs index c158421..d2aba47 100644 --- a/dpd-api/src/lib.rs +++ b/dpd-api/src/lib.rs @@ -59,6 +59,7 @@ api_versions!([ // | example for the next person. // v // (next_int, IDENT), + (5, MEMTEST), (4, V4_OVER_V6_ROUTES), (3, ATTACHED_SUBNETS), (2, DUAL_STACK_NAT_WORKFLOW), @@ -1984,6 +1985,19 @@ pub trait DpdApi { rqctx: RequestContext, path: Path, ) -> Result, HttpError>; + + /** + * Run a memory test on the ASIC + */ + #[endpoint { + method = GET, + path = "/memtest", + versions = VERSION_MEMTEST.. + }] + async fn memtest( + rqctx: RequestContext, + args: TypedBody, + ) -> Result, HttpError>; } /// Parameter used to create a port. @@ -2720,3 +2734,45 @@ pub struct Ber { /// Aggregate BER on the link. pub total_ber: f32, } + +#[derive(Clone, Deserialize, JsonSchema, PartialEq, Serialize)] +pub struct TofinoMemtestResult { + pub overall_success: bool, + pub ind_write_error: bool, + pub ind_read_error: bool, + pub write_list_error: bool, + pub write_block_error: bool, + pub ind_write_error_addr: u64, + pub ind_read_error_addr: u64, + pub num_data_errors: u32, + pub data_error: Vec, + pub num_dma_msgs_sent: u32, + pub num_dma_cmplts_rcvd: u32, +} + +#[derive(Clone, Deserialize, JsonSchema, PartialEq, Serialize)] +pub struct TofinoMemoryErrorDiagnostic { + pub addr: u64, + pub exp_0: u64, + pub exp_1: u64, + pub data_0: u64, + pub data_1: u64, + pub mask_0: u64, + pub mask_1: u64, +} + +#[derive(Copy, Clone, Deserialize, JsonSchema, PartialEq, Serialize)] +#[repr(u32)] +pub enum TofinoMemoryTestPattern { + Random, + Zeroes, + Ones, + Checkerboard, + InverseCheckerboard, + Prbs, +} + +#[derive(Copy, Clone, Deserialize, JsonSchema, PartialEq, Serialize)] +pub struct TofinoMemoryTestArgs { + pub pattern: TofinoMemoryTestPattern, +} diff --git a/dpd-types/src/switch_identifiers.rs b/dpd-types/src/switch_identifiers.rs index 0d86a5e..8a7dec8 100644 --- a/dpd-types/src/switch_identifiers.rs +++ b/dpd-types/src/switch_identifiers.rs @@ -19,7 +19,10 @@ pub struct SwitchIdentifiers { pub fab: Option, /// Lot identifier. pub lot: Option, + // TODO add to API /// Lot number + #[serde(skip)] + #[schemars(skip)] pub lotnum: Option<[char; 4]>, /// Wafer number within the lot. pub wafer: Option, diff --git a/dpd/misc/dpd.xml b/dpd/misc/dpd.xml index b8996c4..c3f58e2 100644 --- a/dpd/misc/dpd.xml +++ b/dpd/misc/dpd.xml @@ -57,6 +57,7 @@ + diff --git a/dpd/p4/metadata.p4 b/dpd/p4/metadata.p4 index 3656ec2..dd1db6d 100644 --- a/dpd/p4/metadata.p4 +++ b/dpd/p4/metadata.p4 @@ -12,6 +12,9 @@ header bridge_h { PortId_t ingress_port; } +@pa_no_overlay("ingress", "meta.nat_egress_hit") +@pa_no_overlay("ingress", "meta.nat_ingress_hit") + struct sidecar_ingress_meta_t { bool dropped; // has packet been dropped bool ipv4_checksum_err; // failed ipv4 checksum diff --git a/dpd/p4/sidecar.p4 b/dpd/p4/sidecar.p4 index ed38d5a..03426bc 100644 --- a/dpd/p4/sidecar.p4 +++ b/dpd/p4/sidecar.p4 @@ -409,8 +409,10 @@ control Services( meta.drop_reason = DROP_NAT_INGRESS_MISS; meta.dropped = true; } - else if (meta.is_switch_address && hdr.geneve.isValid() && hdr.geneve.vni != 0) { - meta.nat_egress_hit = true; + else if (meta.is_switch_address && hdr.geneve.isValid()) { + if (hdr.geneve.vni != 0) { + meta.nat_egress_hit = true; + } } else { service.apply(); @@ -1481,13 +1483,13 @@ control L3Router( ) { apply { if (hdr.ipv4.isValid()) { - if (meta.is_mcast && !meta.is_link_local_mcastv6) { + if (meta.is_mcast && !meta.is_link_local_mcastv6) { // sus MulticastRouter4.apply(hdr, meta, ig_intr_md, ig_tm_md); } else { Router4.apply(hdr, meta, ig_intr_md, ig_tm_md); } } else if (hdr.ipv6.isValid()) { - if (meta.is_mcast && !meta.is_link_local_mcastv6) { + if (meta.is_mcast && !meta.is_link_local_mcastv6) { // sus MulticastRouter6.apply(hdr, meta, ig_intr_md, ig_tm_md); } else { Router6.apply(hdr, meta, ig_intr_md, ig_tm_md); diff --git a/dpd/src/api_server.rs b/dpd/src/api_server.rs index 4917f4d..7101346 100644 --- a/dpd/src/api_server.rs +++ b/dpd/src/api_server.rs @@ -2620,6 +2620,29 @@ impl DpdApi for DpdApiImpl { "not implemented for this asic".to_string(), )) } + + #[cfg(feature = "tofino_asic")] + async fn memtest( + rqctx: RequestContext, + args: TypedBody, + ) -> Result, HttpError> { + let switch: &Switch = rqctx.context(); + let result = crate::memtest::memtest(switch, args.into_inner().pattern) + .map_err(|e| { + HttpError::for_internal_error(format!("memtest error: {e}")) + })?; + Ok(HttpResponseOk(result)) + } + + #[cfg(not(feature = "tofino_asic"))] + async fn memtest( + rqctx: RequestContext, + ) -> Result, HttpError> { + Err(HttpError::for_unavail( + None, + "not implemented for this asic".to_string(), + )) + } } // Convert a port ID path into a `QsfpPort` if possible. This is generally used diff --git a/dpd/src/config.rs b/dpd/src/config.rs index 06d5507..0c17790 100644 --- a/dpd/src/config.rs +++ b/dpd/src/config.rs @@ -221,6 +221,15 @@ pub(crate) fn update_from_smf(config: &mut Config) -> SmfResult<()> { if let Some(rev) = smf::get_property(&snapshot, "board_rev")? { config.asic_config.board_rev = rev; } + if let Some(skip_p4) = smf::get_property(&snapshot, "skip_p4")? { + let Ok(value) = skip_p4.parse() else { + return Err(SmfError::InvalidProperty( + skip_p4.clone(), + "expected 'true' or 'false'".to_owned(), + )); + }; + config.asic_config.skip_p4 = value; + } } #[cfg(feature = "softnpu")] diff --git a/dpd/src/main.rs b/dpd/src/main.rs index 635d8e4..5793450 100644 --- a/dpd/src/main.rs +++ b/dpd/src/main.rs @@ -28,9 +28,11 @@ use signal_hook::consts::SIGQUIT; use signal_hook::consts::SIGTERM; use signal_hook::consts::SIGUSR1; use signal_hook_tokio::Signals; +use slog::Logger; use slog::debug; use slog::error; use slog::info; +use slog::warn; use tokio::sync::Mutex as TokioMutex; use tokio::time::Duration; use tokio::time::sleep; @@ -63,6 +65,8 @@ mod link; mod loopback; mod macaddrs; mod mcast; +#[cfg(feature = "tofino_asic")] +mod memtest; mod nat; mod oxstats; mod port_map; @@ -271,8 +275,12 @@ impl Switch { &config.xcvr_defaults, )?; - let counters = counters::init(&asic_hdl) - .context("failed to initialize counters")?; + let counters = if !config.asic_config.skip_p4 { + counters::init(&asic_hdl) + .context("failed to initialize counters")? + } else { + BTreeMap::new() + }; #[cfg(feature = "tofino_asic")] let transceivers = TransceiverState::new( @@ -282,6 +290,8 @@ impl Switch { let route_data = route::init(&log); let mac_mgmt = Mutex::new(macaddrs::MacManagement::new(&log)); + run_interrupt_monitor(log.clone()); + let ws_log = log.new(slog::o!("unit" => "workflow_server")); let workflow_server = rpw::WorkflowServer::new(ws_log); @@ -566,6 +576,30 @@ async fn stub_main(switch: Switch) -> anyhow::Result<()> { Ok(()) } +async fn diag_main(switch: Switch) -> anyhow::Result<()> { + let switch = Arc::new(switch); + let (smf_tx, smf_rx) = tokio::sync::watch::channel(()); + + let api_server_manager = tokio::task::spawn( + api_server::api_server_manager(switch.clone(), smf_rx.clone()), + ); + + const SIGNALS: &[c_int] = &[SIGTERM, SIGQUIT, SIGINT, SIGHUP, SIGUSR1]; + let signals = Signals::new(SIGNALS).unwrap(); + handle_signals(&switch, signals, smf_tx).await; + + api_server_manager + .await + .expect("while shutting down the api_server_manager"); + + info!(switch.log, "shutting down switch driver"); + switch.asic_hdl.fini(); + + info!(switch.log, "done"); + + Ok(()) +} + // Initialize the QSFP platform subsystem, for the BF SDE to manage the // front IO ports. // @@ -792,18 +826,36 @@ fn main() -> anyhow::Result<()> { async fn run_dpd(opt: Opt) -> anyhow::Result<()> { let config = config::build_config(&opt)?; + let skip_p4 = config.asic_config.skip_p4; let log = common::logging::init("dpd", &config.log_file, config.log_format)?; info!(log, "dpd config: {config:#?}"); + if config.asic_config.skip_p4 { + warn!(log, "running in diagnostic mode, no P4 program will be loaded"); + } + let p4_name = std::env::var("P4_NAME").unwrap_or_else(|_| String::from("sidecar")); + info!(log, "p4 program: {p4_name}"); + let switch = Switch::new(log, &p4_name, config)?; + if p4_name == "sidecar" { - sidecar_main(switch).await + if skip_p4 { + diag_main(switch).await + } else { + sidecar_main(switch).await + } } else { - info!(switch.log, "running as stub to support p4 program: {p4_name}"); + info!(switch.log, "running as stub"); stub_main(switch).await } } + +fn run_interrupt_monitor(log: Logger) { + std::thread::spawn(move || { + asic::tofino_asic::interrupt_monitor::monitor_interrupts(log); + }); +} diff --git a/dpd/src/memtest.rs b/dpd/src/memtest.rs new file mode 100644 index 0000000..8933624 --- /dev/null +++ b/dpd/src/memtest.rs @@ -0,0 +1,18 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// 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 2026 Oxide Computer Company + +use crate::Switch; +use asic::tofino_asic::memtest::run_memtest; +use dpd_api::{TofinoMemoryTestPattern, TofinoMemtestResult}; +use slog::info; + +pub fn memtest( + switch: &Switch, + pattern: TofinoMemoryTestPattern, +) -> anyhow::Result { + info!(switch.log, "running memtest"); + Ok(run_memtest(pattern, &switch.log)?.into()) +} diff --git a/openapi/dpd/dpd-5.0.0-8b201d.json b/openapi/dpd/dpd-5.0.0-8b201d.json new file mode 100644 index 0000000..8c62795 --- /dev/null +++ b/openapi/dpd/dpd-5.0.0-8b201d.json @@ -0,0 +1,10171 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Oxide Switch Dataplane Controller", + "description": "API for managing the Oxide rack switch", + "contact": { + "url": "https://oxide.computer", + "email": "api@oxide.computer" + }, + "version": "5.0.0" + }, + "paths": { + "/all-settings": { + "delete": { + "summary": "Clear all settings.", + "description": "This removes all data entirely.", + "operationId": "reset_all", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/all-settings/{tag}": { + "delete": { + "summary": "Clear all settings associated with a specific tag.", + "description": "This removes:\n\n- All ARP or NDP table entries. - All routes - All links on all switch ports", + "operationId": "reset_all_tagged", + "parameters": [ + { + "in": "path", + "name": "tag", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/arp": { + "get": { + "summary": "Fetch the configured IPv4 ARP table entries.", + "operationId": "arp_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntryResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "post": { + "summary": "Add an IPv4 ARP table entry, mapping an IPv4 address to a MAC address.", + "operationId": "arp_create", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove all entries in the IPv4 ARP tables.", + "operationId": "arp_reset", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/arp/{ip}": { + "get": { + "summary": "Get a single IPv4 ARP table entry, by its IPv4 address.", + "operationId": "arp_get", + "parameters": [ + { + "in": "path", + "name": "ip", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntry" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove a single IPv4 ARP entry, by its IPv4 address.", + "operationId": "arp_delete", + "parameters": [ + { + "in": "path", + "name": "ip", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/attached_subnet": { + "get": { + "summary": "Get all of the external subnets with internal mappings", + "operationId": "attached_subnet_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AttachedSubnetEntryResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "delete": { + "summary": "Clear all external subnet mappings", + "operationId": "attached_subnet_reset", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/attached_subnet/{subnet}": { + "get": { + "summary": "Get the mapping for the given external subnet.", + "operationId": "attached_subnet_get", + "parameters": [ + { + "in": "path", + "name": "subnet", + "description": "The external subnet in CIDR notation being managed", + "required": true, + "schema": { + "$ref": "#/components/schemas/IpNet" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstanceTarget" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Add a mapping to an internal target for an external subnet address.", + "description": "These identify the gimlet on which a guest is running, and gives OPTE the information it needs to identify the guest VM that uses the external subnet.", + "operationId": "attached_subnet_create", + "parameters": [ + { + "in": "path", + "name": "subnet", + "description": "The external subnet in CIDR notation being managed", + "required": true, + "schema": { + "$ref": "#/components/schemas/IpNet" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstanceTarget" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Delete the mapping for an external subnet", + "operationId": "attached_subnet_delete", + "parameters": [ + { + "in": "path", + "name": "subnet", + "description": "The external subnet in CIDR notation being managed", + "required": true, + "schema": { + "$ref": "#/components/schemas/IpNet" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/backplane-map": { + "get": { + "summary": "Return the full backplane map.", + "description": "This returns the entire mapping of all cubbies in a rack, through the cabled backplane, and into the Sidecar main board. It also includes the Tofino \"connector\", which is included in some contexts such as reporting counters.", + "operationId": "backplane_map", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Map_of_BackplaneLink", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/BackplaneLink" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/backplane-map/{port_id}": { + "get": { + "summary": "Return the backplane mapping for a single switch port.", + "operationId": "port_backplane_link", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackplaneLink" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/build-info": { + "get": { + "summary": "Return detailed build information about the `dpd` server itself.", + "operationId": "build_info", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildInfo" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/channels": { + "get": { + "summary": "Get the set of available channels for all ports.", + "description": "This returns the unused MAC channels for each physical switch port. This can be used to determine how many additional links can be crated on a physical switch port.", + "operationId": "channels_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_FreeChannels", + "type": "array", + "items": { + "$ref": "#/components/schemas/FreeChannels" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/fec": { + "get": { + "summary": "Get the FEC RS counters for all links.", + "operationId": "fec_rs_counters_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_LinkFecRSCounters", + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkFecRSCounters" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/fec/{port_id}/{link_id}": { + "get": { + "summary": "Get the FEC RS counters for the given link.", + "operationId": "fec_rs_counters_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkFecRSCounters" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/fsm/{port_id}/{link_id}": { + "get": { + "summary": "Get the autonegotiation FSM counters for the given link.", + "operationId": "link_fsm_counters_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkFsmCounters" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/linkup": { + "get": { + "summary": "Get the LinkUp counters for all links.", + "operationId": "link_up_counters_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_LinkUpCounter", + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkUpCounter" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/linkup/{port_id}/{link_id}": { + "get": { + "summary": "Get the LinkUp counters for the given link.", + "operationId": "link_up_counters_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkUpCounter" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/p4": { + "get": { + "summary": "Get a list of all the available p4-defined counters.", + "operationId": "counter_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_String", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/p4/{counter}": { + "get": { + "summary": "Get the values for a given counter.", + "description": "The name of the counter should match one of those returned by the `counter_list()` call.", + "operationId": "counter_get", + "parameters": [ + { + "in": "query", + "name": "force_sync", + "description": "Force a sync of the counters from the ASIC to memory, even if the default refresh timeout hasn't been reached.", + "required": true, + "schema": { + "type": "boolean" + } + }, + { + "in": "path", + "name": "counter", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_TableCounterEntry", + "type": "array", + "items": { + "$ref": "#/components/schemas/TableCounterEntry" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/p4/{counter}/reset": { + "post": { + "summary": "Reset a single p4-defined counter.", + "description": "The name of the counter should match one of those returned by the `counter_list()` call.", + "operationId": "counter_reset", + "parameters": [ + { + "in": "path", + "name": "counter", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/pcs": { + "get": { + "summary": "Get the physical coding sublayer (PCS) counters for all links.", + "operationId": "pcs_counters_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_LinkPcsCounters", + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkPcsCounters" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/pcs/{port_id}/{link_id}": { + "get": { + "summary": "Get the Physical Coding Sublayer (PCS) counters for the given link.", + "operationId": "pcs_counters_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkPcsCounters" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/rmon/{port_id}/{link_id}/all": { + "get": { + "summary": "Get the full set of traffic counters for the given link.", + "operationId": "rmon_counters_get_all", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkRMonCountersAll" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/counters/rmon/{port_id}/{link_id}/subset": { + "get": { + "summary": "Get the most relevant subset of traffic counters for the given link.", + "operationId": "rmon_counters_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkRMonCounters" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/dpd-uptime": { + "get": { + "summary": "Return the server uptime.", + "operationId": "dpd_uptime", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "int64", + "type": "integer", + "format": "int64" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/dpd-version": { + "get": { + "summary": "Return the version of the `dpd` server itself.", + "operationId": "dpd_version", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "String", + "type": "string" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/leds": { + "get": { + "summary": "Return the state of all attention LEDs on the Sidecar QSFP ports.", + "operationId": "leds_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Map_of_Led", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Led" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/links": { + "get": { + "summary": "List all links, on all switch ports.", + "operationId": "link_list_all", + "parameters": [ + { + "in": "query", + "name": "filter", + "description": "Filter links to those whose name contains the provided string.\n\nIf not provided, then all links are returned.", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Link", + "type": "array", + "items": { + "$ref": "#/components/schemas/Link" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/links/tfport_data": { + "get": { + "summary": "Collect the link data consumed by `tfportd`. This app-specific convenience", + "description": "routine is meant to reduce the time and traffic expended on this once-per-second operation, by consolidating multiple per-link requests into a single per-switch request.", + "operationId": "tfport_data", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_TfportData", + "type": "array", + "items": { + "$ref": "#/components/schemas/TfportData" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/loopback/ipv4": { + "get": { + "summary": "Get loopback IPv4 addresses.", + "operationId": "loopback_ipv4_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Ipv4Entry", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv4Entry" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Add a loopback IPv4.", + "operationId": "loopback_ipv4_create", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4Entry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/loopback/ipv4/{ipv4}": { + "delete": { + "summary": "Remove one loopback IPv4 address.", + "operationId": "loopback_ipv4_delete", + "parameters": [ + { + "in": "path", + "name": "ipv4", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/loopback/ipv6": { + "get": { + "summary": "Get loopback IPv6 addresses.", + "operationId": "loopback_ipv6_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Ipv6Entry", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Entry" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Add a loopback IPv6.", + "operationId": "loopback_ipv6_create", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6Entry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/loopback/ipv6/{ipv6}": { + "delete": { + "summary": "Remove one loopback IPv6 address.", + "operationId": "loopback_ipv6_delete", + "parameters": [ + { + "in": "path", + "name": "ipv6", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/memtest": { + "get": { + "summary": "Run a memory test on the ASIC", + "operationId": "memtest", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TofinoMemoryTestArgs" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TofinoMemtestResult" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/external-groups": { + "post": { + "summary": "Create an external-only multicast group configuration.", + "description": "External-only groups are used for IPv4 and non-admin-scoped IPv6 multicast traffic that doesn't require replication infrastructure. These groups use simple forwarding tables and require a NAT target.", + "operationId": "multicast_group_create_external", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupCreateExternalEntry" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupExternalResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/external-groups/{group_ip}": { + "put": { + "summary": "Update an external-only multicast group configuration for a given group IP address.", + "description": "External-only groups are used for IPv4 and non-admin-scoped IPv6 multicast traffic that doesn't require replication infrastructure.", + "operationId": "multicast_group_update_external", + "parameters": [ + { + "in": "path", + "name": "group_ip", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupUpdateExternalEntry" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupExternalResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/groups": { + "get": { + "summary": "List all multicast groups.", + "operationId": "multicast_groups_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupResponseResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "delete": { + "summary": "Reset all multicast group configurations.", + "operationId": "multicast_reset", + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/groups/{group_ip}": { + "get": { + "summary": "Get the multicast group configuration for a given group IP address.", + "operationId": "multicast_group_get", + "parameters": [ + { + "in": "path", + "name": "group_ip", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Delete a multicast group configuration by IP address.", + "operationId": "multicast_group_delete", + "parameters": [ + { + "in": "path", + "name": "group_ip", + "required": true, + "schema": { + "type": "string", + "format": "ip" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/tags/{tag}": { + "get": { + "summary": "List all multicast groups with a given tag.", + "operationId": "multicast_groups_list_by_tag", + "parameters": [ + { + "in": "path", + "name": "tag", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupResponseResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "delete": { + "summary": "Delete all multicast groups (and associated routes) with a given tag.", + "operationId": "multicast_reset_by_tag", + "parameters": [ + { + "in": "path", + "name": "tag", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/underlay-groups": { + "post": { + "summary": "Create an underlay (internal) multicast group configuration.", + "description": "Underlay groups are used for admin-scoped IPv6 multicast traffic that requires replication infrastructure. These groups support both external and underlay members with full replication capabilities.", + "operationId": "multicast_group_create_underlay", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupCreateUnderlayEntry" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupUnderlayResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/underlay-groups/{group_ip}": { + "get": { + "summary": "Get an underlay (internal) multicast group configuration by admin-scoped", + "description": "IPv6 address.\n\nUnderlay groups handle admin-scoped IPv6 multicast traffic with replication infrastructure for external and underlay members.", + "operationId": "multicast_group_get_underlay", + "parameters": [ + { + "in": "path", + "name": "group_ip", + "required": true, + "schema": { + "$ref": "#/components/schemas/AdminScopedIpv6" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupUnderlayResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Update an underlay (internal) multicast group configuration for a given", + "description": "group IP address.\n\nUnderlay groups are used for admin-scoped IPv6 multicast traffic that requires replication infrastructure with external and underlay members.", + "operationId": "multicast_group_update_underlay", + "parameters": [ + { + "in": "path", + "name": "group_ip", + "required": true, + "schema": { + "$ref": "#/components/schemas/AdminScopedIpv6" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupUpdateUnderlayEntry" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MulticastGroupUnderlayResponse" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/multicast/untagged": { + "delete": { + "summary": "Delete all multicast groups (and associated routes) without a tag.", + "operationId": "multicast_reset_untagged", + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv4": { + "get": { + "summary": "Get all of the external addresses in use for IPv4 NAT mappings.", + "operationId": "nat_ipv4_addresses_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ipv4ResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "delete": { + "summary": "Clear all IPv4 NAT mappings.", + "operationId": "nat_ipv4_reset", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv4/{ipv4}": { + "get": { + "summary": "Get all of the external->internal NAT mappings for a given IPv4 address.", + "operationId": "nat_ipv4_list", + "parameters": [ + { + "in": "path", + "name": "ipv4", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + }, + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4NatResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + } + }, + "/nat/ipv4/{ipv4}/{low}": { + "get": { + "summary": "Get the external->internal NAT mapping for the given address/port", + "operationId": "nat_ipv4_get", + "parameters": [ + { + "in": "path", + "name": "ipv4", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NatTarget" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Clear the NAT mappings for an IPv4 address and starting L3 port.", + "operationId": "nat_ipv4_delete", + "parameters": [ + { + "in": "path", + "name": "ipv4", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv4/{ipv4}/{low}/{high}": { + "put": { + "summary": "Add an external->internal NAT mapping for the given address/port range", + "description": "This maps an external IPv6 address and L3 port range to: - A gimlet's IPv6 address - A gimlet's MAC address - A Geneve VNI\n\nThese identify the gimlet on which a guest is running, and gives OPTE the information it needs to identify the guest VM that uses the external IPv6 and port range when making connections outside of an Oxide rack.", + "operationId": "nat_ipv4_create", + "parameters": [ + { + "in": "path", + "name": "high", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + { + "in": "path", + "name": "ipv4", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NatTarget" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv6": { + "get": { + "summary": "Get all of the external addresses in use for NAT mappings.", + "operationId": "nat_ipv6_addresses_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ipv6ResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "delete": { + "summary": "Clear all IPv6 NAT mappings.", + "operationId": "nat_ipv6_reset", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv6/{ipv6}": { + "get": { + "summary": "Get all of the external->internal NAT mappings for a given address.", + "operationId": "nat_ipv6_list", + "parameters": [ + { + "in": "path", + "name": "ipv6", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + }, + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6NatResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + } + }, + "/nat/ipv6/{ipv6}/{low}": { + "get": { + "summary": "Get the external->internal NAT mapping for the given address and starting L3", + "description": "port.", + "operationId": "nat_ipv6_get", + "parameters": [ + { + "in": "path", + "name": "ipv6", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NatTarget" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Delete the NAT mapping for an IPv6 address and starting L3 port.", + "operationId": "nat_ipv6_delete", + "parameters": [ + { + "in": "path", + "name": "ipv6", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/nat/ipv6/{ipv6}/{low}/{high}": { + "put": { + "summary": "Add an external->internal NAT mapping for the given address and L3 port", + "description": "range.\n\nThis maps an external IPv6 address and L3 port range to: - A gimlet's IPv6 address - A gimlet's MAC address - A Geneve VNI\n\nThese identify the gimlet on which a guest is running, and gives OPTE the information it needs to identify the guest VM that uses the external IPv6 and port range when making connections outside of an Oxide rack.", + "operationId": "nat_ipv6_create", + "parameters": [ + { + "in": "path", + "name": "high", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + { + "in": "path", + "name": "ipv6", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + }, + { + "in": "path", + "name": "low", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NatTarget" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ndp": { + "get": { + "summary": "Fetch the IPv6 NDP table entries.", + "description": "This returns a paginated list of all IPv6 neighbors directly connected to the switch.", + "operationId": "ndp_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntryResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "post": { + "summary": "Add an IPv6 NDP entry, mapping an IPv6 address to a MAC address.", + "operationId": "ndp_create", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove all entries in the the IPv6 NDP tables.", + "operationId": "ndp_reset", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ndp/{ip}": { + "get": { + "summary": "Get a single IPv6 NDP table entry, by its IPv6 address.", + "operationId": "ndp_get", + "parameters": [ + { + "in": "path", + "name": "ip", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArpEntry" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove an IPv6 NDP entry, by its IPv6 address.", + "operationId": "ndp_delete", + "parameters": [ + { + "in": "path", + "name": "ip", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/port/{port_id}/settings": { + "get": { + "summary": "Get port settings atomically.", + "operationId": "port_settings_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "query", + "name": "tag", + "description": "Restrict operations on this port to the provided tag.", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortSettings" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Apply port settings atomically.", + "description": "These settings will be applied holistically, and to the extent possible atomically to a given port. In the event of a failure a rollback is attempted. If the rollback fails there will be inconsistent state. This failure mode returns the error code \"rollback failure\". For more details see the docs on the [`PortSettings`] type.", + "operationId": "port_settings_apply", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "query", + "name": "tag", + "description": "Restrict operations on this port to the provided tag.", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortSettings" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortSettings" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Clear port settings atomically.", + "operationId": "port_settings_clear", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "query", + "name": "tag", + "description": "Restrict operations on this port to the provided tag.", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortSettings" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports": { + "get": { + "summary": "List all switch ports on the system.", + "operationId": "port_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_PortId", + "type": "array", + "items": { + "$ref": "#/components/schemas/PortId" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}": { + "get": { + "summary": "Return information about a single switch port.", + "operationId": "port_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SwitchPort" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/led": { + "get": { + "summary": "Return the current state of the attention LED on a front-facing QSFP port.", + "operationId": "led_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Led" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Override the current state of the attention LED on a front-facing QSFP port.", + "description": "The attention LED normally follows the state of the port itself. For example, if a transceiver is powered and operating normally, then the LED is solid on. An unexpected power fault would then be reflected by powering off the LED.\n\nThe client may override this behavior, explicitly setting the LED to a specified state. This can be undone, sending the LED back to its default policy, with the endpoint `/ports/{port_id}/led/auto`.", + "operationId": "led_set", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LedState" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/led/auto": { + "put": { + "summary": "Set the LED policy to automatic.", + "description": "The automatic LED policy ensures that the state of the LED follows the state of the switch port itself.", + "operationId": "led_set_auto", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links": { + "get": { + "summary": "List the links within a single switch port.", + "operationId": "link_list", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Link", + "type": "array", + "items": { + "$ref": "#/components/schemas/Link" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Create a link on a switch port.", + "description": "Create an interface that can be used for sending Ethernet frames on the provided switch port. This will use the first available lanes in the physical port to create an interface of the desired speed, if possible.", + "operationId": "link_create", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkId" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}": { + "get": { + "summary": "Get an existing link by ID.", + "operationId": "link_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Link" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Delete a link from a switch port.", + "operationId": "link_delete", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/autoneg": { + "get": { + "summary": "Return whether the link is configured to use autonegotiation with its peer", + "description": "link.", + "operationId": "link_autoneg_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set whether a port is configured to use autonegotation with its peer link.", + "operationId": "link_autoneg_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ber": { + "get": { + "summary": "Return the estimated bit-error rate (BER) for a link.", + "operationId": "link_ber_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ber" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/enabled": { + "get": { + "summary": "Return whether the link is enabled.", + "operationId": "link_enabled_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Enable or disable a link.", + "operationId": "link_enabled_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/fault": { + "get": { + "summary": "Return any fault currently set on this link", + "operationId": "link_fault_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FaultCondition" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Inject a fault on this link", + "operationId": "link_fault_inject", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "String", + "type": "string" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Clear any fault currently set on this link", + "operationId": "link_fault_clear", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/history": { + "get": { + "summary": "Get the event history for the given link.", + "operationId": "link_history_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LinkHistory" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ipv4": { + "get": { + "summary": "List the IPv4 addresses associated with a link.", + "operationId": "link_ipv4_list", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4EntryResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "post": { + "summary": "Add an IPv4 address to a link.", + "operationId": "link_ipv4_create", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4Entry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Clear all IPv4 addresses from a link.", + "operationId": "link_ipv4_reset", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ipv4/{address}": { + "delete": { + "summary": "Remove an IPv4 address from a link.", + "operationId": "link_ipv4_delete", + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The IPv4 address on which to operate.", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + }, + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ipv6": { + "get": { + "summary": "List the IPv6 addresses associated with a link.", + "operationId": "link_ipv6_list", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6EntryResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "post": { + "summary": "Add an IPv6 address to a link.", + "operationId": "link_ipv6_create", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6Entry" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Clear all IPv6 addresses from a link.", + "operationId": "link_ipv6_reset", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ipv6/{address}": { + "delete": { + "summary": "Remove an IPv6 address from a link.", + "operationId": "link_ipv6_delete", + "parameters": [ + { + "in": "path", + "name": "address", + "description": "The IPv6 address on which to operate.", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + }, + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/ipv6_enabled": { + "get": { + "summary": "Return whether the link is configured to act as an IPv6 endpoint", + "operationId": "link_ipv6_enabled_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set whether a port is configured to act as an IPv6 endpoint", + "operationId": "link_ipv6_enabled_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/kr": { + "get": { + "summary": "Return whether the link is in KR mode.", + "description": "\"KR\" refers to the Ethernet standard for the link, which are defined in various clauses of the IEEE 802.3 specification. \"K\" is used to denote a link over an electrical cabled backplane, and \"R\" refers to \"scrambled encoding\", a 64B/66B bit-encoding scheme.\n\nThus this should be true iff a link is on the cabled backplane.", + "operationId": "link_kr_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Enable or disable a link.", + "operationId": "link_kr_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/linkup": { + "get": { + "summary": "Return whether a link is up.", + "operationId": "link_linkup_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/mac": { + "get": { + "summary": "Get a link's MAC address.", + "operationId": "link_mac_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MacAddr" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set a link's MAC address.", + "operationId": "link_mac_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MacAddr" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/nat_only": { + "get": { + "summary": "Return whether the link is configured to drop non-nat traffic", + "operationId": "link_nat_only_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set whether a port is configured to use drop non-nat traffic", + "operationId": "link_nat_only_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Boolean", + "type": "boolean" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/prbs": { + "get": { + "summary": "Return the link's PRBS speed and mode.", + "description": "During link training, a pseudorandom bit sequence (PRBS) is used to allow each side to synchronize their clocks and set various parameters on the underlying circuitry (such as filter gains).", + "operationId": "link_prbs_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortPrbsMode" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set a link's PRBS speed and mode.", + "operationId": "link_prbs_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PortPrbsMode" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/adapt": { + "get": { + "summary": "Get the per-lane adaptation counts for each lane on this link", + "operationId": "link_rx_adapt_count_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_DfeAdaptationState", + "type": "array", + "items": { + "$ref": "#/components/schemas/DfeAdaptationState" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/anlt_status": { + "get": { + "summary": "Get the per-lane AN/LT status for each lane on this link", + "operationId": "link_an_lt_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AnLtStatus" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/enc_speed": { + "get": { + "summary": "Get the per-lane speed and encoding for each lane on this link", + "operationId": "link_enc_speed_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_EncSpeed", + "type": "array", + "items": { + "$ref": "#/components/schemas/EncSpeed" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/eye": { + "get": { + "summary": "Get the per-lane eye measurements for each lane on this link", + "operationId": "link_eye_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_SerdesEye", + "type": "array", + "items": { + "$ref": "#/components/schemas/SerdesEye" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/lane_map": { + "get": { + "summary": "Get the logical->physical mappings for each lane in this port", + "operationId": "lane_map_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LaneMap" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/rx_sig": { + "get": { + "summary": "Get the per-lane rx signal info for each lane on this link", + "operationId": "link_rx_sig_info_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_RxSigInfo", + "type": "array", + "items": { + "$ref": "#/components/schemas/RxSigInfo" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/links/{link_id}/serdes/tx_eq": { + "get": { + "summary": "Get the per-lane tx eq settings for each lane on this link", + "operationId": "link_tx_eq_get", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_TxEqSwHw", + "type": "array", + "items": { + "$ref": "#/components/schemas/TxEqSwHw" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Update the per-lane tx eq settings for all lanes on this link", + "operationId": "link_tx_eq_set", + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "The link in the switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TxEq" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/management-mode": { + "get": { + "summary": "Return the current management mode of a QSFP switch port.", + "operationId": "management_mode_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementMode" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Set the current management mode of a QSFP switch port.", + "operationId": "management_mode_set", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManagementMode" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/transceiver": { + "get": { + "summary": "Return the information about a port's transceiver.", + "description": "This returns the status (presence, power state, etc) of the transceiver along with its identifying information. If the port is an optical switch port, but has no transceiver, then the identifying information is empty.\n\nIf the switch port is not a QSFP port, and thus could never have a transceiver, then \"Not Found\" is returned.", + "operationId": "transceiver_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Transceiver" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/transceiver/datapath": { + "get": { + "summary": "Fetch the state of the datapath for the provided transceiver.", + "operationId": "transceiver_datapath_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Datapath" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/transceiver/monitors": { + "get": { + "summary": "Fetch the monitored environmental information for the provided transceiver.", + "operationId": "transceiver_monitors_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Monitors" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/transceiver/power": { + "get": { + "summary": "Return the power state of a transceiver.", + "operationId": "transceiver_power_get", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PowerState" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "put": { + "summary": "Control the power state of a transceiver.", + "operationId": "transceiver_power_set", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PowerState" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/ports/{port_id}/transceiver/reset": { + "post": { + "summary": "Effect a module-level reset of a QSFP transceiver.", + "description": "If the QSFP port has no transceiver or is not a QSFP port, then a client error is returned.", + "operationId": "transceiver_reset", + "parameters": [ + { + "in": "path", + "name": "port_id", + "description": "The switch port on which to operate.", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + } + ], + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv4": { + "get": { + "summary": "Fetch the configured IPv4 routes, mapping IPv4 CIDR blocks to the switch port", + "description": "used for sending out that traffic, and optionally a gateway.", + "operationId": "route_ipv4_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4RoutesResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "put": { + "summary": "Route an IPv4 subnet to a link and a nexthop gateway.", + "description": "This call can be used to create a new single-path route or to replace any existing routes with a new single-path route.", + "operationId": "route_ipv4_set", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Route an IPv4 subnet to a link and a nexthop gateway.", + "description": "This call can be used to create a new single-path route or to add new targets to a multipath route.", + "operationId": "route_ipv4_add", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv4/{cidr}": { + "get": { + "summary": "Get the configured route for the given IPv4 subnet.", + "operationId": "route_ipv4_get", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The IPv4 subnet in CIDR notation whose route entry is returned.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv4Net" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Route", + "type": "array", + "items": { + "$ref": "#/components/schemas/Route" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove all targets for the given subnet", + "operationId": "route_ipv4_delete", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The IPv4 subnet in CIDR notation whose route entry is returned.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv4Net" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv4/{cidr}/{port_id}/{link_id}/{tgt_ip}": { + "delete": { + "summary": "Remove a single target for the given IPv4 subnet", + "operationId": "route_ipv4_delete_target", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The subnet being routed", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv4Net" + } + }, + { + "in": "path", + "name": "link_id", + "description": "The link to which packets should be sent", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port to which packets should be sent", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "path", + "name": "tgt_ip", + "description": "The next hop in the IPv4 route", + "required": true, + "schema": { + "type": "string", + "format": "ipv4" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv4-over-ipv6": { + "put": { + "summary": "Route an IPv4 subnet to a link and an IPv6 nexthop gateway.", + "description": "This call can be used to create a new single-path route or to replace any existing routes with a new single-path route.", + "operationId": "route_ipv4_over_ipv6_set", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4OverIpv6RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Route an IPv4 subnet to a link and an IPv6 nexthop gateway.", + "description": "This call can be used to create a new single-path route or to add new targets to a multipath route.", + "operationId": "route_ipv4_over_ipv6_add", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv4OverIpv6RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv6": { + "get": { + "summary": "Fetch the configured IPv6 routes, mapping IPv6 CIDR blocks to the switch port", + "description": "used for sending out that traffic, and optionally a gateway.", + "operationId": "route_ipv6_list", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6RoutesResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + }, + "put": { + "summary": "Route an IPv6 subnet to a link and a nexthop gateway.", + "description": "This call can be used to create a new single-path route or to replace any existing routes with a new single-path route.", + "operationId": "route_ipv6_set", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "post": { + "summary": "Route an IPv6 subnet to a link and a nexthop gateway.", + "description": "This call can be used to create a new single-path route or to add new targets to a multipath route.", + "operationId": "route_ipv6_add", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ipv6RouteUpdate" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv6/{cidr}": { + "get": { + "summary": "Get a single IPv6 route, by its IPv6 CIDR block.", + "operationId": "route_ipv6_get", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The IPv6 subnet in CIDR notation whose route entry is returned.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv6Net" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_Ipv6Route", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Route" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "summary": "Remove an IPv6 route, by its IPv6 CIDR block.", + "operationId": "route_ipv6_delete", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The IPv6 subnet in CIDR notation whose route entry is returned.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv6Net" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/route/ipv6/{cidr}/{port_id}/{link_id}/{tgt_ip}": { + "delete": { + "summary": "Remove a single target for the given IPv6 subnet", + "operationId": "route_ipv6_delete_target", + "parameters": [ + { + "in": "path", + "name": "cidr", + "description": "The subnet being routed", + "required": true, + "schema": { + "$ref": "#/components/schemas/Ipv6Net" + } + }, + { + "in": "path", + "name": "link_id", + "description": "The link to which packets should be sent", + "required": true, + "schema": { + "$ref": "#/components/schemas/LinkId" + } + }, + { + "in": "path", + "name": "port_id", + "description": "The switch port to which packets should be sent", + "required": true, + "schema": { + "$ref": "#/components/schemas/PortId" + } + }, + { + "in": "path", + "name": "tgt_ip", + "description": "The next hop in the IPv4 route", + "required": true, + "schema": { + "type": "string", + "format": "ipv6" + } + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/rpw/nat/gen": { + "get": { + "summary": "Get NAT generation number", + "operationId": "nat_generation", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "int64", + "type": "integer", + "format": "int64" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/rpw/nat/trigger": { + "post": { + "summary": "Trigger NAT Reconciliation", + "operationId": "nat_trigger_update", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Null", + "type": "string", + "enum": [ + null + ] + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/switch/identifiers": { + "get": { + "summary": "Get switch identifiers.", + "description": "This endpoint returns the switch identifiers, which can be used for consistent field definitions across oximeter time series schemas.", + "operationId": "switch_identifiers", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SwitchIdentifiers" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/table": { + "get": { + "summary": "Get the list of P4 tables", + "operationId": "table_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_String", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/table/{table}/counters": { + "get": { + "summary": "Get any counter data from a single P4 match-action table.", + "description": "The name of the table should match one of those returned by the `table_list()` call.", + "operationId": "table_counters", + "parameters": [ + { + "in": "query", + "name": "force_sync", + "description": "Force a sync of the counters from the ASIC to memory, even if the default refresh timeout hasn't been reached.", + "required": true, + "schema": { + "type": "boolean" + } + }, + { + "in": "path", + "name": "table", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Array_of_TableCounterEntry", + "type": "array", + "items": { + "$ref": "#/components/schemas/TableCounterEntry" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/table/{table}/dump": { + "get": { + "summary": "Get the contents of a single P4 table.", + "description": "The name of the table should match one of those returned by the `table_list()` call.", + "operationId": "table_dump", + "parameters": [ + { + "in": "path", + "name": "table", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/transceivers": { + "get": { + "summary": "Return information about all QSFP transceivers.", + "operationId": "transceivers_list", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "title": "Map_of_Transceiver", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Transceiver" + } + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + } + }, + "components": { + "schemas": { + "AdminScopedIpv6": { + "description": "A validated admin-scoped IPv6 multicast address.\n\nAdmin-scoped addresses are ff04::/16, ff05::/16, or ff08::/16. These are used for internal/underlay multicast groups.", + "type": "string", + "format": "ipv6" + }, + "AnLtStatus": { + "description": "A collection of the data involved in the autonegiation/link-training process", + "type": "object", + "properties": { + "lanes": { + "description": "The per-lane status", + "type": "array", + "items": { + "$ref": "#/components/schemas/LaneStatus" + } + }, + "lp_pages": { + "description": "The base and extended pages received from the link partner", + "allOf": [ + { + "$ref": "#/components/schemas/LpPages" + } + ] + } + }, + "required": [ + "lanes", + "lp_pages" + ] + }, + "AnStatus": { + "description": "State of a single lane during autonegotiation", + "type": "object", + "properties": { + "an_ability": { + "description": "Are we capable of AN?", + "type": "boolean" + }, + "an_complete": { + "description": "Is autonegotiation complete?", + "type": "boolean" + }, + "ext_np_status": { + "description": "Is extended page format supported?", + "type": "boolean" + }, + "link_status": { + "description": "Allegedly: is the link up? In practice, this always seems to be false? TODO: investigate this", + "type": "boolean" + }, + "lp_an_ability": { + "description": "Can the link partner perform AN?", + "type": "boolean" + }, + "page_rcvd": { + "description": "has a base page been received?", + "type": "boolean" + }, + "parallel_detect_fault": { + "description": "A fault has been detected via the parallel detection function", + "type": "boolean" + }, + "remote_fault": { + "description": "Remote fault detected", + "type": "boolean" + } + }, + "required": [ + "an_ability", + "an_complete", + "ext_np_status", + "link_status", + "lp_an_ability", + "page_rcvd", + "parallel_detect_fault", + "remote_fault" + ] + }, + "ApplicationDescriptor": { + "description": "An Application Descriptor describes the supported datapath configurations.\n\nThis is a CMIS-specific concept. It's used for modules to advertise how it can be used by the host. Each application describes the host-side electrical interface; the media-side interface; the number of lanes required; etc.\n\nHost-side software can select one of these applications to instruct the module to use a specific set of lanes, with the interface on either side of the module.", + "type": "object", + "properties": { + "host_id": { + "description": "The electrical interface with the host side.", + "type": "string" + }, + "host_lane_assignment_options": { + "description": "The lanes on the host-side supporting this application.\n\nThis is a bit mask with a 1 identifying the lowest lane in a consecutive group of lanes to which the application can be assigned. This must be used with the `host_lane_count`. For example a value of `0b0000_0001` with a host lane count of 4 indicates that the first 4 lanes may be used in this application.\n\nAn application may support starting from multiple lanes.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "host_lane_count": { + "description": "The number of host-side lanes.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "media_id": { + "description": "The interface, optical or copper, with the media side.", + "allOf": [ + { + "$ref": "#/components/schemas/MediaInterfaceId" + } + ] + }, + "media_lane_assignment_options": { + "description": "The lanes on the media-side supporting this application.\n\nSee `host_lane_assignment_options` for details.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "media_lane_count": { + "description": "The number of media-side lanes.", + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "required": [ + "host_id", + "host_lane_assignment_options", + "host_lane_count", + "media_id", + "media_lane_assignment_options", + "media_lane_count" + ] + }, + "ArpEntry": { + "description": "Represents the mapping of an IP address to a MAC address.", + "type": "object", + "properties": { + "ip": { + "description": "The IP address for the entry.", + "type": "string", + "format": "ip" + }, + "mac": { + "description": "The MAC address to which `ip` maps.", + "allOf": [ + { + "$ref": "#/components/schemas/MacAddr" + } + ] + }, + "tag": { + "description": "A tag used to associate this entry with a client.", + "type": "string" + }, + "update": { + "description": "The time the entry was updated", + "type": "string" + } + }, + "required": [ + "ip", + "mac", + "tag", + "update" + ] + }, + "ArpEntryResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/ArpEntry" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "AttachedSubnetEntry": { + "description": "represents an external subnet mapping", + "type": "object", + "properties": { + "subnet": { + "$ref": "#/components/schemas/IpNet" + }, + "tgt": { + "$ref": "#/components/schemas/InstanceTarget" + } + }, + "required": [ + "subnet", + "tgt" + ] + }, + "AttachedSubnetEntryResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/AttachedSubnetEntry" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "Aux1Monitor": { + "description": "The first auxlliary CMIS monitor.", + "oneOf": [ + { + "description": "The monitored property is custom, i.e., part-specific.", + "type": "object", + "properties": { + "custom": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + } + }, + "required": [ + "custom" + ], + "additionalProperties": false + }, + { + "description": "The current of the laser thermoelectric cooler.\n\nFor actively-cooled laser systems, this specifies the percentage of the maximum current the thermoelectric cooler supports. If the percentage is positive, the cooler is heating the laser. If negative, the cooler is cooling the laser.", + "type": "object", + "properties": { + "tec_current": { + "type": "number", + "format": "float" + } + }, + "required": [ + "tec_current" + ], + "additionalProperties": false + } + ] + }, + "Aux2Monitor": { + "description": "The second auxlliary CMIS monitor.", + "oneOf": [ + { + "description": "The temperature of the laser itself (degrees C).", + "type": "object", + "properties": { + "laser_temperature": { + "type": "number", + "format": "float" + } + }, + "required": [ + "laser_temperature" + ], + "additionalProperties": false + }, + { + "description": "The current of the laser thermoelectric cooler.\n\nFor actively-cooled laser systems, this specifies the percentage of the maximum current the thermoelectric cooler supports. If the percentage is positive, the cooler is heating the laser. If negative, the cooler is cooling the laser.", + "type": "object", + "properties": { + "tec_current": { + "type": "number", + "format": "float" + } + }, + "required": [ + "tec_current" + ], + "additionalProperties": false + } + ] + }, + "Aux3Monitor": { + "description": "The third auxlliary CMIS monitor.", + "oneOf": [ + { + "description": "The temperature of the laser itself (degrees C).", + "type": "object", + "properties": { + "laser_temperature": { + "type": "number", + "format": "float" + } + }, + "required": [ + "laser_temperature" + ], + "additionalProperties": false + }, + { + "description": "Measured voltage of an additional power supply (Volts).", + "type": "object", + "properties": { + "additional_supply_voltage": { + "type": "number", + "format": "float" + } + }, + "required": [ + "additional_supply_voltage" + ], + "additionalProperties": false + } + ] + }, + "AuxMonitors": { + "description": "Auxlliary monitored values for CMIS modules.", + "type": "object", + "properties": { + "aux1": { + "nullable": true, + "description": "Auxlliary monitor 1, either a custom value or TEC current.", + "allOf": [ + { + "$ref": "#/components/schemas/Aux1Monitor" + } + ] + }, + "aux2": { + "nullable": true, + "description": "Auxlliary monitor 1, either laser temperature or TEC current.", + "allOf": [ + { + "$ref": "#/components/schemas/Aux2Monitor" + } + ] + }, + "aux3": { + "nullable": true, + "description": "Auxlliary monitor 1, either laser temperature or additional supply voltage.", + "allOf": [ + { + "$ref": "#/components/schemas/Aux3Monitor" + } + ] + }, + "custom": { + "nullable": true, + "description": "A custom monitor. The value here is entirely vendor- and part-specific, so the part's data sheet must be consulted. The value may be either a signed or unsigned 16-bit integer, and so is included as raw bytes.", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + } + } + }, + "BackplaneCableLeg": { + "description": "The leg of the backplane cable.\n\nThis describes the leg on the actual backplane cable that connects the Sidecar chassis connector to a cubby endpoint.", + "type": "string", + "enum": [ + "A", + "B", + "C", + "D" + ] + }, + "BackplaneLink": { + "description": "A single point-to-point connection on the cabled backplane.\n\nThis describes a single link from the Sidecar switch to a cubby, via the cabled backplane. It ultimately maps the Tofino ASIC pins to the cubby at which that link terminates. This path follows the Sidecar internal cable; the Sidecar chassis connector; and the backplane cable itself. This is used to map the Tofino driver's \"connector\" number (an index in its possible pinouts) through the backplane to our logical cubby numbering.", + "type": "object", + "properties": { + "backplane_leg": { + "$ref": "#/components/schemas/BackplaneCableLeg" + }, + "cubby": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "sidecar_connector": { + "$ref": "#/components/schemas/SidecarConnector" + }, + "sidecar_leg": { + "$ref": "#/components/schemas/SidecarCableLeg" + }, + "tofino_connector": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "required": [ + "backplane_leg", + "cubby", + "sidecar_connector", + "sidecar_leg", + "tofino_connector" + ] + }, + "Ber": { + "description": "Reports the bit-error rate (BER) for a link.", + "type": "object", + "properties": { + "ber": { + "description": "Estimated BER per-lane.", + "type": "array", + "items": { + "type": "number", + "format": "float" + } + }, + "symbol_errors": { + "description": "Counters of symbol errors per-lane.", + "type": "array", + "items": { + "type": "integer", + "format": "uint64", + "minimum": 0 + } + }, + "total_ber": { + "description": "Aggregate BER on the link.", + "type": "number", + "format": "float" + } + }, + "required": [ + "ber", + "symbol_errors", + "total_ber" + ] + }, + "BuildInfo": { + "description": "Detailed build information about `dpd`.", + "type": "object", + "properties": { + "cargo_triple": { + "type": "string" + }, + "debug": { + "type": "boolean" + }, + "git_branch": { + "type": "string" + }, + "git_commit_timestamp": { + "type": "string" + }, + "git_sha": { + "type": "string" + }, + "opt_level": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "rustc_channel": { + "type": "string" + }, + "rustc_commit_sha": { + "type": "string" + }, + "rustc_host_triple": { + "type": "string" + }, + "rustc_semver": { + "type": "string" + }, + "sde_commit_sha": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "cargo_triple", + "debug", + "git_branch", + "git_commit_timestamp", + "git_sha", + "opt_level", + "rustc_channel", + "rustc_commit_sha", + "rustc_host_triple", + "rustc_semver", + "sde_commit_sha", + "version" + ] + }, + "CmisDatapath": { + "description": "A datapath in a CMIS module.\n\nIn contrast to SFF-8636, CMIS makes first-class the concept of a datapath: a set of lanes and all the associated machinery involved in the transfer of data. This includes:\n\n- The \"application descriptor\" which is the host and media interfaces, and the lanes on each side used to transfer data; - The state of the datapath in a well-defined finite state machine (see CMIS 5.0 section 6.3.3); - The flags indicating how the datapath components are operating, such as receiving an input Rx signal or whether the transmitter is disabled.", + "type": "object", + "properties": { + "application": { + "description": "The application descriptor for this datapath.", + "allOf": [ + { + "$ref": "#/components/schemas/ApplicationDescriptor" + } + ] + }, + "lane_status": { + "description": "The status bits for each lane in the datapath.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/CmisLaneStatus" + } + } + }, + "required": [ + "application", + "lane_status" + ] + }, + "CmisLaneStatus": { + "description": "The status of a single CMIS lane.\n\nIf any particular control or status value is unsupported by a module, it is `None`.", + "type": "object", + "properties": { + "rx_auto_squelch_disable": { + "nullable": true, + "description": "Whether the host-side has disabled the Rx auto-squelch.\n\nThe module can implement automatic squelching of the Rx output, if the media-side input signal isn't valid. This indicates whether the host has disabled such a setting.", + "type": "boolean" + }, + "rx_lol": { + "nullable": true, + "description": "Media-side loss of lock flag.\n\nThis is true if the module is not able to extract a clock signal from the media-side signal (usually optical).", + "type": "boolean" + }, + "rx_los": { + "nullable": true, + "description": "Media-side loss of signal flag.\n\nThis is true if there is no detected input signal from the media-side (usually optical).", + "type": "boolean" + }, + "rx_output_enabled": { + "nullable": true, + "description": "Whether the Rx output is enabled.\n\nThe host may control this to disable the electrical output from the module to the host.", + "type": "boolean" + }, + "rx_output_polarity": { + "nullable": true, + "description": "The Rx output polarity.\n\nThis indicates a host-side control that flips the polarity of the host-side output signal.", + "allOf": [ + { + "$ref": "#/components/schemas/LanePolarity" + } + ] + }, + "rx_output_status": { + "description": "Status of host-side Rx output.\n\nThis indicates whether the Rx output is sending a valid signal to the host. Note that this is `Invalid` if the output is either muted (such as squelched) or explicitly disabled.", + "allOf": [ + { + "$ref": "#/components/schemas/OutputStatus" + } + ] + }, + "state": { + "description": "The datapath state of this lane.\n\nSee CMIS 5.0 section 8.9.1 for details.", + "type": "string" + }, + "tx_adaptive_eq_fail": { + "nullable": true, + "description": "A failure in the Tx adaptive input equalization.", + "type": "boolean" + }, + "tx_auto_squelch_disable": { + "nullable": true, + "description": "Whether the host-side has disabled the Tx auto-squelch.\n\nThe module can implement automatic squelching of the Tx output, if the host-side input signal isn't valid. This indicates whether the host has disabled such a setting.", + "type": "boolean" + }, + "tx_failure": { + "nullable": true, + "description": "General Tx failure flag.\n\nThis indicates that an internal and unspecified malfunction has occurred on the Tx lane.", + "type": "boolean" + }, + "tx_force_squelch": { + "nullable": true, + "description": "Whether the host-side has force-squelched the Tx output.\n\nThis indicates that the host can _force_ squelching the output if the signal is not valid.", + "type": "boolean" + }, + "tx_input_polarity": { + "nullable": true, + "description": "The Tx input polarity.\n\nThis indicates a host-side control that flips the polarity of the host-side input signal.", + "allOf": [ + { + "$ref": "#/components/schemas/LanePolarity" + } + ] + }, + "tx_lol": { + "nullable": true, + "description": "Host-side loss of lock flag.\n\nThis is true if the module is not able to extract a clock signal from the host-side electrical signal.", + "type": "boolean" + }, + "tx_los": { + "nullable": true, + "description": "Host-side loss of signal flag.\n\nThis is true if there is no detected electrical signal from the host-side serdes.", + "type": "boolean" + }, + "tx_output_enabled": { + "nullable": true, + "description": "Whether the Tx output is enabled.", + "type": "boolean" + }, + "tx_output_status": { + "description": "Status of media-side Tx output.\n\nThis indicates whether the Rx output is sending a valid signal to the media itself. Note that this is `Invalid` if the output is either muted (such as squelched) or explicitly disabled.", + "allOf": [ + { + "$ref": "#/components/schemas/OutputStatus" + } + ] + } + }, + "required": [ + "rx_output_status", + "state", + "tx_output_status" + ] + }, + "CounterData": { + "description": "For a counter, this contains the number of bytes, packets, or both that were counted. XXX: Ideally this would be a data-bearing enum, with variants for Pkts, Bytes, and PktsAndBytes. However OpenApi doesn't yet have the necessary support, so we're left with this clumsier representation.", + "type": "object", + "properties": { + "bytes": { + "nullable": true, + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pkts": { + "nullable": true, + "type": "integer", + "format": "uint64", + "minimum": 0 + } + } + }, + "Datapath": { + "description": "Information about a transceiver's datapath.\n\nThis includes state related to the low-level eletrical and optical path through which bits flow. This includes flags like loss-of-signal / loss-of-lock; transmitter enablement state; and equalization parameters.", + "oneOf": [ + { + "description": "A number of datapaths in a CMIS module.\n\nCMIS modules may have a large number of supported configurations of their various lanes, each called an \"application\". These are described by the `ApplicationDescriptor` type, which mirrors CMIS 5.0 table 8-18. Each descriptor is identified by an \"Application Selector Code\", which is just its index in the section of the memory map describing them.\n\nEach lane can be used in zero or more applications, however, it may exist in at most one application at a time. These active applications, of which there may be more than one, are keyed by their codes in the contained mapping.", + "type": "object", + "properties": { + "cmis": { + "type": "object", + "properties": { + "connector": { + "description": "The type of free-side connector", + "type": "string" + }, + "datapaths": { + "description": "Mapping from \"application selector\" ID to its datapath information.\n\nThe datapath inclues the lanes used; host electrical interface; media interface; and a lot more about the state of the path.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/CmisDatapath" + } + }, + "supported_lanes": { + "description": "A bit mask with a 1 in bit `i` if the `i`th lane is supported.", + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "required": [ + "connector", + "datapaths", + "supported_lanes" + ] + } + }, + "required": [ + "cmis" + ], + "additionalProperties": false + }, + { + "description": "Datapath state about each lane in an SFF-8636 module.", + "type": "object", + "properties": { + "sff8636": { + "type": "object", + "properties": { + "connector": { + "description": "The type of a media-side connector.\n\nThese values come from SFF-8024 Rev 4.10 Table 4-3.", + "type": "string" + }, + "lanes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sff8636Datapath" + }, + "minItems": 4, + "maxItems": 4 + }, + "specification": { + "$ref": "#/components/schemas/SffComplianceCode" + } + }, + "required": [ + "connector", + "lanes", + "specification" + ] + } + }, + "required": [ + "sff8636" + ], + "additionalProperties": false + } + ] + }, + "DfeAdaptationState": { + "description": "Rx DFE adaptation information", + "type": "object", + "properties": { + "adapt_cnt": { + "description": "Total DFE attempts", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "adapt_done": { + "description": "DFE complete", + "type": "boolean" + }, + "link_lost_cnt": { + "description": "Times the signal was lost since the last read", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "readapt_cnt": { + "description": "DFE attempts since the last read", + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "adapt_cnt", + "adapt_done", + "link_lost_cnt", + "readapt_cnt" + ] + }, + "Direction": { + "description": "Direction a multicast group member is reached by.\n\n`External` group members must have any packet encapsulation removed before packet delivery.", + "type": "string", + "enum": [ + "Underlay", + "External" + ] + }, + "ElectricalMode": { + "description": "The electrical mode of a QSFP-capable port.\n\nQSFP ports can be broken out into one of several different electrical configurations or modes. This describes how the transmit/receive lanes are grouped into a single, logical link.\n\nNote that the electrical mode may only be changed if there are no links within the port, _and_ if the inserted QSFP module actually supports this mode.", + "oneOf": [ + { + "description": "All transmit/receive lanes are used for a single link.", + "type": "string", + "enum": [ + "Single" + ] + } + ] + }, + "EncSpeed": { + "description": "Signal speed and encoding for a single lane", + "type": "object", + "properties": { + "encoding": { + "$ref": "#/components/schemas/LaneEncoding" + }, + "gigabits": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "encoding", + "gigabits" + ] + }, + "Error": { + "description": "Error information from a response.", + "type": "object", + "properties": { + "error_code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "request_id": { + "type": "string" + } + }, + "required": [ + "message", + "request_id" + ] + }, + "ExternalForwarding": { + "description": "Represents the forwarding configuration for external multicast traffic.", + "type": "object", + "properties": { + "vlan_id": { + "nullable": true, + "type": "integer", + "format": "uint16", + "minimum": 0 + } + } + }, + "Fault": { + "description": "A Fault represents a specific kind of failure, and carries some additional context. Currently Faults are only used to describe Link failures, but there is no reason they couldn't be used elsewhere.", + "oneOf": [ + { + "type": "object", + "properties": { + "LinkFlap": { + "type": "string" + } + }, + "required": [ + "LinkFlap" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "Autoneg": { + "type": "string" + } + }, + "required": [ + "Autoneg" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "Injected": { + "type": "string" + } + }, + "required": [ + "Injected" + ], + "additionalProperties": false + } + ] + }, + "FaultCondition": { + "description": "Represents a potential fault condtion on a link", + "type": "object", + "properties": { + "fault": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/Fault" + } + ] + } + } + }, + "FaultReason": { + "description": "The cause of a fault on a transceiver.", + "oneOf": [ + { + "description": "An error occurred accessing the transceiver.", + "type": "string", + "enum": [ + "failed" + ] + }, + { + "description": "Power was enabled, but did not come up in the requisite time.", + "type": "string", + "enum": [ + "power_timeout" + ] + }, + { + "description": "Power was enabled and later lost.", + "type": "string", + "enum": [ + "power_lost" + ] + }, + { + "description": "The service processor disabled the transceiver.\n\nThe SP is responsible for monitoring the thermal data from the transceivers, and controlling the fans to compensate. If a module's thermal data cannot be read, the SP may completely disable the transceiver to ensure it cannot overheat the Sidecar.", + "type": "string", + "enum": [ + "disabled_by_sp" + ] + } + ] + }, + "FecRSCounters": { + "description": "Per-port RS FEC counters", + "type": "object", + "properties": { + "fec_align_status": { + "description": "All lanes synced and aligned", + "type": "boolean" + }, + "fec_corr_cnt": { + "description": "FEC corrected blocks", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_0": { + "description": "FEC symbol errors on lane 0", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_1": { + "description": "FEC symbol errors on lane 1", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_2": { + "description": "FEC symbol errors on lane 2", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_3": { + "description": "FEC symbol errors on lane 3", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_4": { + "description": "FEC symbol errors on lane 4", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_5": { + "description": "FEC symbol errors on lane 5", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_6": { + "description": "FEC symbol errors on lane 6", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_ser_lane_7": { + "description": "FEC symbol errors on lane 7", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "fec_uncorr_cnt": { + "description": "FEC uncorrected blocks", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "hi_ser": { + "description": "symbol errors exceeds threshhold", + "type": "boolean" + }, + "port": { + "description": "Port being tracked", + "type": "string" + } + }, + "required": [ + "fec_align_status", + "fec_corr_cnt", + "fec_ser_lane_0", + "fec_ser_lane_1", + "fec_ser_lane_2", + "fec_ser_lane_3", + "fec_ser_lane_4", + "fec_ser_lane_5", + "fec_ser_lane_6", + "fec_ser_lane_7", + "fec_uncorr_cnt", + "hi_ser", + "port" + ] + }, + "FreeChannels": { + "description": "Represents the free MAC channels on a single physical port.", + "type": "object", + "properties": { + "channels": { + "description": "The set of available channels (lanes) on this connector.", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "connector": { + "description": "The Tofino connector for this port.\n\nThis describes the set of electrical connections representing this port object, which are defined by the pinout and board design of the Sidecar.", + "type": "string" + }, + "port_id": { + "description": "The switch port.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "channels", + "connector", + "port_id" + ] + }, + "InstanceTarget": { + "description": "represents an internal target for either NAT or an external subnet mapping", + "type": "object", + "properties": { + "inner_mac": { + "$ref": "#/components/schemas/MacAddr" + }, + "internal_ip": { + "type": "string", + "format": "ipv6" + }, + "vni": { + "$ref": "#/components/schemas/Vni" + } + }, + "required": [ + "inner_mac", + "internal_ip", + "vni" + ] + }, + "InternalForwarding": { + "description": "Represents the NAT target for multicast traffic for internal/underlay forwarding.", + "type": "object", + "properties": { + "nat_target": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/NatTarget" + } + ] + } + } + }, + "IpNet": { + "x-rust-type": { + "crate": "oxnet", + "path": "oxnet::IpNet", + "version": "0.1.0" + }, + "oneOf": [ + { + "title": "v4", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Net" + } + ] + }, + { + "title": "v6", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" + } + ] + } + ] + }, + "IpSrc": { + "description": "Source filter match key for multicast traffic.", + "oneOf": [ + { + "description": "Exact match for the source IP address.", + "type": "object", + "properties": { + "Exact": { + "type": "string", + "format": "ip" + } + }, + "required": [ + "Exact" + ], + "additionalProperties": false + }, + { + "description": "Subnet match for the source IP address.", + "type": "object", + "properties": { + "Subnet": { + "$ref": "#/components/schemas/Ipv4Net" + } + }, + "required": [ + "Subnet" + ], + "additionalProperties": false + } + ] + }, + "Ipv4Entry": { + "description": "An IPv4 address assigned to a link.", + "type": "object", + "properties": { + "addr": { + "description": "The IP address.", + "type": "string", + "format": "ipv4" + }, + "tag": { + "description": "Client-side tag for this object.", + "type": "string" + } + }, + "required": [ + "addr", + "tag" + ] + }, + "Ipv4EntryResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv4Entry" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "Ipv4Nat": { + "description": "represents an IPv4 NAT reservation", + "type": "object", + "properties": { + "external": { + "type": "string", + "format": "ipv4" + }, + "high": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "low": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "target": { + "$ref": "#/components/schemas/NatTarget" + } + }, + "required": [ + "external", + "high", + "low", + "target" + ] + }, + "Ipv4NatResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv4Nat" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "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" + }, + "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])$" + }, + "Ipv4OverIpv6RouteUpdate": { + "type": "object", + "properties": { + "cidr": { + "description": "Traffic destined for any address within the CIDR block is routed using this information.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Net" + } + ] + }, + "replace": { + "description": "Should this route replace any existing route? If a route exists and this parameter is false, then the call will fail.", + "type": "boolean" + }, + "target": { + "description": "A single Route associated with this CIDR", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Route" + } + ] + } + }, + "required": [ + "cidr", + "replace", + "target" + ] + }, + "Ipv4Route": { + "description": "A route for an IPv4 subnet.", + "type": "object", + "properties": { + "link_id": { + "$ref": "#/components/schemas/LinkId" + }, + "port_id": { + "$ref": "#/components/schemas/PortId" + }, + "tag": { + "type": "string" + }, + "tgt_ip": { + "type": "string", + "format": "ipv4" + }, + "vlan_id": { + "nullable": true, + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "link_id", + "port_id", + "tag", + "tgt_ip" + ] + }, + "Ipv4RouteUpdate": { + "description": "Represents a new or replacement mapping of a subnet to a single IPv4 RouteTarget nexthop target.", + "type": "object", + "properties": { + "cidr": { + "description": "Traffic destined for any address within the CIDR block is routed using this information.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Net" + } + ] + }, + "replace": { + "description": "Should this route replace any existing route? If a route exists and this parameter is false, then the call will fail.", + "type": "boolean" + }, + "target": { + "description": "A single Route associated with this CIDR", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Route" + } + ] + } + }, + "required": [ + "cidr", + "replace", + "target" + ] + }, + "Ipv4Routes": { + "type": "object", + "properties": { + "cidr": { + "description": "Traffic destined for any address within the CIDR block is routed using this information.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv4Net" + } + ] + }, + "targets": { + "description": "All RouteTargets associated with this CIDR", + "type": "array", + "items": { + "$ref": "#/components/schemas/Route" + } + } + }, + "required": [ + "cidr", + "targets" + ] + }, + "Ipv4RoutesResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv4Routes" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "Ipv6Entry": { + "description": "An IPv6 address assigned to a link.", + "type": "object", + "properties": { + "addr": { + "description": "The IP address.", + "type": "string", + "format": "ipv6" + }, + "tag": { + "description": "Client-side tag for this object.", + "type": "string" + } + }, + "required": [ + "addr", + "tag" + ] + }, + "Ipv6EntryResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Entry" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "Ipv6Nat": { + "description": "represents an IPv6 NAT reservation", + "type": "object", + "properties": { + "external": { + "type": "string", + "format": "ipv6" + }, + "high": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "low": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "target": { + "$ref": "#/components/schemas/NatTarget" + } + }, + "required": [ + "external", + "high", + "low", + "target" + ] + }, + "Ipv6NatResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Nat" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "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" + }, + "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])$" + }, + "Ipv6Route": { + "description": "A route for an IPv6 subnet.", + "type": "object", + "properties": { + "link_id": { + "$ref": "#/components/schemas/LinkId" + }, + "port_id": { + "$ref": "#/components/schemas/PortId" + }, + "tag": { + "type": "string" + }, + "tgt_ip": { + "type": "string", + "format": "ipv6" + }, + "vlan_id": { + "nullable": true, + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "link_id", + "port_id", + "tag", + "tgt_ip" + ] + }, + "Ipv6RouteUpdate": { + "description": "Represents a new or replacement mapping of a subnet to a single IPv6 RouteTarget nexthop target.", + "type": "object", + "properties": { + "cidr": { + "description": "Traffic destined for any address within the CIDR block is routed using this information.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" + } + ] + }, + "replace": { + "description": "Should this route replace any existing route? If a route exists and this parameter is false, then the call will fail.", + "type": "boolean" + }, + "target": { + "description": "A single RouteTarget associated with this CIDR", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Route" + } + ] + } + }, + "required": [ + "cidr", + "replace", + "target" + ] + }, + "Ipv6Routes": { + "description": "Represents all mappings of an IPv6 subnet to a its nexthop target(s).", + "type": "object", + "properties": { + "cidr": { + "description": "Traffic destined for any address within the CIDR block is routed using this information.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" + } + ] + }, + "targets": { + "description": "All RouteTargets associated with this CIDR", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Route" + } + } + }, + "required": [ + "cidr", + "targets" + ] + }, + "Ipv6RoutesResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ipv6Routes" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "LaneEncoding": { + "description": "Signal encoding", + "oneOf": [ + { + "description": "Pulse Amplitude Modulation 4-level", + "type": "string", + "enum": [ + "Pam4" + ] + }, + { + "description": "Non-Return-to-Zero encoding", + "type": "string", + "enum": [ + "Nrz" + ] + }, + { + "description": "No encoding selected", + "type": "string", + "enum": [ + "None" + ] + } + ] + }, + "LaneMap": { + "description": "Mapping of the logical lanes in a link to their physical instantiation in the MAC/serdes interface.", + "type": "object", + "properties": { + "logical_lane": { + "description": "logical lane within the mac block for each lane", + "type": "array", + "items": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "mac_block": { + "description": "MAC block in the tofino ASIC", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "rx_phys": { + "description": "Rx logical->physical mapping", + "type": "array", + "items": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "rx_polarity": { + "description": "Rx polarity", + "type": "array", + "items": { + "$ref": "#/components/schemas/Polarity" + } + }, + "tx_phys": { + "description": "Tx logical->physical mapping", + "type": "array", + "items": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "tx_polarity": { + "description": "Tx polarity", + "type": "array", + "items": { + "$ref": "#/components/schemas/Polarity" + } + } + }, + "required": [ + "logical_lane", + "mac_block", + "rx_phys", + "rx_polarity", + "tx_phys", + "tx_polarity" + ] + }, + "LanePolarity": { + "description": "The polarity of a transceiver lane.", + "type": "string", + "enum": [ + "normal", + "flipped" + ] + }, + "LaneStatus": { + "description": "The combined status of a lane, with respect to the autonegotiation / link-training process.", + "type": "object", + "properties": { + "lane_an_status": { + "description": "Detailed autonegotiation status", + "allOf": [ + { + "$ref": "#/components/schemas/AnStatus" + } + ] + }, + "lane_done": { + "description": "Has a lane successfully completed autoneg and link training?", + "type": "boolean" + }, + "lane_lt_status": { + "description": "Detailed link-training status", + "allOf": [ + { + "$ref": "#/components/schemas/LtStatus" + } + ] + } + }, + "required": [ + "lane_an_status", + "lane_done", + "lane_lt_status" + ] + }, + "Led": { + "description": "Information about a QSFP port's LED.", + "type": "object", + "properties": { + "policy": { + "description": "The policy by which the LED is controlled.", + "allOf": [ + { + "$ref": "#/components/schemas/LedPolicy" + } + ] + }, + "state": { + "description": "The state of the LED.", + "allOf": [ + { + "$ref": "#/components/schemas/LedState" + } + ] + } + }, + "required": [ + "policy", + "state" + ] + }, + "LedPolicy": { + "description": "The policy by which a port's LED is controlled.", + "oneOf": [ + { + "description": "The default policy is for the LED to reflect the port's state itself.\n\nIf the port is operating normally, the LED will be solid on. Without a transceiver, the LED will be solid off. A blinking LED is used to indicate an unsupported module or other failure on that port.", + "type": "string", + "enum": [ + "automatic" + ] + }, + { + "description": "The LED is explicitly overridden by client requests.", + "type": "string", + "enum": [ + "override" + ] + } + ] + }, + "LedState": { + "description": "The state of a module's attention LED, on the Sidecar front IO panel.", + "oneOf": [ + { + "description": "The LED is off.\n\nThis indicates that the port is disabled or not working at all.", + "type": "string", + "enum": [ + "off" + ] + }, + { + "description": "The LED is solid on.\n\nThis indicates that the port is working as expected and enabled.", + "type": "string", + "enum": [ + "on" + ] + }, + { + "description": "The LED is blinking.\n\nThis is used to draw attention to the port, such as to indicate a fault or to locate a port for servicing.", + "type": "string", + "enum": [ + "blink" + ] + } + ] + }, + "Link": { + "description": "An Ethernet-capable link within a switch port.", + "type": "object", + "properties": { + "address": { + "description": "The MAC address for the link.", + "allOf": [ + { + "$ref": "#/components/schemas/MacAddr" + } + ] + }, + "asic_id": { + "description": "The lower-level ASIC ID used to refer to this object in the switch driver software.", + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "autoneg": { + "description": "True if this link is configured to autonegotiate with its peer.", + "type": "boolean" + }, + "enabled": { + "description": "True if this link is enabled.", + "type": "boolean" + }, + "fec": { + "nullable": true, + "description": "The error-correction scheme for this link.", + "allOf": [ + { + "$ref": "#/components/schemas/PortFec" + } + ] + }, + "fsm_state": { + "description": "Current state in the autonegotiation/link-training finite state machine", + "type": "string" + }, + "ipv6_enabled": { + "description": "The link is configured for IPv6 use", + "type": "boolean" + }, + "kr": { + "description": "True if this link is in KR mode, i.e., is on a cabled backplane.", + "type": "boolean" + }, + "link_id": { + "description": "The `LinkId` within the switch port for this link.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "link_state": { + "description": "The state of the Ethernet link.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkState" + } + ] + }, + "media": { + "description": "The physical media underlying this link.", + "allOf": [ + { + "$ref": "#/components/schemas/PortMedia" + } + ] + }, + "port_id": { + "description": "The switch port on which this link exists.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + }, + "prbs": { + "description": "The PRBS mode.", + "allOf": [ + { + "$ref": "#/components/schemas/PortPrbsMode" + } + ] + }, + "presence": { + "description": "True if the transceiver module has detected a media presence.", + "type": "boolean" + }, + "speed": { + "description": "The speed of the link.", + "allOf": [ + { + "$ref": "#/components/schemas/PortSpeed" + } + ] + }, + "tofino_connector": { + "description": "The Tofino connector number associated with this link.", + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "address", + "asic_id", + "autoneg", + "enabled", + "fsm_state", + "ipv6_enabled", + "kr", + "link_id", + "link_state", + "media", + "port_id", + "prbs", + "presence", + "speed", + "tofino_connector" + ] + }, + "LinkCreate": { + "description": "Parameters used to create a link on a switch port.", + "type": "object", + "properties": { + "autoneg": { + "description": "Whether the link is configured to autonegotiate with its peer during link training.\n\nThis is generally only true for backplane links, and defaults to `false`.", + "default": false, + "type": "boolean" + }, + "fec": { + "nullable": true, + "description": "The requested forward-error correction method. If this is None, the standard FEC for the underlying media will be applied if it can be determined.", + "allOf": [ + { + "$ref": "#/components/schemas/PortFec" + } + ] + }, + "kr": { + "description": "Whether the link is configured in KR mode, an electrical specification generally only true for backplane link.\n\nThis defaults to `false`.", + "default": false, + "type": "boolean" + }, + "lane": { + "nullable": true, + "description": "The first lane of the port to use for the new link", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "speed": { + "description": "The requested speed of the link.", + "allOf": [ + { + "$ref": "#/components/schemas/PortSpeed" + } + ] + }, + "tx_eq": { + "nullable": true, + "description": "Transceiver equalization adjustment parameters. This defaults to `None`.", + "default": null, + "allOf": [ + { + "$ref": "#/components/schemas/TxEq" + } + ] + } + }, + "required": [ + "speed" + ] + }, + "LinkEvent": { + "type": "object", + "properties": { + "channel": { + "nullable": true, + "description": "Channel ID for sub-link-level events", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "class": { + "description": "Event class", + "type": "string" + }, + "details": { + "nullable": true, + "description": "Optionally, additional details about the event", + "type": "string" + }, + "subclass": { + "description": "Event subclass", + "type": "string" + }, + "timestamp": { + "description": "Time the event occurred. The time is represented in milliseconds, starting at an undefined time in the past. This means that timestamps can be used to measure the time between events, but not to determine the wall-clock time at which the event occurred.", + "type": "integer", + "format": "int64" + } + }, + "required": [ + "class", + "subclass", + "timestamp" + ] + }, + "LinkFecRSCounters": { + "description": "The FEC counters for a specific link, including its link ID.", + "type": "object", + "properties": { + "counters": { + "description": "The FEC counter data.", + "allOf": [ + { + "$ref": "#/components/schemas/FecRSCounters" + } + ] + }, + "link_id": { + "description": "The link ID.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "port_id": { + "description": "The switch port ID.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "counters", + "link_id", + "port_id" + ] + }, + "LinkFsmCounter": { + "description": "Reports how many times a given autoneg/link-training state has been entered", + "type": "object", + "properties": { + "current": { + "description": "Times entered since the link was last enabled", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "state_name": { + "description": "FSM state being counted", + "type": "string" + }, + "total": { + "description": "Times entered since the link was created", + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "current", + "state_name", + "total" + ] + }, + "LinkFsmCounters": { + "description": "Reports all the autoneg/link-training states a link has transitioned into.", + "type": "object", + "properties": { + "counters": { + "description": "All the states this link has entered, along with counts of how many times each state was entered.", + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkFsmCounter" + } + }, + "link_path": { + "description": "Link being reported", + "type": "string" + } + }, + "required": [ + "counters", + "link_path" + ] + }, + "LinkHistory": { + "type": "object", + "properties": { + "events": { + "description": "The set of historical events recorded", + "type": "array", + "items": { + "$ref": "#/components/schemas/LinkEvent" + } + }, + "timestamp": { + "description": "The timestamp in milliseconds at which this history was collected.", + "type": "integer", + "format": "int64" + } + }, + "required": [ + "events", + "timestamp" + ] + }, + "LinkId": { + "description": "An identifier for a link within a switch port.\n\nA switch port identified by a [`PortId`] may have multiple links within it, each identified by a `LinkId`. These are unique within a switch port only.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "LinkPcsCounters": { + "description": "The Physical Coding Sublayer (PCS) counters for a specific link.", + "type": "object", + "properties": { + "counters": { + "description": "The PCS counter data.", + "allOf": [ + { + "$ref": "#/components/schemas/PcsCounters" + } + ] + }, + "link_id": { + "description": "The link ID.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "port_id": { + "description": "The switch port ID.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "counters", + "link_id", + "port_id" + ] + }, + "LinkRMonCounters": { + "description": "The RMON counters (traffic counters) for a specific link.", + "type": "object", + "properties": { + "counters": { + "description": "The RMON counter data.", + "allOf": [ + { + "$ref": "#/components/schemas/RMonCounters" + } + ] + }, + "link_id": { + "description": "The link ID.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "port_id": { + "description": "The switch port ID.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "counters", + "link_id", + "port_id" + ] + }, + "LinkRMonCountersAll": { + "description": "The complete RMON counters (traffic counters) for a specific link.", + "type": "object", + "properties": { + "counters": { + "description": "The RMON counter data.", + "allOf": [ + { + "$ref": "#/components/schemas/RMonCountersAll" + } + ] + }, + "link_id": { + "description": "The link ID.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "port_id": { + "description": "The switch port ID.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "counters", + "link_id", + "port_id" + ] + }, + "LinkSettings": { + "description": "An object with link settings used in concert with [`PortSettings`].", + "type": "object", + "properties": { + "addrs": { + "type": "array", + "items": { + "type": "string", + "format": "ip" + }, + "uniqueItems": true + }, + "params": { + "$ref": "#/components/schemas/LinkCreate" + } + }, + "required": [ + "addrs", + "params" + ] + }, + "LinkState": { + "description": "The state of a data link with a peer.", + "oneOf": [ + { + "description": "An error was encountered while trying to configure the link in the switch hardware.", + "type": "object", + "properties": { + "config_error": { + "type": "string" + } + }, + "required": [ + "config_error" + ], + "additionalProperties": false + }, + { + "description": "The link is up.", + "type": "string", + "enum": [ + "up" + ] + }, + { + "description": "The link is down.", + "type": "string", + "enum": [ + "down" + ] + }, + { + "description": "The Link is offline due to a fault", + "type": "object", + "properties": { + "faulted": { + "$ref": "#/components/schemas/Fault" + } + }, + "required": [ + "faulted" + ], + "additionalProperties": false + }, + { + "description": "The link's state is not known.", + "type": "string", + "enum": [ + "unknown" + ] + } + ] + }, + "LinkUpCounter": { + "description": "Reports how many times a link has transitioned from Down to Up.", + "type": "object", + "properties": { + "current": { + "description": "LinkUp transitions since the link was last enabled", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "link_path": { + "description": "Link being reported", + "type": "string" + }, + "total": { + "description": "LinkUp transitions since the link was created", + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "current", + "link_path", + "total" + ] + }, + "LpPages": { + "description": "Set of AN pages sent by our link partner", + "type": "object", + "properties": { + "base_page": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "next_page1": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "next_page2": { + "type": "integer", + "format": "uint64", + "minimum": 0 + } + }, + "required": [ + "base_page", + "next_page1", + "next_page2" + ] + }, + "LtStatus": { + "description": "Link-training status for a single lane", + "type": "object", + "properties": { + "frame_lock": { + "description": "Frame lock state", + "type": "boolean" + }, + "readout_state": { + "description": "Readout for frame lock state", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "readout_training_state": { + "description": "Training state readout", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "readout_txstate": { + "description": "State machine readout for training arbiter", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "rx_trained": { + "description": "Local training finished", + "type": "boolean" + }, + "sig_det": { + "description": "Signal detect for PCS", + "type": "boolean" + }, + "training_failure": { + "description": "Link training failed", + "type": "boolean" + }, + "tx_training_data_en": { + "description": "TX control to send training pattern", + "type": "boolean" + } + }, + "required": [ + "frame_lock", + "readout_state", + "readout_training_state", + "readout_txstate", + "rx_trained", + "sig_det", + "training_failure", + "tx_training_data_en" + ] + }, + "MacAddr": { + "description": "An EUI-48 MAC address, used for layer-2 addressing.", + "type": "object", + "properties": { + "a": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "minItems": 6, + "maxItems": 6 + } + }, + "required": [ + "a" + ] + }, + "ManagementMode": { + "description": "How a switch port is managed.\n\nThe free-side devices in QSFP ports are complex devices, whose operation usually involves coordinated steps through one or more state machines. For example, when bringing up an optical link, a signal from the peer link must be detected; then a signal recovered; equalizer gains set; etc. In `Automatic` mode, all these kinds of steps are managed autonomously by switch driver software. In `Manual` mode, none of these will occur -- a switch port will only change in response to explicit requests from the operator or Oxide control plane.", + "oneOf": [ + { + "description": "A port is managed manually, by either the Oxide control plane or an operator.", + "type": "string", + "enum": [ + "manual" + ] + }, + { + "description": "A port is managed automatically by the switch software.", + "type": "string", + "enum": [ + "automatic" + ] + } + ] + }, + "MediaInterfaceId": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "description": "Media interface ID for multi-mode fiber media.\n\nSee SFF-8024 Table 4-6.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "mmf" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "id": { + "description": "Media interface ID for single-mode fiber.\n\nSee SFF-8024 Table 4-7.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "smf" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "id": { + "description": "Media interface ID for passive copper cables.\n\nSee SFF-8024 Table 4-8.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "passive_copper" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "id": { + "description": "Media interface ID for active cable assemblies.\n\nSee SFF-8024 Table 4-9.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "active_cable" + ] + } + }, + "required": [ + "id", + "type" + ] + }, + { + "type": "object", + "properties": { + "id": { + "description": "Media interface ID for BASE-T.\n\nSee SFF-8024 Table 4-10.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "base_t" + ] + } + }, + "required": [ + "id", + "type" + ] + } + ] + }, + "Monitors": { + "description": "Free-side device monitoring information.\n\nNote that all values are optional, as some specifications do not require that modules implement monitoring of those values.", + "type": "object", + "properties": { + "aux_monitors": { + "nullable": true, + "description": "Auxiliary monitoring values.\n\nThese are only available on CMIS-compatible transceivers, e.g., QSFP-DD.", + "allOf": [ + { + "$ref": "#/components/schemas/AuxMonitors" + } + ] + }, + "receiver_power": { + "nullable": true, + "description": "The measured input optical power (milliwatts);\n\nNote that due to a limitation in the SFF-8636 specification, it's possible for receiver power to be zero. See [`ReceiverPower`] for details.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ReceiverPower" + } + }, + "supply_voltage": { + "nullable": true, + "description": "The measured input supply voltage (Volts).", + "type": "number", + "format": "float" + }, + "temperature": { + "nullable": true, + "description": "The measured cage temperature (degrees C);", + "type": "number", + "format": "float" + }, + "transmitter_bias_current": { + "nullable": true, + "description": "The output laser bias current (milliamps).", + "type": "array", + "items": { + "type": "number", + "format": "float" + } + }, + "transmitter_power": { + "nullable": true, + "description": "The measured output optical power (milliwatts).", + "type": "array", + "items": { + "type": "number", + "format": "float" + } + } + } + }, + "MulticastGroupCreateExternalEntry": { + "description": "A multicast group configuration for POST requests for external (to the rack) groups.", + "type": "object", + "properties": { + "external_forwarding": { + "$ref": "#/components/schemas/ExternalForwarding" + }, + "group_ip": { + "type": "string", + "format": "ip" + }, + "internal_forwarding": { + "$ref": "#/components/schemas/InternalForwarding" + }, + "sources": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/IpSrc" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "external_forwarding", + "group_ip", + "internal_forwarding" + ] + }, + "MulticastGroupCreateUnderlayEntry": { + "description": "A multicast group configuration for POST requests for internal (to the rack) groups.", + "type": "object", + "properties": { + "group_ip": { + "$ref": "#/components/schemas/AdminScopedIpv6" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MulticastGroupMember" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "group_ip", + "members" + ] + }, + "MulticastGroupExternalResponse": { + "description": "Response structure for external multicast group operations. These groups handle IPv4 and non-admin IPv6 multicast via NAT targets.", + "type": "object", + "properties": { + "external_forwarding": { + "$ref": "#/components/schemas/ExternalForwarding" + }, + "external_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "group_ip": { + "type": "string", + "format": "ip" + }, + "internal_forwarding": { + "$ref": "#/components/schemas/InternalForwarding" + }, + "sources": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/IpSrc" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "external_forwarding", + "external_group_id", + "group_ip", + "internal_forwarding" + ] + }, + "MulticastGroupMember": { + "description": "Represents a member of a multicast group.", + "type": "object", + "properties": { + "direction": { + "$ref": "#/components/schemas/Direction" + }, + "link_id": { + "$ref": "#/components/schemas/LinkId" + }, + "port_id": { + "$ref": "#/components/schemas/PortId" + } + }, + "required": [ + "direction", + "link_id", + "port_id" + ] + }, + "MulticastGroupResponse": { + "description": "Unified response type for operations that return mixed group types.", + "oneOf": [ + { + "description": "Response structure for underlay/internal multicast group operations. These groups handle admin-scoped IPv6 multicast with full replication.", + "type": "object", + "properties": { + "external_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "group_ip": { + "$ref": "#/components/schemas/AdminScopedIpv6" + }, + "kind": { + "type": "string", + "enum": [ + "underlay" + ] + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MulticastGroupMember" + } + }, + "tag": { + "nullable": true, + "type": "string" + }, + "underlay_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "external_group_id", + "group_ip", + "kind", + "members", + "underlay_group_id" + ] + }, + { + "description": "Response structure for external multicast group operations. These groups handle IPv4 and non-admin IPv6 multicast via NAT targets.", + "type": "object", + "properties": { + "external_forwarding": { + "$ref": "#/components/schemas/ExternalForwarding" + }, + "external_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "group_ip": { + "type": "string", + "format": "ip" + }, + "internal_forwarding": { + "$ref": "#/components/schemas/InternalForwarding" + }, + "kind": { + "type": "string", + "enum": [ + "external" + ] + }, + "sources": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/IpSrc" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "external_forwarding", + "external_group_id", + "group_ip", + "internal_forwarding", + "kind" + ] + } + ] + }, + "MulticastGroupResponseResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/MulticastGroupResponse" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "MulticastGroupUnderlayResponse": { + "description": "Response structure for underlay/internal multicast group operations. These groups handle admin-scoped IPv6 multicast with full replication.", + "type": "object", + "properties": { + "external_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "group_ip": { + "$ref": "#/components/schemas/AdminScopedIpv6" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MulticastGroupMember" + } + }, + "tag": { + "nullable": true, + "type": "string" + }, + "underlay_group_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + "required": [ + "external_group_id", + "group_ip", + "members", + "underlay_group_id" + ] + }, + "MulticastGroupUpdateExternalEntry": { + "description": "A multicast group update entry for PUT requests for external (to the rack) groups.", + "type": "object", + "properties": { + "external_forwarding": { + "$ref": "#/components/schemas/ExternalForwarding" + }, + "internal_forwarding": { + "$ref": "#/components/schemas/InternalForwarding" + }, + "sources": { + "nullable": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/IpSrc" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "external_forwarding", + "internal_forwarding" + ] + }, + "MulticastGroupUpdateUnderlayEntry": { + "description": "Represents a multicast replication entry for PUT requests for internal (to the rack) groups.", + "type": "object", + "properties": { + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MulticastGroupMember" + } + }, + "tag": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "members" + ] + }, + "NatTarget": { + "description": "represents an internal NAT target", + "type": "object", + "properties": { + "inner_mac": { + "$ref": "#/components/schemas/MacAddr" + }, + "internal_ip": { + "type": "string", + "format": "ipv6" + }, + "vni": { + "$ref": "#/components/schemas/Vni" + } + }, + "required": [ + "inner_mac", + "internal_ip", + "vni" + ] + }, + "Oui": { + "description": "An Organization Unique Identifier.", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "minItems": 3, + "maxItems": 3 + }, + "OutputStatus": { + "type": "string", + "enum": [ + "valid", + "invalid" + ] + }, + "PcsCounters": { + "description": "Per-port PCS counters", + "type": "object", + "properties": { + "bad_sync_headers": { + "description": "Count of bad sync headers", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "bip_errors_per_pcs_lane": { + "description": "Bit Inteleaved Parity errors (per lane)", + "type": "array", + "items": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "block_lock_loss": { + "description": "Count of block-lock loss detections", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "errored_blocks": { + "description": "Count of errored blocks", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "hi_ber": { + "description": "Count of high bit error rate events", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "invalid_errors": { + "description": "Count of invalid error events", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "port": { + "description": "Port being tracked", + "type": "string" + }, + "sync_loss": { + "description": "Count of sync loss detections", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "unknown_errors": { + "description": "Count of unknown error events", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "valid_errors": { + "description": "Count of valid error events", + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "bad_sync_headers", + "bip_errors_per_pcs_lane", + "block_lock_loss", + "errored_blocks", + "hi_ber", + "invalid_errors", + "port", + "sync_loss", + "unknown_errors", + "valid_errors" + ] + }, + "Polarity": { + "type": "string", + "enum": [ + "Normal", + "Inverted" + ] + }, + "PortFec": { + "type": "string", + "enum": [ + "None", + "Firecode", + "RS" + ] + }, + "PortId": { + "example": "qsfp0", + "title": "PortId", + "description": "Physical switch port identifier", + "oneOf": [ + { + "title": "internal", + "type": "string", + "pattern": "(^[iI][nN][tT]0$)" + }, + { + "title": "rear", + "type": "string", + "pattern": "(^[rR][eE][aA][rR](([0-9])|([1-2][0-9])|(3[0-1]))$)" + }, + { + "title": "qsfp", + "type": "string", + "pattern": "(^[qQ][sS][fF][pP](([0-9])|([1-2][0-9])|(3[0-1]))$)" + } + ] + }, + "PortMedia": { + "type": "string", + "enum": [ + "Copper", + "Optical", + "CPU", + "None", + "Unknown" + ] + }, + "PortPrbsMode": { + "description": "Legal PRBS modes", + "type": "string", + "enum": [ + "Mode31", + "Mode23", + "Mode15", + "Mode13", + "Mode11", + "Mode9", + "Mode7", + "Mission" + ] + }, + "PortSettings": { + "description": "A port settings transaction object. When posted to the `/port-settings/{port_id}` API endpoint, these settings will be applied holistically, and to the extent possible atomically to a given port.", + "type": "object", + "properties": { + "links": { + "description": "The link settings to apply to the port on a per-link basis. Any links not in this map that are resident on the switch port will be removed. Any links that are in this map that are not resident on the switch port will be added. Any links that are resident on the switch port and in this map, and are different, will be modified. Links are indexed by spatial index within the port.", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/LinkSettings" + } + } + }, + "required": [ + "links" + ] + }, + "PortSpeed": { + "description": "Speeds with which a single port may be configured", + "type": "string", + "enum": [ + "Speed0G", + "Speed1G", + "Speed10G", + "Speed25G", + "Speed40G", + "Speed50G", + "Speed100G", + "Speed200G", + "Speed400G" + ] + }, + "PowerMode": { + "description": "The power mode of a module.", + "type": "object", + "properties": { + "software_override": { + "nullable": true, + "description": "Whether the module is configured for software override of power control.\n\nIf the module is in `PowerState::Off`, this can't be determined, and `None` is returned.", + "type": "boolean" + }, + "state": { + "description": "The actual power state.", + "allOf": [ + { + "$ref": "#/components/schemas/PowerState" + } + ] + } + }, + "required": [ + "state" + ] + }, + "PowerState": { + "description": "An allowed power state for the module.", + "oneOf": [ + { + "description": "A module is entirely powered off, using the EFuse.", + "type": "string", + "enum": [ + "off" + ] + }, + { + "description": "Power is enabled to the module, but module remains in low-power mode.\n\nIn this state, modules will not establish a link or transmit traffic, but they may be managed and queried for information through their memory maps.", + "type": "string", + "enum": [ + "low" + ] + }, + { + "description": "The module is in high-power mode.\n\nNote that additional configuration may be required to correctly configure the module, such as described in SFF-8636 rev 2.10a table 6-10, and that the _host side_ is responsible for ensuring that the relevant configuration is applied.", + "type": "string", + "enum": [ + "high" + ] + } + ] + }, + "RMonCounters": { + "description": "High level subset of the RMon counters maintained by the Tofino ASIC", + "type": "object", + "properties": { + "crc_error_stomped": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "fragments_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frame_too_long": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_dropped_buffer_full": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_all": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_ok": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_all": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_ok": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_with_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_with_any_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_rx_in_good_frames": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_tx_total": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_tx_without_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "port": { + "type": "string" + } + }, + "required": [ + "crc_error_stomped", + "fragments_rx", + "frame_too_long", + "frames_dropped_buffer_full", + "frames_rx_all", + "frames_rx_ok", + "frames_tx_all", + "frames_tx_ok", + "frames_tx_with_error", + "frames_with_any_error", + "octets_rx", + "octets_rx_in_good_frames", + "octets_tx_total", + "octets_tx_without_error", + "port" + ] + }, + "RMonCountersAll": { + "description": "All of the RMon counters maintained by the Tofino ASIC", + "type": "object", + "properties": { + "crc_error_stomped": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "fragments_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frame_too_long": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_dropped_buffer_full": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_all": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_indersized": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_1024_1518": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_128_255": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_1519_2047": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_2048_4095": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_256_511": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_4096_8191": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_512_1023": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_65_127": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_8192_9215": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_9216": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_eq_64": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_length_lt_64": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_oftype_pause": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_ok": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_oversized": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_any_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_broadcast_addresses": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_fcs_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_length_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_multicast_addresses": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_rx_with_unicast_addresses": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_truncated": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_all": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_broadcast": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_1024_1518": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_128_255": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_1519_2047": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_2048_4095": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_256_511": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_4096_8191": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_512_1023": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_65_127": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_8192_9215": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_9216": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_eq_64": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_length_lt_64": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_multicast": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_ok": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_pause": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_pri_pause": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_unicast": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_vlan": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "frames_tx_with_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "jabber_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_rx_in_good_frames": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_tx_total": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "octets_tx_without_error": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "port": { + "type": "string" + }, + "pri0_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri0_framex_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri1_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri1_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri2_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri2_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri3_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri3_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri4_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri4_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri5_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri5_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri6_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri6_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri7_frames_rx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "pri7_frames_tx": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "priority_pause_frames": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri0_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri1_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri2_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri3_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri4_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri5_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri6_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_pri7_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_standard_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "rx_vlan_frames_good": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri0_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri1_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri2_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri3_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri4_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri5_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri6_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "tx_pri7_pause_1us_count": { + "type": "integer", + "format": "uint64", + "minimum": 0 + } + }, + "required": [ + "crc_error_stomped", + "fragments_rx", + "frame_too_long", + "frames_dropped_buffer_full", + "frames_rx_all", + "frames_rx_indersized", + "frames_rx_length_1024_1518", + "frames_rx_length_128_255", + "frames_rx_length_1519_2047", + "frames_rx_length_2048_4095", + "frames_rx_length_256_511", + "frames_rx_length_4096_8191", + "frames_rx_length_512_1023", + "frames_rx_length_65_127", + "frames_rx_length_8192_9215", + "frames_rx_length_9216", + "frames_rx_length_eq_64", + "frames_rx_length_lt_64", + "frames_rx_oftype_pause", + "frames_rx_ok", + "frames_rx_oversized", + "frames_rx_with_any_error", + "frames_rx_with_broadcast_addresses", + "frames_rx_with_fcs_error", + "frames_rx_with_length_error", + "frames_rx_with_multicast_addresses", + "frames_rx_with_unicast_addresses", + "frames_truncated", + "frames_tx_all", + "frames_tx_broadcast", + "frames_tx_length_1024_1518", + "frames_tx_length_128_255", + "frames_tx_length_1519_2047", + "frames_tx_length_2048_4095", + "frames_tx_length_256_511", + "frames_tx_length_4096_8191", + "frames_tx_length_512_1023", + "frames_tx_length_65_127", + "frames_tx_length_8192_9215", + "frames_tx_length_9216", + "frames_tx_length_eq_64", + "frames_tx_length_lt_64", + "frames_tx_multicast", + "frames_tx_ok", + "frames_tx_pause", + "frames_tx_pri_pause", + "frames_tx_unicast", + "frames_tx_vlan", + "frames_tx_with_error", + "jabber_rx", + "octets_rx", + "octets_rx_in_good_frames", + "octets_tx_total", + "octets_tx_without_error", + "port", + "pri0_frames_rx", + "pri0_framex_tx", + "pri1_frames_rx", + "pri1_frames_tx", + "pri2_frames_rx", + "pri2_frames_tx", + "pri3_frames_rx", + "pri3_frames_tx", + "pri4_frames_rx", + "pri4_frames_tx", + "pri5_frames_rx", + "pri5_frames_tx", + "pri6_frames_rx", + "pri6_frames_tx", + "pri7_frames_rx", + "pri7_frames_tx", + "priority_pause_frames", + "rx_pri0_pause_1us_count", + "rx_pri1_pause_1us_count", + "rx_pri2_pause_1us_count", + "rx_pri3_pause_1us_count", + "rx_pri4_pause_1us_count", + "rx_pri5_pause_1us_count", + "rx_pri6_pause_1us_count", + "rx_pri7_pause_1us_count", + "rx_standard_pause_1us_count", + "rx_vlan_frames_good", + "tx_pri0_pause_1us_count", + "tx_pri1_pause_1us_count", + "tx_pri2_pause_1us_count", + "tx_pri3_pause_1us_count", + "tx_pri4_pause_1us_count", + "tx_pri5_pause_1us_count", + "tx_pri6_pause_1us_count", + "tx_pri7_pause_1us_count" + ] + }, + "ReceiverPower": { + "description": "Measured receiver optical power.\n\nThe SFF specifications allow for devices to monitor input optical power in several ways. It may either be an average power, over some unspecified time, or a peak-to-peak power. The latter is often abbreviated OMA, for Optical Modulation Amplitude. Again the time interval for peak-to-peak measurments are not specified.\n\nDetails -------\n\nThe SFF-8636 specification has an unfortunate limitation. There is no separate advertisement for whether a module supports measurements of receiver power. Instead, the _kind_ of measurement is advertised. The _same bit value_ could mean that either a peak-to-peak measurement is supported, or the measurements are not supported at all. Thus values of `PeakToPeak(0.0)` may mean that power measurements are not supported.", + "oneOf": [ + { + "description": "The measurement is represents average optical power, in mW.", + "type": "object", + "properties": { + "average": { + "type": "number", + "format": "float" + } + }, + "required": [ + "average" + ], + "additionalProperties": false + }, + { + "description": "The measurement represents a peak-to-peak, in mW.", + "type": "object", + "properties": { + "peak_to_peak": { + "type": "number", + "format": "float" + } + }, + "required": [ + "peak_to_peak" + ], + "additionalProperties": false + } + ] + }, + "Route": { + "oneOf": [ + { + "type": "object", + "properties": { + "V4": { + "$ref": "#/components/schemas/Ipv4Route" + } + }, + "required": [ + "V4" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "V6": { + "$ref": "#/components/schemas/Ipv6Route" + } + }, + "required": [ + "V6" + ], + "additionalProperties": false + } + ] + }, + "RxSigInfo": { + "description": "Per-lane Rx signal information", + "type": "object", + "properties": { + "phy_ready": { + "description": "CDR lock achieved", + "type": "boolean" + }, + "ppm": { + "description": "Apparent PPM difference between local and remote", + "type": "integer", + "format": "int32" + }, + "sig_detect": { + "description": "Rx signal detected", + "type": "boolean" + } + }, + "required": [ + "phy_ready", + "ppm", + "sig_detect" + ] + }, + "SerdesEye": { + "description": "Eye height(s) for a single lane in mv", + "oneOf": [ + { + "type": "object", + "properties": { + "Nrz": { + "type": "number", + "format": "float" + } + }, + "required": [ + "Nrz" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "Pam4": { + "type": "object", + "properties": { + "eye1": { + "type": "number", + "format": "float" + }, + "eye2": { + "type": "number", + "format": "float" + }, + "eye3": { + "type": "number", + "format": "float" + } + }, + "required": [ + "eye1", + "eye2", + "eye3" + ] + } + }, + "required": [ + "Pam4" + ], + "additionalProperties": false + } + ] + }, + "Sff8636Datapath": { + "description": "The datapath of an SFF-8636 module.\n\nThis describes the state of a single lane in an SFF module. It includes information about input and output signals, faults, and controls.", + "type": "object", + "properties": { + "rx_cdr_enabled": { + "description": "Media-side transmit Clock and Data Recovery (CDR) enable status.\n\nCDR is the process by which the module enages an internal retimer function, through which the module attempts to recovery a clock signal directly from the input bitstream.", + "type": "boolean" + }, + "rx_lol": { + "description": "Media-side loss of lock flag.\n\nThis is true if the module is not able to extract a clock signal from the media-side signal (usually optical).", + "type": "boolean" + }, + "rx_los": { + "description": "Media-side loss of signal flag.\n\nThis is true if there is no detected input signal from the media-side (usually optical).", + "type": "boolean" + }, + "tx_adaptive_eq_fault": { + "description": "Flag indicating a fault in adaptive transmit equalization.", + "type": "boolean" + }, + "tx_cdr_enabled": { + "description": "Host-side transmit Clock and Data Recovery (CDR) enable status.\n\nCDR is the process by which the module enages an internal retimer function, through which the module attempts to recovery a clock signal directly from the input bitstream.", + "type": "boolean" + }, + "tx_enabled": { + "description": "Software control of output transmitter.", + "type": "boolean" + }, + "tx_fault": { + "description": "Flag indicating a fault in the transmitter and/or laser.", + "type": "boolean" + }, + "tx_lol": { + "description": "Host-side loss of lock flag.\n\nThis is true if the module is not able to extract a clock signal from the host-side electrical signal.", + "type": "boolean" + }, + "tx_los": { + "description": "Host-side loss of signal flag.\n\nThis is true if there is no detected electrical signal from the host-side serdes.", + "type": "boolean" + } + }, + "required": [ + "rx_cdr_enabled", + "rx_lol", + "rx_los", + "tx_adaptive_eq_fault", + "tx_cdr_enabled", + "tx_enabled", + "tx_fault", + "tx_lol", + "tx_los" + ] + }, + "SffComplianceCode": { + "description": "The compliance code for an SFF-8636 module.\n\nThese values record a specification compliance code, from SFF-8636 Table 6-17, or an extended specification compliance code, from SFF-8024 Table 4-4.", + "oneOf": [ + { + "type": "object", + "properties": { + "code": { + "description": "Extended electrical or optical interface codes", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "extended" + ] + } + }, + "required": [ + "code", + "type" + ] + }, + { + "type": "object", + "properties": { + "code": { + "description": "The Ethernet specification implemented by a module.", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ethernet" + ] + } + }, + "required": [ + "code", + "type" + ] + } + ] + }, + "SidecarCableLeg": { + "description": "The leg of the Sidecar-internal cable.\n\nThis describes the leg on the cabling that connects the pins on the Tofino ASIC to the Sidecar chassis connector.", + "type": "string", + "enum": [ + "A", + "C" + ] + }, + "SidecarConnector": { + "description": "The Sidecar chassis connector mating the backplane and internal cabling.\n\nThis describes the \"group\" of backplane links that all terminate in one connector on the Sidecar itself. This is the connection point between a cable on the backplane itself and the Sidecar chassis.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "SwitchIdentifiers": { + "description": "Identifiers for a switch.", + "type": "object", + "properties": { + "asic_backend": { + "description": "Asic backend (compiler target) responsible for these identifiers.", + "type": "string" + }, + "fab": { + "nullable": true, + "description": "Fabrication plant identifier.", + "type": "string", + "minLength": 1, + "maxLength": 1 + }, + "lot": { + "nullable": true, + "description": "Lot identifier.", + "type": "string", + "minLength": 1, + "maxLength": 1 + }, + "model": { + "description": "The model number of the switch being managed.", + "type": "string" + }, + "revision": { + "description": "The revision number of the switch being managed.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "serial": { + "description": "The serial number of the switch being managed.", + "type": "string" + }, + "sidecar_id": { + "description": "Unique identifier for the chip.", + "type": "string", + "format": "uuid" + }, + "slot": { + "description": "The slot number of the switch being managed.\n\nMGS uses u16 for this internally.", + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "wafer": { + "nullable": true, + "description": "Wafer number within the lot.", + "type": "integer", + "format": "uint8", + "minimum": 0 + }, + "wafer_loc": { + "nullable": true, + "description": "The wafer location as (x, y) coordinates on the wafer, represented as an array due to the lack of tuple support in OpenAPI.", + "type": "array", + "items": { + "type": "integer", + "format": "int16" + }, + "minItems": 2, + "maxItems": 2 + } + }, + "required": [ + "asic_backend", + "model", + "revision", + "serial", + "sidecar_id", + "slot" + ] + }, + "SwitchPort": { + "description": "A physical port on the Sidecar switch.", + "type": "object", + "properties": { + "management_mode": { + "description": "How the QSFP device is managed.\n\nSee `ManagementMode` for details.", + "allOf": [ + { + "$ref": "#/components/schemas/ManagementMode" + } + ] + }, + "port_id": { + "description": "The identifier for the switch port.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + }, + "transceiver": { + "nullable": true, + "description": "Details about a transceiver module inserted into the switch port.\n\nIf there is no transceiver at all, this will be `None`.", + "allOf": [ + { + "$ref": "#/components/schemas/Transceiver" + } + ] + } + }, + "required": [ + "port_id" + ] + }, + "Table": { + "description": "Represents the contents of a P4 table", + "type": "object", + "properties": { + "entries": { + "description": "There will be an entry for each populated slot in the table", + "type": "array", + "items": { + "$ref": "#/components/schemas/TableEntry" + } + }, + "name": { + "description": "A user-friendly name for the table", + "type": "string" + }, + "size": { + "description": "The maximum number of entries the table can hold", + "type": "integer", + "format": "uint", + "minimum": 0 + } + }, + "required": [ + "entries", + "name", + "size" + ] + }, + "TableCounterEntry": { + "type": "object", + "properties": { + "data": { + "description": "Counter values", + "allOf": [ + { + "$ref": "#/components/schemas/CounterData" + } + ] + }, + "keys": { + "description": "Names and values of each of the key fields.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "data", + "keys" + ] + }, + "TableEntry": { + "description": "Each entry in a P4 table is addressed by matching against a set of key values. If an entry is found, an action is taken with an action-specific set of arguments.\n\nNote: each entry will have the same key fields and each instance of any given action will have the same argument names, so a vector of TableEntry structs will contain a signficant amount of redundant data. We could consider tightening this up by including a schema of sorts in the \"struct Table\".", + "type": "object", + "properties": { + "action": { + "description": "Name of the action to take on a match", + "type": "string" + }, + "action_args": { + "description": "Names and values for the arguments to the action implementation.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "keys": { + "description": "Names and values of each of the key fields.", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "action", + "action_args", + "keys" + ] + }, + "TfportData": { + "description": "The per-link data consumed by tfportd", + "type": "object", + "properties": { + "asic_id": { + "description": "The lower-level ASIC ID used to refer to this object in the switch driver software.", + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "ipv6_enabled": { + "description": "Is ipv6 enabled for this link", + "type": "boolean" + }, + "link_id": { + "description": "The link ID for this link.", + "allOf": [ + { + "$ref": "#/components/schemas/LinkId" + } + ] + }, + "link_local": { + "nullable": true, + "description": "The IPv6 link-local address of the link, if it exists.", + "type": "string", + "format": "ipv6" + }, + "mac": { + "description": "The MAC address for the link.", + "allOf": [ + { + "$ref": "#/components/schemas/MacAddr" + } + ] + }, + "port_id": { + "description": "The switch port ID for this link.", + "allOf": [ + { + "$ref": "#/components/schemas/PortId" + } + ] + } + }, + "required": [ + "asic_id", + "ipv6_enabled", + "link_id", + "mac", + "port_id" + ] + }, + "TofinoMemoryErrorDiagnostic": { + "type": "object", + "properties": { + "addr": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "data_0": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "data_1": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "exp_0": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "exp_1": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "mask_0": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "mask_1": { + "type": "integer", + "format": "uint64", + "minimum": 0 + } + }, + "required": [ + "addr", + "data_0", + "data_1", + "exp_0", + "exp_1", + "mask_0", + "mask_1" + ] + }, + "TofinoMemoryTestArgs": { + "type": "object", + "properties": { + "pattern": { + "$ref": "#/components/schemas/TofinoMemoryTestPattern" + } + }, + "required": [ + "pattern" + ] + }, + "TofinoMemoryTestPattern": { + "type": "string", + "enum": [ + "Random", + "Zeroes", + "Ones", + "Checkerboard", + "InverseCheckerboard", + "Prbs" + ] + }, + "TofinoMemtestResult": { + "type": "object", + "properties": { + "data_error": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TofinoMemoryErrorDiagnostic" + } + }, + "ind_read_error": { + "type": "boolean" + }, + "ind_read_error_addr": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "ind_write_error": { + "type": "boolean" + }, + "ind_write_error_addr": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "num_data_errors": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "num_dma_cmplts_rcvd": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "num_dma_msgs_sent": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "overall_success": { + "type": "boolean" + }, + "write_block_error": { + "type": "boolean" + }, + "write_list_error": { + "type": "boolean" + } + }, + "required": [ + "data_error", + "ind_read_error", + "ind_read_error_addr", + "ind_write_error", + "ind_write_error_addr", + "num_data_errors", + "num_dma_cmplts_rcvd", + "num_dma_msgs_sent", + "overall_success", + "write_block_error", + "write_list_error" + ] + }, + "Transceiver": { + "description": "The state of a transceiver in a QSFP switch port.", + "oneOf": [ + { + "description": "The transceiver could not be managed due to a power fault.", + "type": "object", + "properties": { + "info": { + "$ref": "#/components/schemas/FaultReason" + }, + "state": { + "type": "string", + "enum": [ + "faulted" + ] + } + }, + "required": [ + "info", + "state" + ] + }, + { + "description": "A transceiver was present, but unsupported and automatically disabled.", + "type": "object", + "properties": { + "state": { + "type": "string", + "enum": [ + "unsupported" + ] + } + }, + "required": [ + "state" + ] + }, + { + "description": "A transceiver is present and supported.", + "type": "object", + "properties": { + "info": { + "$ref": "#/components/schemas/TransceiverInfo" + }, + "state": { + "type": "string", + "enum": [ + "supported" + ] + } + }, + "required": [ + "info", + "state" + ] + } + ] + }, + "TransceiverInfo": { + "description": "Information about a QSFP transceiver.\n\nThis stores the most relevant information about a transceiver module, such as vendor info or power. Each field may be missing, indicating it could not be determined.", + "type": "object", + "properties": { + "electrical_mode": { + "description": "The electrical mode of the transceiver.\n\nSee [`ElectricalMode`] for details.", + "allOf": [ + { + "$ref": "#/components/schemas/ElectricalMode" + } + ] + }, + "in_reset": { + "nullable": true, + "description": "True if the module is currently in reset.", + "type": "boolean" + }, + "interrupt_pending": { + "nullable": true, + "description": "True if there is a pending interrupt on the module.", + "type": "boolean" + }, + "power_mode": { + "nullable": true, + "description": "The power mode of the transceiver.", + "allOf": [ + { + "$ref": "#/components/schemas/PowerMode" + } + ] + }, + "vendor_info": { + "nullable": true, + "description": "Vendor and part identifying information.\n\nThe information will not be populated if it could not be read.", + "allOf": [ + { + "$ref": "#/components/schemas/VendorInfo" + } + ] + } + }, + "required": [ + "electrical_mode" + ] + }, + "TxEq": { + "description": "Parameters to adjust the transceiver equalization settings for a link on a switch. These parameters match those available on a tofino-based sidecar, and may need to be adapted when we move to a new switch ASIC.", + "type": "object", + "properties": { + "main": { + "nullable": true, + "type": "integer", + "format": "int32" + }, + "post1": { + "nullable": true, + "type": "integer", + "format": "int32" + }, + "post2": { + "nullable": true, + "type": "integer", + "format": "int32" + }, + "pre1": { + "nullable": true, + "type": "integer", + "format": "int32" + }, + "pre2": { + "nullable": true, + "type": "integer", + "format": "int32" + } + } + }, + "TxEqSwHw": { + "description": "This represents the software-determined equalization value initially assigned to the transceiver and the value actually being used by the hardware. The values may differ on transceivers that are capable of tuning their own settings at run time.", + "type": "object", + "properties": { + "hw": { + "$ref": "#/components/schemas/TxEq" + }, + "sw": { + "$ref": "#/components/schemas/TxEq" + } + }, + "required": [ + "hw", + "sw" + ] + }, + "Vendor": { + "description": "Vendor-specific information about a transceiver module.", + "type": "object", + "properties": { + "date": { + "nullable": true, + "type": "string" + }, + "name": { + "type": "string" + }, + "oui": { + "$ref": "#/components/schemas/Oui" + }, + "part": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "serial": { + "type": "string" + } + }, + "required": [ + "name", + "oui", + "part", + "revision", + "serial" + ] + }, + "VendorInfo": { + "description": "The vendor information for a transceiver module.", + "type": "object", + "properties": { + "identifier": { + "description": "The SFF-8024 identifier.", + "type": "string" + }, + "vendor": { + "description": "The vendor information.", + "allOf": [ + { + "$ref": "#/components/schemas/Vendor" + } + ] + } + }, + "required": [ + "identifier", + "vendor" + ] + }, + "Vni": { + "description": "A Geneve Virtual Network Identifier.\n\nA Geneve VNI is a 24-bit value used to identify virtual networks encapsulated using the Generic Network Virtualization Encapsulation (Geneve) protocol (RFC 8926).", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "ipv4ResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "type": "string", + "format": "ipv4" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, + "ipv6ResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "type": "string", + "format": "ipv6" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + } + }, + "responses": { + "Error": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } +} diff --git a/openapi/dpd/dpd-latest.json b/openapi/dpd/dpd-latest.json index 9ec6bba..80125c0 120000 --- a/openapi/dpd/dpd-latest.json +++ b/openapi/dpd/dpd-latest.json @@ -1 +1 @@ -dpd-4.0.0-42069e.json \ No newline at end of file +dpd-5.0.0-8b201d.json \ No newline at end of file diff --git a/swadm/Cargo.toml b/swadm/Cargo.toml index bc14da0..c168878 100644 --- a/swadm/Cargo.toml +++ b/swadm/Cargo.toml @@ -15,6 +15,7 @@ dpd-client.workspace = true futures.workspace = true oxide-tokio-rt.workspace = true oxnet.workspace = true +reqwest.workspace = true slog.workspace = true tabwriter.workspace = true tokio.workspace = true diff --git a/swadm/src/main.rs b/swadm/src/main.rs index 59f7c38..ac8bf2a 100644 --- a/swadm/src/main.rs +++ b/swadm/src/main.rs @@ -7,6 +7,7 @@ use std::convert::TryFrom; use std::io; use std::str::FromStr; +use std::time::Duration; use anyhow::Context; @@ -16,6 +17,7 @@ use dpd_client::Client; use dpd_client::ClientState; use dpd_client::default_port; use dpd_client::types; +use dpd_client::types::TofinoMemoryTestPattern; mod addr; mod arp; @@ -92,6 +94,33 @@ enum Commands { cmd: compliance::Compliance, }, Identifiers, + Memtest { + #[clap(value_enum)] + pattern: TestPattern, + }, +} + +#[derive(Debug, clap::ValueEnum, Clone, Copy)] +pub enum TestPattern { + Random, + Zeroes, + Ones, + Checkerboard, + InverseCheckerboard, + Prbs, +} + +impl From for TofinoMemoryTestPattern { + fn from(value: TestPattern) -> Self { + match value { + TestPattern::Random => Self::Random, + TestPattern::Zeroes => Self::Zeroes, + TestPattern::Ones => Self::Ones, + TestPattern::Checkerboard => Self::Checkerboard, + TestPattern::InverseCheckerboard => Self::InverseCheckerboard, + TestPattern::Prbs => Self::Prbs, + } + } } // A LinkPath or "loopback", used when either is appropriate. @@ -210,7 +239,15 @@ async fn main_impl() -> anyhow::Result<()> { let host = opts.host.unwrap_or_else(|| "localhost".to_string()); let log = slog::Logger::root(slog::Discard, slog::o!()); let client_state = ClientState { tag: String::from("cli"), log }; - let client = Client::new(&format!("http://{host}:{port}"), client_state); + //let client = Client::new(&format!("http://{host}:{port}"), client_state); + let c = reqwest::Client::builder() + .timeout(Duration::from_secs(60 * 60 * 24)) + .build()?; + let client = Client::new_with_client( + &format!("http://{host}:{port}"), + c, + client_state, + ); match opts.cmd { Commands::DpdBuildInfo => build_info(&client).await, @@ -233,19 +270,37 @@ async fn main_impl() -> anyhow::Result<()> { compliance::compliance_cmd(&client, compliance).await } Commands::Identifiers => identifiers(), + Commands::Memtest { pattern } => memtest(&client, pattern).await, } } fn identifiers() -> anyhow::Result<()> { - /* - let t = tofino::get_tofino().unwrap().unwrap(); - let pci = t.open_pci().unwrap(); - */ let pci = tofino::pci::Pci::new("/dev/tofino/1", tofino::REGISTER_SIZE).unwrap(); let fuse = tofino::fuse::Fuse::read(&pci).unwrap(); let chip_id: tofino::fuse::ChipId = fuse.chip_id.into(); + println!( + "device id: {}", + match fuse.device_id { + 0x0100 => "A0".to_owned(), + 0x0110 => match fuse.rev_num { + 0 => "B0".to_owned(), + 2 => "B1".to_owned(), + _ => format!("{:016x}", fuse.device_id), + }, + _ => format!("{:016x}", fuse.device_id), + } + ); + println!("device rev: {}", fuse.rev_num); println!("chip id: {:016x}", fuse.chip_id); println!("{}", chip_id); Ok(()) } + +async fn memtest(client: &Client, pattern: TestPattern) -> anyhow::Result<()> { + let result = client + .memtest(&types::TofinoMemoryTestArgs { pattern: pattern.into() }) + .await?; + println!("{result:#?}"); + Ok(()) +}