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 <yann.dirson@vates.fr>
RTMGRP_IPV6_IFADDR,
RTMGRP_LINK,
};
+use std::cell::RefCell;
use std::collections::hash_map;
use std::convert::TryInto;
use std::error::Error;
Ok(events)
}
- fn nl_linkmessage_decode(&mut self, msg: &LinkMessage)
- -> io::Result<(Rc<NetInterface>, Option<String>)> {
+ fn nl_linkmessage_decode(
+ &mut self, msg: &LinkMessage
+ ) -> io::Result<(Rc<RefCell<NetInterface>>, // ref to the (possibly new) impacted interface
+ Option<String>, // MAC address
+ )> {
let LinkMessage{header, nlas, ..} = msg;
// extract fields of interest
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<NetInterface>, IpAddr)> {
+ fn nl_addressmessage_decode(&mut self, msg: &AddressMessage)
+ -> io::Result<(Rc<RefCell<NetInterface>>, IpAddr)> {
let AddressMessage{header, nlas, ..} = msg;
// extract fields of interest
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;
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 {
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
})
&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()),
+use std::cell::RefCell;
use std::collections::HashMap;
use std::net::IpAddr;
use std::rc::Rc;
// 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<u32, Rc<NetInterface>>;
+// The interface may change name after creation (hence `RefCell`).
+pub type NetInterfaceCache = HashMap<u32, Rc<RefCell<NetInterface>>>;
#[derive(Debug)]
pub enum NetEventOp {
#[derive(Debug)]
pub struct NetEvent {
- pub iface: Rc<NetInterface>,
+ pub iface: Rc<RefCell<NetInterface>>,
pub op: NetEventOp,
}
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)?;
}
}
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:?}");
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"),
#[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}"))?;
// 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);
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}"))?;
},