link: add netkit interface type support#34
Conversation
There was a problem hiding this comment.
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.
| #[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, | ||
| } |
There was a problem hiding this comment.
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>,
}| 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(()) | ||
| } | ||
| } |
There was a problem hiding this comment.
Update the Display implementation to print scrub and peer_scrub only when they are present as Some values.
| 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"]); |
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>
Support creating and displaying netkit interfaces via
ip link add <name> type netkit. Accepts all man pageoptions: mode, scrub, forward/blackhole policy, peer name.
Includes integration tests comparing output against system ip.