diff --git a/src/agent/rustjail/src/lib.rs b/src/agent/rustjail/src/lib.rs index 6f96d18c2d..9ca124b1f2 100644 --- a/src/agent/rustjail/src/lib.rs +++ b/src/agent/rustjail/src/lib.rs @@ -154,12 +154,15 @@ fn hook_grpc_to_oci(h: &[grpcHook]) -> Vec { fn hooks_grpc_to_oci(h: &grpc::Hooks) -> oci::Hooks { let prestart = hook_grpc_to_oci(h.Prestart.as_ref()); + let create_runtime = hook_grpc_to_oci(h.CreateRuntime.as_ref()); + let poststart = hook_grpc_to_oci(h.Poststart.as_ref()); let poststop = hook_grpc_to_oci(h.Poststop.as_ref()); oci::Hooks { prestart, + create_runtime, poststart, poststop, } @@ -860,6 +863,7 @@ mod tests { env: Vec::from([String::from("env1"), String::from("env2")]), timeout: Some(10), }]), + ..Default::default() }, }, TestData { @@ -908,6 +912,7 @@ mod tests { env: Vec::from([String::from("env1"), String::from("env2")]), timeout: Some(10), }]), + ..Default::default() }, }, ]; diff --git a/src/dragonball/src/api/v1/instance_info.rs b/src/dragonball/src/api/v1/instance_info.rs index 86174a2fd7..45d03b4144 100644 --- a/src/dragonball/src/api/v1/instance_info.rs +++ b/src/dragonball/src/api/v1/instance_info.rs @@ -50,6 +50,8 @@ pub struct InstanceInfo { pub vmm_version: String, /// The pid of the current VMM process. pub pid: u32, + /// The tid of the current VMM master thread. + pub master_tid: u32, /// The state of async actions. pub async_state: AsyncState, /// List of tids of vcpu threads (vcpu index, tid) @@ -66,6 +68,7 @@ impl InstanceInfo { state: InstanceState::Uninitialized, vmm_version, pid: std::process::id(), + master_tid: 0, async_state: AsyncState::Uninitialized, tids: Vec::new(), last_instance_downtime: 0, @@ -80,6 +83,7 @@ impl Default for InstanceInfo { state: InstanceState::Uninitialized, vmm_version: env!("CARGO_PKG_VERSION").to_string(), pid: std::process::id(), + master_tid: 0, async_state: AsyncState::Uninitialized, tids: Vec::new(), last_instance_downtime: 0, diff --git a/src/libs/oci/src/lib.rs b/src/libs/oci/src/lib.rs index 3bcaefa162..7a31662a11 100644 --- a/src/libs/oci/src/lib.rs +++ b/src/libs/oci/src/lib.rs @@ -193,6 +193,8 @@ pub struct Hooks { #[serde(default, skip_serializing_if = "Vec::is_empty")] pub prestart: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub create_runtime: Vec, + #[serde(default, skip_serializing_if = "Vec::is_empty")] pub poststart: Vec, #[serde(default, skip_serializing_if = "Vec::is_empty")] pub poststop: Vec, @@ -1401,6 +1403,7 @@ mod tests { env: vec![], timeout: None, }], + ..Default::default() }), annotations: [ ("com.example.key1".to_string(), "value1".to_string()), diff --git a/src/libs/protocols/protos/oci.proto b/src/libs/protocols/protos/oci.proto index aa0db01238..43dea0657e 100644 --- a/src/libs/protocols/protos/oci.proto +++ b/src/libs/protocols/protos/oci.proto @@ -166,6 +166,9 @@ message Hooks { // Poststop is a list of hooks to be run after the container process exits. repeated Hook Poststop = 3 [(gogoproto.nullable) = false]; + + // Createruntime is a list of hooks to be run during the creation of runtime(sandbox). + repeated Hook CreateRuntime = 4 [(gogoproto.nullable) = false]; } message Hook { diff --git a/src/libs/protocols/src/trans.rs b/src/libs/protocols/src/trans.rs index c6f0c64f03..3c1aa6f66a 100644 --- a/src/libs/protocols/src/trans.rs +++ b/src/libs/protocols/src/trans.rs @@ -294,6 +294,7 @@ impl From for crate::oci::Hooks { fn from(from: Hooks) -> Self { crate::oci::Hooks { Prestart: from_vec(from.prestart), + CreateRuntime: from_vec(from.create_runtime), Poststart: from_vec(from.poststart), Poststop: from_vec(from.poststop), unknown_fields: Default::default(), @@ -974,6 +975,10 @@ impl From for oci::Hooks { for hook in from.take_Prestart().to_vec() { prestart.push(hook.into()) } + let mut create_runtime = Vec::new(); + for hook in from.take_CreateRuntime().to_vec() { + create_runtime.push(hook.into()) + } let mut poststart = Vec::new(); for hook in from.take_Poststart().to_vec() { poststart.push(hook.into()); @@ -984,6 +989,7 @@ impl From for oci::Hooks { } oci::Hooks { prestart, + create_runtime, poststart, poststop, } diff --git a/src/runtime-rs/Cargo.lock b/src/runtime-rs/Cargo.lock index fbff64e875..9ba66e7641 100644 --- a/src/runtime-rs/Cargo.lock +++ b/src/runtime-rs/Cargo.lock @@ -1703,6 +1703,8 @@ dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", + "memoffset 0.6.5", + "pin-utils", ] [[package]] @@ -2428,12 +2430,15 @@ dependencies = [ "hyper", "hyperlocal", "hypervisor", + "kata-sys-util", "kata-types", "lazy_static", "linux_container", "logging", + "nix 0.25.1", "oci", "persist", + "serde_json", "shim-interface", "slog", "slog-scope", diff --git a/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs b/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs index 8eea6f4666..9cd05de914 100644 --- a/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs +++ b/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs @@ -472,6 +472,10 @@ impl CloudHypervisorInner { Ok(Vec::::new()) } + pub(crate) async fn get_vmm_master_tid(&self) -> Result { + todo!() + } + pub(crate) async fn check(&self) -> Result<()> { Ok(()) } diff --git a/src/runtime-rs/crates/hypervisor/src/ch/mod.rs b/src/runtime-rs/crates/hypervisor/src/ch/mod.rs index 8e754415d7..7805d26015 100644 --- a/src/runtime-rs/crates/hypervisor/src/ch/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/ch/mod.rs @@ -118,6 +118,11 @@ impl Hypervisor for CloudHypervisor { inner.get_pids().await } + async fn get_vmm_master_tid(&self) -> Result { + let inner = self.inner.read().await; + inner.get_vmm_master_tid().await + } + async fn check(&self) -> Result<()> { let inner = self.inner.read().await; inner.check().await diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs index d4d75e6efa..fc3bea7a57 100644 --- a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs +++ b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs @@ -127,6 +127,11 @@ impl DragonballInner { Ok(Vec::from_iter(pids.into_iter())) } + pub(crate) async fn get_vmm_master_tid(&self) -> Result { + let master_tid = self.vmm_instance.get_vmm_master_tid(); + Ok(master_tid) + } + pub(crate) async fn check(&self) -> Result<()> { Ok(()) } diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs index 2886043c83..d096abf544 100644 --- a/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs @@ -117,6 +117,11 @@ impl Hypervisor for Dragonball { inner.get_pids().await } + async fn get_vmm_master_tid(&self) -> Result { + let inner = self.inner.read().await; + inner.get_vmm_master_tid().await + } + async fn check(&self) -> Result<()> { let inner = self.inner.read().await; inner.check().await diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs index f0d613938d..8e7d6332fd 100644 --- a/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs +++ b/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs @@ -75,6 +75,12 @@ impl VmmInstance { share_info_lock.write().unwrap().id = String::from(id); } + pub fn get_vmm_master_tid(&self) -> u32 { + let info = self.vmm_shared_info.clone(); + let result = info.read().unwrap().master_tid; + result + } + pub fn get_vcpu_tids(&self) -> Vec<(u8, u32)> { let info = self.vmm_shared_info.clone(); let result = info.read().unwrap().tids.clone(); @@ -103,6 +109,7 @@ impl VmmInstance { Some(kvm.into_raw_fd()), ) .expect("Failed to start vmm"); + let vmm_shared_info = self.get_shared_info(); self.vmm_thread = Some( thread::Builder::new() @@ -110,6 +117,9 @@ impl VmmInstance { .spawn(move || { || -> Result { debug!(sl!(), "run vmm thread start"); + let cur_tid = nix::unistd::gettid().as_raw() as u32; + vmm_shared_info.write().unwrap().master_tid = cur_tid; + if let Some(netns_path) = netns { info!(sl!(), "set netns for vmm master {}", &netns_path); let netns_fd = File::open(&netns_path) diff --git a/src/runtime-rs/crates/hypervisor/src/lib.rs b/src/runtime-rs/crates/hypervisor/src/lib.rs index 3c417f195e..e7f18e513b 100644 --- a/src/runtime-rs/crates/hypervisor/src/lib.rs +++ b/src/runtime-rs/crates/hypervisor/src/lib.rs @@ -87,6 +87,7 @@ pub trait Hypervisor: Send + Sync { async fn hypervisor_config(&self) -> HypervisorConfig; async fn get_thread_ids(&self) -> Result; async fn get_pids(&self) -> Result>; + async fn get_vmm_master_tid(&self) -> Result; async fn cleanup(&self) -> Result<()>; async fn check(&self) -> Result<()>; async fn get_jailer_root(&self) -> Result; diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs index e298e801bd..995a9c5908 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs @@ -89,6 +89,11 @@ impl QemuInner { todo!() } + pub(crate) async fn get_vmm_master_tid(&self) -> Result { + info!(sl!(), "QemuInner::get_vmm_master_tid()"); + todo!() + } + pub(crate) async fn cleanup(&self) -> Result<()> { info!(sl!(), "QemuInner::cleanup()"); todo!() diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs index 6df3869236..0192e2a8e9 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs @@ -103,6 +103,11 @@ impl Hypervisor for Qemu { inner.get_thread_ids().await } + async fn get_vmm_master_tid(&self) -> Result { + let inner = self.inner.read().await; + inner.get_vmm_master_tid().await + } + async fn cleanup(&self) -> Result<()> { let inner = self.inner.read().await; inner.cleanup().await diff --git a/src/runtime-rs/crates/runtimes/Cargo.toml b/src/runtime-rs/crates/runtimes/Cargo.toml index 6ff6b71a1d..142c44ed0c 100644 --- a/src/runtime-rs/crates/runtimes/Cargo.toml +++ b/src/runtime-rs/crates/runtimes/Cargo.toml @@ -13,9 +13,12 @@ slog-scope = "4.4.0" tokio = { version = "1.8.0", features = ["rt-multi-thread"] } hyper = { version = "0.14.20", features = ["stream", "server", "http1"] } hyperlocal = "0.8" +serde_json = "1.0.88" +nix = "0.25.0" common = { path = "./common" } kata-types = { path = "../../../libs/kata-types" } +kata-sys-util = { path = "../../../libs/kata-sys-util" } logging = { path = "../../../libs/logging"} oci = { path = "../../../libs/oci" } shim-interface = { path = "../../../libs/shim-interface" } diff --git a/src/runtime-rs/crates/runtimes/common/Cargo.toml b/src/runtime-rs/crates/runtimes/common/Cargo.toml index 00eb64825d..78a640e95d 100644 --- a/src/runtime-rs/crates/runtimes/common/Cargo.toml +++ b/src/runtime-rs/crates/runtimes/common/Cargo.toml @@ -26,3 +26,4 @@ agent = { path = "../../agent" } kata-sys-util = { path = "../../../../libs/kata-sys-util" } kata-types = { path = "../../../../libs/kata-types" } oci = { path = "../../../../libs/oci" } + diff --git a/src/runtime-rs/crates/runtimes/common/src/sandbox.rs b/src/runtime-rs/crates/runtimes/common/src/sandbox.rs index 4a5e49cba8..56dc95087e 100644 --- a/src/runtime-rs/crates/runtimes/common/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/common/src/sandbox.rs @@ -17,6 +17,9 @@ pub trait Sandbox: Send + Sync { // agent function async fn agent_sock(&self) -> Result; + // hypervisor function + async fn get_vmm_master_tid(&self) -> Result; + // utils async fn set_iptables(&self, is_ipv6: bool, data: Vec) -> Result>; async fn get_iptables(&self, is_ipv6: bool) -> Result>; diff --git a/src/runtime-rs/crates/runtimes/src/manager.rs b/src/runtime-rs/crates/runtimes/src/manager.rs index 49193cb5c8..ba2b0b0b06 100644 --- a/src/runtime-rs/crates/runtimes/src/manager.rs +++ b/src/runtime-rs/crates/runtimes/src/manager.rs @@ -18,6 +18,8 @@ use hypervisor::Param; use kata_types::{ annotations::Annotation, config::default::DEFAULT_GUEST_DNS_FILE, config::TomlConfig, }; +use kata_sys_util::hooks::HookStates; + #[cfg(feature = "linux")] use linux_container::LinuxContainer; use persist::sandbox_persist::Persist; @@ -81,7 +83,12 @@ impl RuntimeHandlerManagerInner { Ok(()) } - async fn try_init(&mut self, spec: &oci::Spec, options: &Option>) -> Result<()> { + async fn try_init( + &mut self, + spec: &oci::Spec, + state: &oci::State, + options: &Option>, + ) -> Result<()> { // return if runtime instance has init if self.runtime_instance.is_some() { return Ok(()); @@ -125,6 +132,35 @@ impl RuntimeHandlerManagerInner { .await .context("init runtime handler")?; + let mut st = state.clone(); + if let Some(runtime_instance) = self.runtime_instance.clone() { + let vmm_master_tid = runtime_instance + .sandbox + .get_vmm_master_tid() + .await + .context("get vmm master tid")?; + st.pid = vmm_master_tid as i32; + } + + // Prestart Hooks [DEPRECATED in newest oci spec]: + // * should be run in runtime namespace + // * should be run after vm is started, but before container is created + // if Prestart Hook and CreateRuntime Hook are both supported + // * spec details: https://github.com/opencontainers/runtime-spec/blob/c1662686cff159595277b79322d0272f5182941b/config.md#prestart + if let Some(hooks) = spec.hooks.as_ref() { + let mut prestart_hook_states = HookStates::new(); + prestart_hook_states.execute_hooks(&hooks.prestart, Some(st.clone()))? + } + + // CreateRuntime Hooks: + // * should be run in runtime namespace + // * should be run when creating the runtime + // * spec details: https://github.com/opencontainers/runtime-spec/blob/c1662686cff159595277b79322d0272f5182941b/config.md#createruntime-hooks + if let Some(hooks) = spec.hooks.as_ref() { + let mut create_runtime_hook_states = HookStates::new(); + create_runtime_hook_states.execute_hooks(&hooks.create_runtime, Some(st.clone()))? + } + // the sandbox creation can reach here only once and the sandbox is created // so we can safely create the shim management socket right now // the unwrap here is safe because the runtime handler is correctly created @@ -207,10 +243,11 @@ impl RuntimeHandlerManager { async fn try_init_runtime_instance( &self, spec: &oci::Spec, + state: &oci::State, options: &Option>, ) -> Result<()> { let mut inner = self.inner.write().await; - inner.try_init(spec, options).await + inner.try_init(spec, state, options).await } pub async fn handler_message(&self, req: Request) -> Result { @@ -222,8 +259,16 @@ impl RuntimeHandlerManager { oci::OCI_SPEC_CONFIG_FILE_NAME ); let spec = oci::Spec::load(&bundler_path).context("load spec")?; + let state = oci::State { + version: spec.version.clone(), + id: container_config.container_id.to_string(), + status: oci::ContainerState::Creating, + pid: 0, + bundle: bundler_path, + annotations: spec.annotations.clone(), + }; - self.try_init_runtime_instance(&spec, &container_config.options) + self.try_init_runtime_instance(&spec, &state, &container_config.options) .await .context("try init runtime instance")?; let instance = self diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs index 93ff1a4997..3289b4f293 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs @@ -37,6 +37,7 @@ pub struct Container { pid: u32, pub container_id: ContainerID, config: ContainerConfig, + spec: oci::Spec, inner: Arc>, agent: Arc, resource_manager: Arc, @@ -47,6 +48,7 @@ impl Container { pub fn new( pid: u32, config: ContainerConfig, + spec: oci::Spec, agent: Arc, resource_manager: Arc, ) -> Result { @@ -67,6 +69,7 @@ impl Container { pid, container_id, config, + spec, inner: Arc::new(RwLock::new(ContainerInner::new( agent.clone(), init_process, @@ -382,6 +385,14 @@ impl Container { .context("agent update container")?; Ok(()) } + + pub async fn config(&self) -> ContainerConfig { + self.config.clone() + } + + pub async fn spec(&self) -> oci::Spec { + self.spec.clone() + } } fn amend_spec(spec: &mut oci::Spec, disable_guest_seccomp: bool) -> Result<()> { diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs index ba73c17d56..326614e9b3 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs @@ -5,11 +5,10 @@ // use anyhow::{anyhow, Context, Result}; - +use async_trait::async_trait; use std::{collections::HashMap, sync::Arc}; use agent::Agent; -use async_trait::async_trait; use common::{ error::Error, types::{ @@ -19,10 +18,13 @@ use common::{ }, ContainerManager, }; +use hypervisor::Hypervisor; use oci::Process as OCIProcess; use resource::ResourceManager; use tokio::sync::RwLock; +use kata_sys_util::hooks::HookStates; + use super::{logger_with_process, Container}; pub struct VirtContainerManager { @@ -31,6 +33,7 @@ pub struct VirtContainerManager { containers: Arc>>, resource_manager: Arc, agent: Arc, + hypervisor: Arc, } impl VirtContainerManager { @@ -38,6 +41,7 @@ impl VirtContainerManager { sid: &str, pid: u32, agent: Arc, + hypervisor: Arc, resource_manager: Arc, ) -> Self { Self { @@ -46,6 +50,7 @@ impl VirtContainerManager { containers: Default::default(), resource_manager, agent, + hypervisor, } } } @@ -56,6 +61,7 @@ impl ContainerManager for VirtContainerManager { let container = Container::new( self.pid, config, + spec.clone(), self.agent.clone(), self.resource_manager.clone(), ) @@ -87,6 +93,26 @@ impl ContainerManager for VirtContainerManager { let c = containers .remove(container_id) .ok_or_else(|| Error::ContainerNotFound(container_id.to_string()))?; + + // Poststop Hooks: + // * should be run in runtime namespace + // * should be run after the container is deleted but before delete operation returns + // * spec details: https://github.com/opencontainers/runtime-spec/blob/c1662686cff159595277b79322d0272f5182941b/config.md#poststop + let c_spec = c.spec().await; + let vmm_master_tid = self.hypervisor.get_vmm_master_tid().await?; + let state = oci::State { + version: c_spec.version.clone(), + id: c.container_id.to_string(), + status: oci::ContainerState::Stopped, + pid: vmm_master_tid as i32, + bundle: c.config().await.bundle, + annotations: c_spec.annotations.clone(), + }; + if let Some(hooks) = c_spec.hooks.as_ref() { + let mut poststop_hook_states = HookStates::new(); + poststop_hook_states.execute_hooks(&hooks.poststop, Some(state))?; + } + c.state_process(process).await.context("state process") } ProcessType::Exec => { @@ -190,6 +216,26 @@ impl ContainerManager for VirtContainerManager { .get(container_id) .ok_or_else(|| Error::ContainerNotFound(container_id.clone()))?; c.start(process).await.context("start")?; + + // Poststart Hooks: + // * should be run in runtime namespace + // * should be run after user-specific command is executed but before start operation returns + // * spec details: https://github.com/opencontainers/runtime-spec/blob/c1662686cff159595277b79322d0272f5182941b/config.md#poststart + let c_spec = c.spec().await; + let vmm_master_tid = self.hypervisor.get_vmm_master_tid().await?; + let state = oci::State { + version: c_spec.version.clone(), + id: c.container_id.to_string(), + status: oci::ContainerState::Running, + pid: vmm_master_tid as i32, + bundle: c.config().await.bundle, + annotations: c_spec.annotations.clone(), + }; + if let Some(hooks) = c_spec.hooks.as_ref() { + let mut poststart_hook_states = HookStates::new(); + poststart_hook_states.execute_hooks(&hooks.poststart, Some(state))?; + } + Ok(PID { pid: self.pid }) } diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/lib.rs b/src/runtime-rs/crates/runtimes/virt_container/src/lib.rs index b73caa8494..3d1381c71f 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/lib.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/lib.rs @@ -86,13 +86,18 @@ impl RuntimeHandler for VirtContainer { sid, msg_sender, agent.clone(), - hypervisor, + hypervisor.clone(), resource_manager.clone(), ) .await .context("new virt sandbox")?; - let container_manager = - container_manager::VirtContainerManager::new(sid, pid, agent, resource_manager); + let container_manager = container_manager::VirtContainerManager::new( + sid, + pid, + agent, + hypervisor, + resource_manager, + ); Ok(RuntimeInstance { sandbox: Arc::new(sandbox), container_manager: Arc::new(container_manager), diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index be7577eccb..91372c881e 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -278,6 +278,10 @@ impl Sandbox for VirtSandbox { self.agent.agent_sock().await } + async fn get_vmm_master_tid(&self) -> Result { + self.hypervisor.get_vmm_master_tid().await + } + async fn set_iptables(&self, is_ipv6: bool, data: Vec) -> Result> { info!(sl!(), "sb: set_iptables invoked"); let req = SetIPTablesRequest { is_ipv6, data };