netcfg: interface enable/disable control (ip link set eth0 down/up)

LinkDevice trait gains is_enabled() and set_enabled() with defaults.
EthernetLink stores enabled flag (default: true). When disabled,
link_state() reports 'down' regardless of hardware_address presence.

netcfg/ifaces/eth0/enabled is rw:
  cat /scheme/netcfg/ifaces/eth0/enabled  →  'up' or 'down'
  echo up   > .../enabled  →  bring interface up
  echo down > .../enabled  →  bring interface down
  echo on/off/1/0/yes/no  →  also accepted

Mirrors Linux 'ip link set dev <state>'.

Pre-existing link state (hardware_address Some/None) unchanged;
the enabled flag adds a software override layer that can be
toggled without restarting the netstack.
This commit is contained in:
Red Bear OS
2026-07-08 18:24:02 +03:00
parent 89083a25f9
commit 9bab466704
4 changed files with 58 additions and 2 deletions
+17 -1
View File
@@ -87,6 +87,7 @@ pub struct EthernetLink {
ip_address: Option<IpCidr>,
qdisc_config: QdiscConfig,
mtu: usize,
enabled: bool,
stats: Stats,
arp_requests: u64,
arp_replies: u64,
@@ -123,6 +124,7 @@ impl EthernetLink {
slaac_state: Default::default(),
qdisc_config: QdiscConfig::default(),
mtu: Self::MTU,
enabled: true,
stats: Stats::default(),
neighbor_cache: Default::default(),
arp_requests: 0,
@@ -882,7 +884,13 @@ impl LinkDevice for EthernetLink {
}
fn link_state(&self) -> &'static str {
if self.hardware_address.is_some() { "up" } else { "down" }
if !self.enabled {
"down"
} else if self.hardware_address.is_some() {
"up"
} else {
"down"
}
}
fn qdisc_info(&self) -> String {
@@ -904,5 +912,13 @@ impl LinkDevice for EthernetLink {
fn set_mtu(&mut self, mtu: usize) {
self.mtu = mtu.clamp(576, 9000);
}
fn is_enabled(&self) -> bool {
self.enabled
}
fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
}
+6
View File
@@ -59,6 +59,12 @@ pub trait LinkDevice {
fn set_mtu(&mut self, _mtu: usize) {}
fn is_enabled(&self) -> bool {
true
}
fn set_enabled(&mut self, _enabled: bool) {}
fn link_state(&self) -> &'static str {
"unknown"
}
+34
View File
@@ -522,6 +522,40 @@ fn mk_root_node(
None => "Device not found\n".into(),
}
}
},
"enabled" => {
rw [devices] (Option<bool>, None)
|| {
match devices.borrow().get("eth0") {
Some(dev) => if dev.is_enabled() { "up\n".to_string() } else { "down\n".to_string() },
None => "Device not found\n".into(),
}
}
|cur_value, line| {
let s = line.trim();
match s {
"up" | "1" | "true" | "yes" | "on" => {
if let Some(dev) = devices.borrow_mut().get_mut("eth0") {
dev.set_enabled(true);
*cur_value = Some(true);
Ok(())
} else {
Err(SyscallError::new(syscall::ENODEV))
}
}
"down" | "0" | "false" | "no" | "off" => {
if let Some(dev) = devices.borrow_mut().get_mut("eth0") {
dev.set_enabled(false);
*cur_value = Some(false);
Ok(())
} else {
Err(SyscallError::new(syscall::ENODEV))
}
}
_ => Err(SyscallError::new(syscall::EINVAL)),
}
}
|_cur_value| { Ok(()) }
}
},
"lo" => {