Skip to content

link: add netkit interface type support#34

Merged
cathay4t merged 1 commit into
rust-netlink:mainfrom
cathay4t:main
Jun 11, 2026
Merged

link: add netkit interface type support#34
cathay4t merged 1 commit into
rust-netlink:mainfrom
cathay4t:main

Conversation

@cathay4t

Copy link
Copy Markdown
Member

Support creating and displaying netkit interfaces via
ip link add <name> type netkit. Accepts all man page
options: mode, scrub, forward/blackhole policy, peer name.

Includes integration tests comparing output against system ip.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the netkit link type, including parsing, serialization, display formatting, and integration tests. The review feedback focuses on aligning the CLI argument parsing and JSON/text output with standard iproute2 behavior. Key recommendations include requiring the policy keyword for policy arguments, supporting the name keyword for peer configurations, serializing scrub fields as optional to omit default values, and updating the corresponding display formatting and test cases.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/ip/link/ifaces/netkit.rs
Comment on lines +12 to +23
#[derive(Serialize)]
pub(crate) struct CliLinkInfoDataNetkit {
mode: String,
#[serde(rename = "type")]
typ: String,
#[serde(skip_serializing_if = "Option::is_none")]
policy: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
peer_policy: Option<String>,
scrub: String,
peer_scrub: String,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To match standard iproute2 behavior, scrub and peer_scrub should be serialized as Option<String> and skipped when they are not set or set to the default value. This ensures the JSON output matches the system ip command output.

#[derive(Serialize)]
pub(crate) struct CliLinkInfoDataNetkit {
    mode: String,
    #[serde(rename = "type")]
    typ: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    policy: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    peer_policy: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    scrub: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    peer_scrub: Option<String>,
}

Comment thread src/ip/link/ifaces/netkit.rs
Comment on lines +199 to +216
impl std::fmt::Display for CliLinkInfoDataNetkit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "mode {} type {}", self.mode, self.typ)?;
if let Some(ref policy) = self.policy {
write!(f, " policy {policy}")?;
}
if let Some(ref peer_policy) = self.peer_policy {
write!(f, " peer policy {peer_policy}")?;
}
if !self.scrub.is_empty() {
write!(f, " scrub {}", self.scrub)?;
}
if !self.peer_scrub.is_empty() {
write!(f, " peer scrub {}", self.peer_scrub)?;
}
Ok(())
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the Display implementation to print scrub and peer_scrub only when they are present as Some values.

Suggested change
impl std::fmt::Display for CliLinkInfoDataNetkit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "mode {} type {}", self.mode, self.typ)?;
if let Some(ref policy) = self.policy {
write!(f, " policy {policy}")?;
}
if let Some(ref peer_policy) = self.peer_policy {
write!(f, " peer policy {peer_policy}")?;
}
if !self.scrub.is_empty() {
write!(f, " scrub {}", self.scrub)?;
}
if !self.peer_scrub.is_empty() {
write!(f, " peer scrub {}", self.peer_scrub)?;
}
Ok(())
}
}
impl std::fmt::Display for CliLinkInfoDataNetkit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "mode {} type {}", self.mode, self.typ)?;
if let Some(ref policy) = self.policy {
write!(f, " policy {policy}")?;
}
if let Some(ref peer_policy) = self.peer_policy {
write!(f, " peer policy {peer_policy}")?;
}
if let Some(ref scrub) = self.scrub {
write!(f, " scrub {scrub}")?;
}
if let Some(ref peer_scrub) = self.peer_scrub {
write!(f, " peer scrub {peer_scrub}")?;
}
Ok(())
}
}

fn test_netkit_create_forward_policy() {
with_netns(|ns| {
let name = "tnk-fwd";
ns.ip_rs_exec_cmd(&["link", "add", name, "type", "netkit", "forward"]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the test command to use the standard policy forward syntax.

Suggested change
ns.ip_rs_exec_cmd(&["link", "add", name, "type", "netkit", "forward"]);
ns.ip_rs_exec_cmd(&["link", "add", name, "type", "netkit", "policy", "forward"]);

Comment thread src/ip/link/tests/netkit.rs
Comment thread src/ip/link/tests/netkit.rs
Comment thread src/ip/link/tests/netkit.rs
Support creating and displaying netkit interfaces via
`ip link add <name> type netkit`. Accepts all man page
options: mode, scrub, forward/blackhole policy, peer name.

Includes integration tests comparing output against system ip.

Signed-off-by: Gris Ge <cnfourt@gmail.com>
@cathay4t
cathay4t merged commit cd72f30 into rust-netlink:main Jun 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant