Skip to content

Commit 087c974

Browse files
authored
Add an API to temporarily disable an interface (#20)
1 parent ce952e6 commit 087c974

File tree

11 files changed

+268
-84
lines changed

11 files changed

+268
-84
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adm/src/main.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ enum Interface {
122122
/// List all configured interfaces
123123
#[structopt(visible_alias = "ls")]
124124
List,
125+
/// Locally disable lldp on the interface. This refers strictly to
126+
/// local interface plumbing, and is independent of the LLDP protocol's
127+
/// administrative tx/rx disablement.
128+
Disable { iface: String },
129+
/// Clear the locally set disable flag.
130+
Enable { iface: String },
125131
}
126132

127133
#[derive(Debug, StructOpt)]
@@ -328,7 +334,15 @@ fn display_neighbor(n: &types::Neighbor) {
328334
}
329335

330336
fn display_interface(i: &types::Interface) {
331-
println!("port: {} interface: {}", i.port, i.iface);
337+
println!(
338+
"port: {} interface: {}{}",
339+
i.port,
340+
i.iface,
341+
match i.disabled {
342+
true => " [Disabled]",
343+
false => "",
344+
}
345+
);
332346
display_sysinfo(&i.system_info);
333347
}
334348

@@ -465,6 +479,16 @@ async fn main() -> anyhow::Result<()> {
465479
.await
466480
.map(|r| r.into_inner().iter().for_each(display_interface))
467481
.context("failed to remove interface"),
482+
Interface::Disable { iface } => client
483+
.interface_set_disabled(&iface, true)
484+
.await
485+
.map(|_| ())
486+
.context("failed to set the disabled flag"),
487+
Interface::Enable { iface } => client
488+
.interface_set_disabled(&iface, false)
489+
.await
490+
.map(|_| ())
491+
.context("failed to clear the disabled flag"),
468492
},
469493
Commands::Neighbors => {
470494
for iface in client

dpd-client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ serde.workspace = true
1616
serde_json.workspace = true
1717
slog.workspace = true
1818
tokio = { workspace = true, features = [ "full" ] }
19+
uuid.workspace = true
1920

2021
common.workspace = true
2122
progenitor.workspace = true

lldpd/src/api_server.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ async fn sys_clear_management_addr(
274274
pub struct Interface {
275275
pub port: String,
276276
pub iface: String,
277+
pub disabled: bool,
277278
pub system_info: types::SystemInfo,
278279
}
279280

@@ -364,6 +365,7 @@ async fn interface_get(
364365
Interface {
365366
port: interface.clone(),
366367
iface: i.iface.clone(),
368+
disabled: i.disabled,
367369
system_info: (&interfaces::build_lldpdu(&switchinfo, &i))
368370
.into(),
369371
}
@@ -391,6 +393,7 @@ async fn interface_list(
391393
Interface {
392394
port: name.clone(),
393395
iface: i.iface.clone(),
396+
disabled: i.disabled,
394397
system_info: (&interfaces::build_lldpdu(&switchinfo, &i))
395398
.into(),
396399
}
@@ -399,6 +402,24 @@ async fn interface_list(
399402
))
400403
}
401404

405+
#[endpoint {
406+
method = POST,
407+
path = "/interface/{iface}/disabled",
408+
}]
409+
async fn interface_set_disabled(
410+
rqctx: RequestContext<Arc<Global>>,
411+
path: Path<InterfacePathParams>,
412+
body: TypedBody<bool>,
413+
) -> Result<HttpResponseUpdatedNoContent, HttpError> {
414+
let global: &Global = rqctx.context();
415+
let inner = path.into_inner();
416+
let val = body.into_inner();
417+
interfaces::disabled_set(global, &inner.iface, val)
418+
.await
419+
.map_err(|e| e.into())
420+
.map(|_| HttpResponseUpdatedNoContent())
421+
}
422+
402423
#[endpoint {
403424
method = POST,
404425
path = "/interface/{iface}/chassis_id",
@@ -913,6 +934,7 @@ pub fn http_api() -> dropshot::ApiDescription<Arc<Global>> {
913934
api.register(interface_del).unwrap();
914935
api.register(interface_list).unwrap();
915936
api.register(interface_get).unwrap();
937+
api.register(interface_set_disabled).unwrap();
916938
api.register(interface_set_chassis_id).unwrap();
917939
api.register(interface_del_chassis_id).unwrap();
918940
api.register(interface_set_port_id).unwrap();

lldpd/src/errors.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ pub enum LldpdError {
3535
Dlpi(String),
3636
#[error("Interrupted system call")]
3737
EIntr,
38+
#[error("packet read timed out")]
39+
ETimedOut,
3840
#[error("error: {0}")]
3941
Other(String),
4042
}
@@ -91,6 +93,9 @@ impl convert::From<LldpdError> for dropshot::HttpError {
9193
LldpdError::EIntr => dropshot::HttpError::for_internal_error(
9294
"interrupted system call".into(),
9395
),
96+
LldpdError::ETimedOut => dropshot::HttpError::for_internal_error(
97+
"network timeout".into(),
98+
),
9499
LldpdError::Other(e) => dropshot::HttpError::for_internal_error(e),
95100
}
96101
}

0 commit comments

Comments
 (0)