Skip to content

Commit fb89e38

Browse files
committed
ip-link: Support showing veth & bond & bridge link-kind details
1 parent 00a4806 commit fb89e38

File tree

3 files changed

+194
-4
lines changed

3 files changed

+194
-4
lines changed

src/ip/link/flags.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub fn link_flags_to_string(mut flags: LinkFlags) -> Vec<String> {
4444
// Compatible with iproute2, but we still append `CONTROLLER`
4545
// after iproute2 flags.
4646
ret.push("MASTER".into());
47+
flags.remove(flag)
4748
} else if flag == LinkFlags::LowerUp {
4849
ret.push("LOWER_UP".into());
4950
flags.remove(flag)

src/ip/link/link_info.rs

Lines changed: 185 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: MIT
22

3-
use rtnetlink::packet_route::link::{InfoData, InfoPortData, LinkInfo};
3+
use rtnetlink::packet_route::link::{
4+
BondArpValidate, InfoData, InfoPortData, LinkInfo,
5+
};
46
use serde::Serialize;
57

68
use iproute_rs::mac_to_string;
@@ -140,6 +142,32 @@ pub(crate) enum CliLinkInfoData {
140142
nf_call_ip6tables: u8,
141143
nf_call_arptables: u8,
142144
},
145+
Veth,
146+
Bond {
147+
mode: String,
148+
miimon: u32,
149+
updelay: u32,
150+
downdelay: u32,
151+
peer_notify_delay: u32,
152+
use_carrier: u8,
153+
arp_interval: u32,
154+
arp_missed_max: u8,
155+
arp_validate: Option<String>,
156+
arp_all_targets: String,
157+
primary_reselect: String,
158+
fail_over_mac: String,
159+
xmit_hash_policy: String,
160+
resend_igmp: u32,
161+
num_peer_notif: u8,
162+
all_slaves_active: u8,
163+
min_links: u32,
164+
lp_interval: u32,
165+
packets_per_slave: u32,
166+
ad_lacp_active: String,
167+
ad_lacp_rate: String,
168+
ad_select: String,
169+
tlb_dynamic_lb: u8,
170+
},
143171
}
144172

