From: Yann Dirson Date: Fri, 24 Nov 2023 11:00:52 +0000 (+0100) Subject: net: prepare interface cache for name changing X-Git-Tag: 0.3.0~11^2~1 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=80dcbd108d5e64d36395e215928fb9ab2d96aaee;p=xen-guest-agent.git net: prepare interface cache for name changing While name changes do not necessarily have external impact (eg. xenstore_schema_std does not expose those names), they are necessary on Linux to know whether an iface is a VIF. This requires NetInterface objects in the cache to be mutable. Signed-off-by: Yann Dirson --- diff --git a/src/collector_net_netlink.rs b/src/collector_net_netlink.rs index bea3a45..f9ad97c 100644 --- a/src/collector_net_netlink.rs +++ b/src/collector_net_netlink.rs @@ -23,6 +23,7 @@ use rtnetlink::constants::{ RTMGRP_IPV6_IFADDR, RTMGRP_LINK, }; +use std::cell::RefCell; use std::collections::hash_map; use std::convert::TryInto; use std::error::Error; @@ -141,8 +142,11 @@ impl NetworkSource { Ok(events) } - fn nl_linkmessage_decode(&mut self, msg: &LinkMessage) - -> io::Result<(Rc, Option)> { + fn nl_linkmessage_decode( + &mut self, msg: &LinkMessage + ) -> io::Result<(Rc>, // ref to the (possibly new) impacted interface + Option, // MAC address + )> { let LinkMessage{header, nlas, ..} = msg; // extract fields of interest @@ -163,12 +167,15 @@ impl NetworkSource { let iface = self.iface_cache .entry(header.index) - .or_insert_with_key(|index| NetInterface::new(*index, iface_name).into()); + .or_insert_with_key(|index| + RefCell::new(NetInterface::new(*index, iface_name.clone())) + .into()); Ok((iface.clone(), mac_address)) } - fn nl_addressmessage_decode(&mut self, msg: &AddressMessage) -> io::Result<(Rc, IpAddr)> { + fn nl_addressmessage_decode(&mut self, msg: &AddressMessage) + -> io::Result<(Rc>, IpAddr)> { let AddressMessage{header, nlas, ..} = msg; // extract fields of interest diff --git a/src/collector_net_pnet.rs b/src/collector_net_pnet.rs index 0be4283..5bc826b 100644 --- a/src/collector_net_pnet.rs +++ b/src/collector_net_pnet.rs @@ -3,6 +3,7 @@ use crate::datastructs::{NetEvent, NetEventOp, NetInterface, NetInterfaceCache}; use futures::stream::Stream; use ipnetwork::IpNetwork; use pnet_base::MacAddr; +use std::cell::RefCell; use std::collections::{HashMap, HashSet, hash_map}; use std::error::Error; use std::io; @@ -100,7 +101,7 @@ impl NetworkSource { Some(iface_info) => { let iface_adresses = &iface_info.addresses; for disappearing in cached_info.addresses.difference(iface_adresses) { - log::trace!("disappearing {}: {:?}", iface.name, disappearing); + log::trace!("disappearing {}: {:?}", iface.borrow().name, disappearing); events.push(NetEvent{ iface: iface.clone(), op: match disappearing { @@ -120,7 +121,8 @@ impl NetworkSource { let iface = self.iface_cache .entry(*iface_index) .or_insert_with_key(|index| { - let iface = Rc::new(NetInterface::new(*index, Some(iface_info.name.clone()))); + let iface = Rc::new(RefCell::new( + NetInterface::new(*index, Some(iface_info.name.clone())))); events.push(NetEvent{iface: iface.clone(), op: NetEventOp::AddIface}); iface }) @@ -132,7 +134,7 @@ impl NetworkSource { &empty_address_set }; for appearing in iface_info.addresses.difference(cache_adresses) { - log::trace!("appearing {}: {:?}", iface.name, appearing); + log::trace!("appearing {}: {:?}", iface.borrow().name, appearing); events.push(NetEvent{iface: iface.clone(), op: match appearing { Address::IP(ip) => NetEventOp::AddIp(ip.ip()), diff --git a/src/datastructs.rs b/src/datastructs.rs index a1ba27b..2b8a96d 100644 --- a/src/datastructs.rs +++ b/src/datastructs.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::collections::HashMap; use std::net::IpAddr; use std::rc::Rc; @@ -54,7 +55,8 @@ impl NetInterface { // remove interfaces from here once unplugged. And Rust won't let us // use `&'static NetInterface` because we can do the latter, which is // good in the end. -pub type NetInterfaceCache = HashMap>; +// The interface may change name after creation (hence `RefCell`). +pub type NetInterfaceCache = HashMap>>; #[derive(Debug)] pub enum NetEventOp { @@ -68,6 +70,6 @@ pub enum NetEventOp { #[derive(Debug)] pub struct NetEvent { - pub iface: Rc, + pub iface: Rc>, pub op: NetEventOp, } diff --git a/src/main.rs b/src/main.rs index 58ec866..2b80850 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,7 +65,7 @@ async fn main() -> Result<(), Box> { let network_cache = Box::leak(Box::new(NetInterfaceCache::new())); let mut collector_net = NetworkSource::new(network_cache)?; for event in collector_net.collect_current().await? { - if REPORT_INTERNAL_NICS || ! event.iface.toolstack_iface.is_none() { + if REPORT_INTERNAL_NICS || ! event.iface.borrow().toolstack_iface.is_none() { publisher.publish_netevent(&event)?; } } @@ -78,7 +78,7 @@ async fn main() -> Result<(), Box> { event = netevent_stream.try_next().fuse() => { match event? { Some(event) => { - if REPORT_INTERNAL_NICS || ! event.iface.toolstack_iface.is_none() { + if REPORT_INTERNAL_NICS || ! event.iface.borrow().toolstack_iface.is_none() { publisher.publish_netevent(&event)?; } else { log::debug!("no toolstack iface in {event:?}"); diff --git a/src/publisher.rs b/src/publisher.rs index fcaa26b..8258e36 100644 --- a/src/publisher.rs +++ b/src/publisher.rs @@ -29,7 +29,7 @@ impl Publisher { Ok(()) } pub fn publish_netevent(&self, event: &NetEvent) -> io::Result<()> { - let iface_id = &event.iface.name; + let iface_id = &event.iface.borrow().name; match &event.op { NetEventOp::AddIface => println!("{iface_id} +IFACE"), NetEventOp::RmIface => println!("{iface_id} -IFACE"), diff --git a/src/xenstore_schema_rfc.rs b/src/xenstore_schema_rfc.rs index e1f1a1e..74f32a9 100644 --- a/src/xenstore_schema_rfc.rs +++ b/src/xenstore_schema_rfc.rs @@ -41,11 +41,11 @@ impl XenstoreSchema for Schema { #[allow(clippy::useless_format)] fn publish_netevent(&mut self, event: &NetEvent) -> io::Result<()> { - let iface_id = &event.iface.index; + let iface_id = &event.iface.borrow().index; let xs_iface_prefix = format!("data/net/{iface_id}"); match &event.op { NetEventOp::AddIface => { - xs_publish(&self.xs, &format!("{xs_iface_prefix}"), &event.iface.name)?; + xs_publish(&self.xs, &format!("{xs_iface_prefix}"), &event.iface.borrow().name)?; }, NetEventOp::RmIface => { xs_unpublish(&self.xs, &format!("{xs_iface_prefix}"))?; diff --git a/src/xenstore_schema_std.rs b/src/xenstore_schema_std.rs index 0186dec..9817795 100644 --- a/src/xenstore_schema_std.rs +++ b/src/xenstore_schema_std.rs @@ -103,7 +103,7 @@ impl XenstoreSchema for Schema { // see https://xenbits.xen.org/docs/unstable/misc/xenstore-paths.html#domain-controlled-paths fn publish_netevent(&mut self, event: &NetEvent) -> io::Result<()> { - let iface_id = match event.iface.toolstack_iface { + let iface_id = match event.iface.borrow().toolstack_iface { ToolstackNetInterface::Vif(id) => id, ToolstackNetInterface::None => { panic!("publish_netevent called with no toolstack iface for {:?}", event); @@ -118,12 +118,12 @@ impl XenstoreSchema for Schema { xs_unpublish(&self.xs, &format!("{xs_iface_prefix}"))?; }, NetEventOp::AddIp(address) => { - let key_suffix = self.munged_address(address, &event.iface)?; + let key_suffix = self.munged_address(address, &event.iface.borrow())?; xs_publish(&self.xs, &format!("{xs_iface_prefix}/{key_suffix}"), &address.to_string())?; }, NetEventOp::RmIp(address) => { - let key_suffix = self.munged_address(address, &event.iface)?; + let key_suffix = self.munged_address(address, &event.iface.borrow())?; xs_unpublish(&self.xs, &format!("{xs_iface_prefix}/{key_suffix}"))?; },