observer: wire into forwarding/output paths for live capture

Router now captures packets flowing through the network stack:
- forward_packets(): capture all forwarded/local-delivered packets
- Observer injected via Router::new() from Smolnetd constructor

When /scheme/netcfg/capture/enable is written, all packets
traversing the router are captured into the ring buffer.
When disabled, zero overhead (AtomicBool check).
This commit is contained in:
Red Bear OS
2026-07-08 16:25:50 +03:00
parent ff66b96266
commit c1eb0b3db0
4 changed files with 220 additions and 3 deletions
+1
View File
@@ -4,6 +4,7 @@ pub mod common;
pub mod device;
pub mod node;
pub mod stream;
pub mod verbs;
pub use self::node::*;
pub use self::stream::*;
+206
View File
@@ -0,0 +1,206 @@
// HDA verb and parameter constants — ported from Linux 7.1 include/sound/hda_verbs.h.
// The hda_verbs.h header defines the HDA specification's verb IDs, parameter IDs,
// and capability bitfields for codec communication via CORB/RIRB.
// ---- Widget types (hda_verbs.h:25) ----
pub const AC_WID_AUD_OUT: u8 = 0x00;
pub const AC_WID_AUD_IN: u8 = 0x01;
pub const AC_WID_AUD_MIX: u8 = 0x02;
pub const AC_WID_AUD_SEL: u8 = 0x03;
pub const AC_WID_PIN: u8 = 0x04;
pub const AC_WID_POWER: u8 = 0x05;
pub const AC_WID_VOL_KNB: u8 = 0x06;
pub const AC_WID_BEEP: u8 = 0x07;
pub const AC_WID_VENDOR: u8 = 0x0f;
// ---- GET verbs (hda_verbs.h:40-84) ----
pub const AC_VERB_GET_STREAM_FORMAT: u32 = 0x0a00;
pub const AC_VERB_GET_AMP_GAIN_MUTE: u32 = 0x0b00;
pub const AC_VERB_GET_PROC_COEF: u32 = 0x0c00;
pub const AC_VERB_GET_COEF_INDEX: u32 = 0x0d00;
pub const AC_VERB_PARAMETERS: u32 = 0x0f00;
pub const AC_VERB_GET_CONNECT_SEL: u32 = 0x0f01;
pub const AC_VERB_GET_CONNECT_LIST: u32 = 0x0f02;
pub const AC_VERB_GET_PROC_STATE: u32 = 0x0f03;
pub const AC_VERB_GET_SDI_SELECT: u32 = 0x0f04;
pub const AC_VERB_GET_POWER_STATE: u32 = 0x0f05;
pub const AC_VERB_GET_CONV: u32 = 0x0f06;
pub const AC_VERB_GET_PIN_WIDGET_CONTROL: u32 = 0x0f07;
pub const AC_VERB_GET_UNSOLICITED_RESPONSE: u32 = 0x0f08;
pub const AC_VERB_GET_PIN_SENSE: u32 = 0x0f09;
pub const AC_VERB_GET_BEEP_CONTROL: u32 = 0x0f0a;
pub const AC_VERB_GET_EAPD_BTLENABLE: u32 = 0x0f0c;
pub const AC_VERB_GET_DIGI_CONVERT_1: u32 = 0x0f0d;
pub const AC_VERB_GET_VOLUME_KNOB_CONTROL: u32 = 0x0f0f;
pub const AC_VERB_GET_CONFIG_DEFAULT: u32 = 0x0f1c;
pub const AC_VERB_GET_SUBSYSTEM_ID: u32 = 0x0f20;
pub const AC_VERB_GET_STRIPE_CONTROL: u32 = 0x0f24;
pub const AC_VERB_GET_CVT_CHAN_COUNT: u32 = 0x0f2d;
pub const AC_VERB_GET_HDMI_DIP_SIZE: u32 = 0x0f2e;
pub const AC_VERB_GET_HDMI_ELDD: u32 = 0x0f2f;
pub const AC_VERB_GET_DEVICE_SEL: u32 = 0x0f35;
pub const AC_VERB_GET_DEVICE_LIST: u32 = 0x0f36;
// ---- SET verbs (hda_verbs.h:89-131) ----
pub const AC_VERB_SET_STREAM_FORMAT: u32 = 0x200;
pub const AC_VERB_SET_AMP_GAIN_MUTE: u32 = 0x300;
pub const AC_VERB_SET_PROC_COEF: u32 = 0x400;
pub const AC_VERB_SET_COEF_INDEX: u32 = 0x500;
pub const AC_VERB_SET_CONNECT_SEL: u32 = 0x701;
pub const AC_VERB_SET_PROC_STATE: u32 = 0x703;
pub const AC_VERB_SET_SDI_SELECT: u32 = 0x704;
pub const AC_VERB_SET_POWER_STATE: u32 = 0x705;
pub const AC_VERB_SET_CHANNEL_STREAMID: u32 = 0x706;
pub const AC_VERB_SET_PIN_WIDGET_CONTROL: u32 = 0x707;
pub const AC_VERB_SET_UNSOLICITED_ENABLE: u32 = 0x708;
pub const AC_VERB_SET_PIN_SENSE: u32 = 0x709;
pub const AC_VERB_SET_BEEP_CONTROL: u32 = 0x70a;
pub const AC_VERB_SET_EAPD_BTLENABLE: u32 = 0x70c;
pub const AC_VERB_SET_DIGI_CONVERT_1: u32 = 0x70d;
pub const AC_VERB_SET_DIGI_CONVERT_2: u32 = 0x70e;
pub const AC_VERB_SET_VOLUME_KNOB_CONTROL: u32 = 0x70f;
pub const AC_VERB_SET_CONFIG_DEFAULT_BYTES_0: u32 = 0x71c;
pub const AC_VERB_SET_CONFIG_DEFAULT_BYTES_1: u32 = 0x71d;
pub const AC_VERB_SET_CONFIG_DEFAULT_BYTES_2: u32 = 0x71e;
pub const AC_VERB_SET_CONFIG_DEFAULT_BYTES_3: u32 = 0x71f;
pub const AC_VERB_SET_EAPD: u32 = 0x788;
pub const AC_VERB_SET_CODEC_RESET: u32 = 0x7ff;
pub const AC_VERB_SET_STRIPE_CONTROL: u32 = 0x724;
pub const AC_VERB_SET_CVT_CHAN_COUNT: u32 = 0x72d;
// ---- Parameter IDs for AC_VERB_PARAMETERS (hda_verbs.h:136-154) ----
pub const AC_PAR_VENDOR_ID: u8 = 0x00;
pub const AC_PAR_SUBSYSTEM_ID: u8 = 0x01;
pub const AC_PAR_REV_ID: u8 = 0x02;
pub const AC_PAR_NODE_COUNT: u8 = 0x04;
pub const AC_PAR_FUNCTION_TYPE: u8 = 0x05;
pub const AC_PAR_AUDIO_FG_CAP: u8 = 0x08;
pub const AC_PAR_AUDIO_WIDGET_CAP: u8 = 0x09;
pub const AC_PAR_PCM: u8 = 0x0a;
pub const AC_PAR_STREAM: u8 = 0x0b;
pub const AC_PAR_PIN_CAP: u8 = 0x0c;
pub const AC_PAR_AMP_IN_CAP: u8 = 0x0d;
pub const AC_PAR_CONNLIST_LEN: u8 = 0x0e;
pub const AC_PAR_POWER_STATE: u8 = 0x0f;
pub const AC_PAR_PROC_CAP: u8 = 0x10;
pub const AC_PAR_GPIO_CAP: u8 = 0x11;
pub const AC_PAR_AMP_OUT_CAP: u8 = 0x12;
pub const AC_PAR_VOL_KNB_CAP: u8 = 0x13;
pub const AC_PAR_DEVLIST_LEN: u8 = 0x15;
pub const AC_PAR_HDMI_LPCM_CAP: u8 = 0x20;
// ---- Audio Widget Capabilities (hda_verbs.h:171-188) ----
pub const AC_WCAP_STEREO: u32 = 1 << 0;
pub const AC_WCAP_IN_AMP: u32 = 1 << 1;
pub const AC_WCAP_OUT_AMP: u32 = 1 << 2;
pub const AC_WCAP_AMP_OVRD: u32 = 1 << 3;
pub const AC_WCAP_FORMAT_OVRD: u32 = 1 << 4;
pub const AC_WCAP_STRIPE: u32 = 1 << 5;
pub const AC_WCAP_PROC_WID: u32 = 1 << 6;
pub const AC_WCAP_UNSOL_CAP: u32 = 1 << 7;
pub const AC_WCAP_CONN_LIST: u32 = 1 << 8;
pub const AC_WCAP_DIGITAL: u32 = 1 << 9;
pub const AC_WCAP_POWER: u32 = 1 << 10;
pub const AC_WCAP_LR_SWAP: u32 = 1 << 11;
pub const AC_WCAP_CP_CAPS: u32 = 1 << 12;
pub const AC_WCAP_CHAN_CNT_EXT: u32 = 7 << 13;
pub const AC_WCAP_DELAY: u32 = 0xf << 16;
pub const AC_WCAP_DELAY_SHIFT: u8 = 16;
pub const AC_WCAP_TYPE: u32 = 0xf << 20;
pub const AC_WCAP_TYPE_SHIFT: u8 = 20;
// ---- Pin Capabilities (hda_verbs.h:262-289) ----
pub const AC_PINCAP_IMP_SENSE: u32 = 1 << 0;
pub const AC_PINCAP_TRIG_REQ: u32 = 1 << 1;
pub const AC_PINCAP_PRES_DETECT: u32 = 1 << 2;
pub const AC_PINCAP_HP_DRV: u32 = 1 << 3;
pub const AC_PINCAP_OUT: u32 = 1 << 4;
pub const AC_PINCAP_IN: u32 = 1 << 5;
pub const AC_PINCAP_BALANCE: u32 = 1 << 6;
pub const AC_PINCAP_HDMI: u32 = 1 << 7;
pub const AC_PINCAP_DP: u32 = 1 << 24;
pub const AC_PINCAP_VREF: u32 = 0x37 << 8;
pub const AC_PINCAP_VREF_SHIFT: u8 = 8;
pub const AC_PINCAP_EAPD: u32 = 1 << 16;
pub const AC_PINCAP_HBR: u32 = 1 << 27;
// ---- Pin Widget Control (hda_verbs.h:400-411) ----
pub const AC_PINCTL_EPT: u32 = 0x3;
pub const AC_PINCTL_EPT_NATIVE: u8 = 0;
pub const AC_PINCTL_EPT_HBR: u8 = 3;
pub const AC_PINCTL_IN_EN: u8 = 1 << 5;
pub const AC_PINCTL_OUT_EN: u8 = 1 << 6;
pub const AC_PINCTL_HP_EN: u8 = 1 << 7;
// ---- Pin Sense (hda_verbs.h:414-416) ----
pub const AC_PINSENSE_IMPEDANCE_MASK: u32 = 0x7fff_ffff;
pub const AC_PINSENSE_PRESENCE: u32 = 1 << 31;
pub const AC_PINSENSE_ELDV: u32 = 1 << 30;
// ---- Power State (hda_verbs.h:311-330) ----
pub const AC_PWRST_D0SUP: u32 = 1 << 0;
pub const AC_PWRST_D1SUP: u32 = 1 << 1;
pub const AC_PWRST_D2SUP: u32 = 1 << 2;
pub const AC_PWRST_D3SUP: u32 = 1 << 3;
pub const AC_PWRST_D3COLDSUP: u32 = 1 << 4;
pub const AC_PWRST_S3D3COLDSUP: u32 = 1 << 29;
pub const AC_PWRST_CLKSTOP: u32 = 1 << 30;
pub const AC_PWRST_EPSS: u32 = 1 << 31;
pub const AC_PWRST_SETTING: u32 = 0xf;
pub const AC_PWRST_ACTUAL: u32 = 0xf << 4;
pub const AC_PWRST_ACTUAL_SHIFT: u8 = 4;
pub const AC_PWRST_D0: u32 = 0x00;
pub const AC_PWRST_D1: u32 = 0x01;
pub const AC_PWRST_D2: u32 = 0x02;
pub const AC_PWRST_D3: u32 = 0x03;
pub const AC_PWRST_ERROR: u32 = 1 << 8;
pub const AC_PWRST_CLK_STOP_OK: u32 = 1 << 9;
pub const AC_PWRST_SETTING_RESET: u32 = 1 << 10;
// ---- Amplifier (hda_verbs.h:366-380) ----
pub const AC_AMP_MUTE: u8 = 1 << 7;
pub const AC_AMP_GAIN: u8 = 0x7f;
pub const AC_AMP_GET_LEFT: u32 = 1 << 13;
pub const AC_AMP_GET_OUTPUT: u32 = 1 << 15;
// ---- PCM/Stream format (hda_verbs.h:191-235) ----
pub const AC_SUPPCM_BITS_8: u32 = 1 << 16;
pub const AC_SUPPCM_BITS_16: u32 = 1 << 17;
pub const AC_SUPPCM_BITS_20: u32 = 1 << 18;
pub const AC_SUPPCM_BITS_24: u32 = 1 << 19;
pub const AC_SUPPCM_BITS_32: u32 = 1 << 20;
pub const AC_SUPFMT_PCM: u32 = 1;
// ---- DIGITAL1 (hda_verbs.h:383-391) ----
pub const AC_DIG1_ENABLE: u32 = 1;
pub const AC_DIG1_V: u32 = 1 << 1;
pub const AC_DIG1_EMPHASIS: u32 = 1 << 3;
pub const AC_DIG1_COPYRIGHT: u32 = 1 << 4;
pub const AC_DIG1_NONAUDIO: u32 = 1 << 5;
pub const AC_DIG1_PROFESSIONAL: u32 = 1 << 6;
pub const AC_DIG1_LEVEL: u32 = 1 << 7;
// ---- Connection List (hda_verbs.h:307-308) ----
pub const AC_CLIST_LENGTH: u32 = 0x7f;
pub const AC_CLIST_LONG: u32 = 1 << 7;
// ---- Function Group (hda_verbs.h:161-168) ----
pub const AC_GRP_AUDIO_FUNCTION: u8 = 0x01;
pub const AC_GRP_MODEM_FUNCTION: u8 = 0x02;
pub const AC_FGT_UNSOL_CAP: u32 = 1 << 8;
pub const AC_AFG_OUT_DELAY: u32 = 0xf;
pub const AC_AFG_IN_DELAY: u32 = 0xf << 8;
pub const AC_AFG_BEEP_GEN: u32 = 1 << 16;
// ---- Stream Format (hda_verbs.h:221-235) ----
pub const AC_FMT_CHAN_SHIFT: u8 = 0;
pub const AC_FMT_CHAN_MASK: u32 = 0x0f;
pub const AC_FMT_BITS_SHIFT: u8 = 4;
pub const AC_FMT_BITS_MASK: u32 = 7 << 4;
pub const AC_FMT_BITS_8: u32 = 0;
pub const AC_FMT_BITS_16: u32 = 1 << 4;
pub const AC_FMT_BITS_20: u32 = 2 << 4;
pub const AC_FMT_BITS_24: u32 = 3 << 4;
pub const AC_FMT_BITS_32: u32 = 4 << 4;
pub const AC_FMT_BASE_48K: u32 = 0;
pub const AC_FMT_BASE_44K: u32 = 1 << 14;
+11 -1
View File
@@ -10,6 +10,7 @@ use self::route_table::{RouteTable, RouteType};
use crate::filter::{FilterTable, Hook, PacketContext, Verdict};
use crate::icmp_error;
use crate::link::DeviceList;
use crate::observer::ObserverRef;
use crate::scheme::Smolnetd;
pub mod route_table;
@@ -22,10 +23,11 @@ pub struct Router {
devices: Rc<RefCell<DeviceList>>,
route_table: Rc<RefCell<RouteTable>>,
pub ip_forward: Rc<Cell<bool>>,
observer: ObserverRef,
}
impl Router {
pub fn new(devices: Rc<RefCell<DeviceList>>, route_table: Rc<RefCell<RouteTable>>) -> Self {
pub fn new(devices: Rc<RefCell<DeviceList>>, route_table: Rc<RefCell<RouteTable>>, observer: ObserverRef) -> Self {
let rx_buffer = PacketBuffer::new(
vec![PacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0u8; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE],
@@ -40,6 +42,7 @@ impl Router {
devices,
route_table,
ip_forward: Rc::new(Cell::new(true)),
observer,
}
}
@@ -185,6 +188,13 @@ impl Router {
forwarded.push(buf);
}
for packet in &forwarded {
self.observer.capture(packet);
}
for packet in &local {
self.observer.capture(packet);
}
for packet in local {
let Ok(buf) = self.rx_buffer.enqueue(packet.len(), ()) else {
break;
+2 -2
View File
@@ -113,13 +113,13 @@ impl Smolnetd {
let devices = Rc::new(RefCell::new(DeviceList::default()));
let route_table = Rc::new(RefCell::new(RouteTable::default()));
let observer = Observer::new();
let mut network_device = Tracer::new(
Router::new(Rc::clone(&devices), Rc::clone(&route_table)),
Router::new(Rc::clone(&devices), Rc::clone(&route_table), Rc::clone(&observer)),
|_timestamp, printer| trace!("{}", printer),
);
let ip_forward = network_device.get_mut().ip_forward.clone();
let observer = Observer::new();
let config = Config::new(HardwareAddress::Ip);
let mut iface = SmoltcpInterface::new(config, &mut network_device, Instant::now());