145173
impl CliLinkInfoData {
@@ -607,9 +635,117 @@ impl CliLinkInfoData {
607635
protocol,
608636
}
609637
}
610-
InfoData::Veth(_info_veth) => todo!(),
638+
InfoData::Veth(_) => CliLinkInfoData::Veth,
611639
InfoData::Vxlan(_info_vxlan) => todo!(),
612-
InfoData::Bond(_info_bond) => todo!(),
640+
InfoData::Bond(info_bond) => {
641+
let mut mode = String::new();
642+
let mut miimon = 0;
643+
let mut updelay = 0;
644+
let mut downdelay = 0;
645+
let mut peer_notify_delay = 0;
646+
let mut use_carrier = 0;
647+
let mut arp_interval = 0;
648+
let mut arp_missed_max = 0;
649+
let mut arp_validate = None;
650+
let mut arp_all_targets = String::new();
651+
let mut primary_reselect = String::new();
652+
let mut fail_over_mac = String::new();
653+
let mut xmit_hash_policy = String::new();
654+
let mut resend_igmp = 0;
655+
let mut num_peer_notif = 0;
656+
let mut all_slaves_active = 0;
657+
let mut min_links = 0;
658+
let mut lp_interval = 0;
659+
let mut packets_per_slave = 0;
660+
let mut ad_lacp_active = String::new();
661+
let mut ad_lacp_rate = String::new();
662+
let mut ad_select = String::new();
663+
let mut tlb_dynamic_lb = 0;
664+
665+
for nla in info_bond {
666+
use rtnetlink::packet_route::link::InfoBond;
667+
match nla {
668+
InfoBond::Mode(v) => mode = v.to_string(),
669+
InfoBond::MiiMon(v) => miimon = *v,
670+
InfoBond::UpDelay(v) => updelay = *v,
671+
InfoBond::DownDelay(v) => downdelay = *v,
672+
InfoBond::PeerNotifDelay(v) => peer_notify_delay = *v,
673+
InfoBond::UseCarrier(v) => use_carrier = *v,
674+
InfoBond::ArpInterval(v) => arp_interval = *v,
675+
InfoBond::MissedMax(v) => arp_missed_max = *v,
676+
InfoBond::ArpValidate(v) => {
677+
if matches!(v, BondArpValidate::None) {
678+
arp_validate = None
679+
} else {
680+
arp_validate = Some(v.to_string())
681+
}
682+
}
683+
InfoBond::ArpAllTargets(v) => {
684+
arp_all_targets = v.to_string()
685+
}
686+
InfoBond::PrimaryReselect(v) => {
687+
primary_reselect = v.to_string()
688+
}
689+
InfoBond::FailOverMac(v) => {
690+
fail_over_mac = v.to_string()
691+
}
692+
InfoBond::XmitHashPolicy(v) => {
693+
xmit_hash_policy = v.to_string()
694+
}
695+
InfoBond::ResendIgmp(v) => resend_igmp = *v,
696+
InfoBond::NumPeerNotif(v) => num_peer_notif = *v,
697+
InfoBond::AllPortsActive(v) => all_slaves_active = *v,
698+
InfoBond::MinLinks(v) => min_links = *v,
699+
InfoBond::LpInterval(v) => lp_interval = *v,
700+
InfoBond::PacketsPerPort(v) => packets_per_slave = *v,
701+
InfoBond::AdLacpActive(v) => {
702+
ad_lacp_active =
703+
if *v == 1 { "on" } else { "off" }.to_string()
704+
}
705+
InfoBond::AdLacpRate(v) => {
706+
ad_lacp_rate = if *v == 1 { "fast" } else { "slow" }
707+
.to_string()
708+
}
709+
InfoBond::AdSelect(v) => {
710+
ad_select = match *v {
711+
0 => "stable",
712+
1 => "bandwidth",
713+
2 => "count",
714+
3 => "hash",
715+
_ => "unknown",
716+
}
717+
.to_string()
718+
}
719+
InfoBond::TlbDynamicLb(v) => tlb_dynamic_lb = *v,
720+
_ => (), /* println!("Remains {:?}", nla) */
721+
}
722+
}
723+
Self::Bond {
724+
mode,
725+
miimon,
726+
updelay,
727+
downdelay,
728+
peer_notify_delay,
729+
use_carrier,
730+
arp_interval,
731+
arp_missed_max,
732+
arp_validate,
733+
arp_all_targets,
734+
primary_reselect,
735+
fail_over_mac,
736+
xmit_hash_policy,
737+
resend_igmp,
738+
num_peer_notif,
739+
all_slaves_active,
740+
min_links,
741+
lp_interval,
742+
packets_per_slave,
743+
ad_lacp_active,
744+
ad_lacp_rate,
745+
ad_select,
746+
tlb_dynamic_lb,
747+
}
748+
}
613749
InfoData::IpVlan(_info_ip_vlan) => todo!(),
614750
InfoData::IpVtap(_info_ip_vtap) => todo!(),
615751
InfoData::MacVlan(_info_mac_vlan) => todo!(),
@@ -746,6 +882,52 @@ impl std::fmt::Display for CliLinkInfoData {
746882
write!(f, "mab off")?;
747883
}
748884
}
885+
CliLinkInfoData::Veth => (),
886+
CliLinkInfoData::Bond {
887+
mode,
888+
miimon,
889+
updelay,
890+
downdelay,
891+
peer_notify_delay,
892+
use_carrier,
893+
arp_interval,
894+
arp_missed_max,
895+
arp_validate,
896+
arp_all_targets,
897+
primary_reselect,
898+
fail_over_mac,
899+
xmit_hash_policy,
900+
resend_igmp,
901+
num_peer_notif: num_grat_arp,
902+
all_slaves_active,
903+
min_links,
904+
lp_interval,
905+
packets_per_slave: packaets_per_slave,
906+
ad_lacp_active: lacp_active,
907+
ad_lacp_rate: lacp_rate,
908+
ad_select,
909+
tlb_dynamic_lb,
910+
} => {
911+
let arp_validate =
912+
arp_validate.as_ref().map_or("none", |s| s.as_str());
913+
914+
write!(
915+
f,
916+
"mode {mode} miimon {miimon} updelay {updelay} downdelay \
917+
{downdelay} peer_notify_delay {peer_notify_delay} \
918+
use_carrier {use_carrier} arp_interval {arp_interval} \
919+
arp_missed_max {arp_missed_max} arp_validate \
920+
{arp_validate} arp_all_targets {arp_all_targets} \
921+
primary_reselect {primary_reselect} fail_over_mac \
922+
{fail_over_mac} xmit_hash_policy {xmit_hash_policy} \
923+
resend_igmp {resend_igmp} num_grat_arp {num_grat_arp} \
924+
all_slaves_active {all_slaves_active} min_links \
925+
{min_links} lp_interval {lp_interval} packets_per_slave \
926+
{packaets_per_slave} lacp_active {lacp_active} lacp_rate \
927+
{lacp_rate} ad_select {ad_select} tlb_dynamic_lb \
928+
{tlb_dynamic_lb}",
929+
)?;
930+
}
749931
CliLinkInfoData::Bridge {
750932
forward_delay,
751933
hello_time,

src/ip/link/tests/link.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// SPDX-License-Identifier: MIT
22

3+
use serde_json::Value;
4+
35
use crate::tests::{exec_cmd, get_ip_cli_path};
46

57
const TEST_NETNS: &str = "iproute-rs-test";
@@ -179,7 +181,12 @@ fn test_link_show_json() {
179181

180182
let our_output = exec_in_netns(&[cli_path.as_str(), "-j", "link", "show"]);
181183

182-
pretty_assertions::assert_eq!(expected_output, our_output);
184+
let expected_json: Value =
185+
serde_json::from_str(&expected_output).expect("To be valid json");
186+
let our_json: Value =
187+
serde_json::from_str(&our_output).expect("To be valid json");
188+
189+
pretty_assertions::assert_eq!(expected_json, our_json);
183190
}
184191

185192
#[test]

0 commit comments

Comments
 (0)