Simplify EthernetInterface lifetimes.
This commit is contained in:
parent
02a80a6000
commit
8da202ff7f
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use managed::{ManagedSlice, ManagedMap};
|
use managed::{ManagedSlice, ManagedMap};
|
||||||
#[cfg(not(feature = "proto-igmp"))]
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use crate::phy::{Device, DeviceCapabilities, RxToken, TxToken};
|
use crate::phy::{Device, DeviceCapabilities, RxToken, TxToken};
|
||||||
|
@ -57,9 +55,9 @@ use crate::iface::Routes;
|
||||||
/// The network interface logically owns a number of other data structures; to avoid
|
/// The network interface logically owns a number of other data structures; to avoid
|
||||||
/// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
|
/// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
|
||||||
/// a `&mut [T]`, or `Vec<T>` if a heap is available.
|
/// a `&mut [T]`, or `Vec<T>` if a heap is available.
|
||||||
pub struct Interface<'b, 'c, 'e, DeviceT: for<'d> Device<'d>> {
|
pub struct Interface<'a, DeviceT: for<'d> Device<'d>> {
|
||||||
device: DeviceT,
|
device: DeviceT,
|
||||||
inner: InterfaceInner<'b, 'c, 'e>,
|
inner: InterfaceInner<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The device independent part of an Ethernet network interface.
|
/// The device independent part of an Ethernet network interface.
|
||||||
|
@ -69,17 +67,15 @@ pub struct Interface<'b, 'c, 'e, DeviceT: for<'d> Device<'d>> {
|
||||||
/// the `device` mutably until they're used, which makes it impossible to call other
|
/// the `device` mutably until they're used, which makes it impossible to call other
|
||||||
/// methods on the `Interface` in this time (since its `device` field is borrowed
|
/// methods on the `Interface` in this time (since its `device` field is borrowed
|
||||||
/// exclusively). However, it is still possible to call methods on its `inner` field.
|
/// exclusively). However, it is still possible to call methods on its `inner` field.
|
||||||
struct InterfaceInner<'b, 'c, 'e> {
|
struct InterfaceInner<'a> {
|
||||||
neighbor_cache: NeighborCache<'b>,
|
neighbor_cache: NeighborCache<'a>,
|
||||||
ethernet_addr: EthernetAddress,
|
ethernet_addr: EthernetAddress,
|
||||||
ip_addrs: ManagedSlice<'c, IpCidr>,
|
ip_addrs: ManagedSlice<'a, IpCidr>,
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
any_ip: bool,
|
any_ip: bool,
|
||||||
routes: Routes<'e>,
|
routes: Routes<'a>,
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
ipv4_multicast_groups: ManagedMap<'e, Ipv4Address, ()>,
|
ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
|
||||||
#[cfg(not(feature = "proto-igmp"))]
|
|
||||||
_ipv4_multicast_groups: PhantomData<&'e ()>,
|
|
||||||
/// When to report for (all or) the next multicast group membership via IGMP
|
/// When to report for (all or) the next multicast group membership via IGMP
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
igmp_report_state: IgmpReportState,
|
igmp_report_state: IgmpReportState,
|
||||||
|
@ -88,22 +84,20 @@ struct InterfaceInner<'b, 'c, 'e> {
|
||||||
|
|
||||||
/// A builder structure used for creating a Ethernet network
|
/// A builder structure used for creating a Ethernet network
|
||||||
/// interface.
|
/// interface.
|
||||||
pub struct InterfaceBuilder <'b, 'c, 'e, DeviceT: for<'d> Device<'d>> {
|
pub struct InterfaceBuilder <'a, DeviceT: for<'d> Device<'d>> {
|
||||||
device: DeviceT,
|
device: DeviceT,
|
||||||
ethernet_addr: Option<EthernetAddress>,
|
ethernet_addr: Option<EthernetAddress>,
|
||||||
neighbor_cache: Option<NeighborCache<'b>>,
|
neighbor_cache: Option<NeighborCache<'a>>,
|
||||||
ip_addrs: ManagedSlice<'c, IpCidr>,
|
ip_addrs: ManagedSlice<'a, IpCidr>,
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
any_ip: bool,
|
any_ip: bool,
|
||||||
routes: Routes<'e>,
|
routes: Routes<'a>,
|
||||||
/// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
|
/// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
ipv4_multicast_groups: ManagedMap<'e, Ipv4Address, ()>,
|
ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
|
||||||
#[cfg(not(feature = "proto-igmp"))]
|
|
||||||
_ipv4_multicast_groups: PhantomData<&'e ()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT>
|
||||||
where DeviceT: for<'d> Device<'d> {
|
where DeviceT: for<'d> Device<'d> {
|
||||||
/// Create a builder used for creating a network interface using the
|
/// Create a builder used for creating a network interface using the
|
||||||
/// given device and address.
|
/// given device and address.
|
||||||
|
@ -141,8 +135,6 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
routes: Routes::new(ManagedMap::Borrowed(&mut [])),
|
routes: Routes::new(ManagedMap::Borrowed(&mut [])),
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
|
ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
|
||||||
#[cfg(not(feature = "proto-igmp"))]
|
|
||||||
_ipv4_multicast_groups: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +159,7 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
///
|
///
|
||||||
/// [ip_addrs]: struct.EthernetInterface.html#method.ip_addrs
|
/// [ip_addrs]: struct.EthernetInterface.html#method.ip_addrs
|
||||||
pub fn ip_addrs<T>(mut self, ip_addrs: T) -> Self
|
pub fn ip_addrs<T>(mut self, ip_addrs: T) -> Self
|
||||||
where T: Into<ManagedSlice<'c, IpCidr>>
|
where T: Into<ManagedSlice<'a, IpCidr>>
|
||||||
{
|
{
|
||||||
let ip_addrs = ip_addrs.into();
|
let ip_addrs = ip_addrs.into();
|
||||||
InterfaceInner::check_ip_addrs(&ip_addrs);
|
InterfaceInner::check_ip_addrs(&ip_addrs);
|
||||||
|
@ -198,8 +190,8 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
/// [routes].
|
/// [routes].
|
||||||
///
|
///
|
||||||
/// [routes]: struct.EthernetInterface.html#method.routes
|
/// [routes]: struct.EthernetInterface.html#method.routes
|
||||||
pub fn routes<T>(mut self, routes: T) -> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
pub fn routes<T>(mut self, routes: T) -> InterfaceBuilder<'a, DeviceT>
|
||||||
where T: Into<Routes<'e>>
|
where T: Into<Routes<'a>>
|
||||||
{
|
{
|
||||||
self.routes = routes.into();
|
self.routes = routes.into();
|
||||||
self
|
self
|
||||||
|
@ -217,14 +209,14 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
/// [`join_multicast_group()`]: struct.EthernetInterface.html#method.join_multicast_group
|
/// [`join_multicast_group()`]: struct.EthernetInterface.html#method.join_multicast_group
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
pub fn ipv4_multicast_groups<T>(mut self, ipv4_multicast_groups: T) -> Self
|
pub fn ipv4_multicast_groups<T>(mut self, ipv4_multicast_groups: T) -> Self
|
||||||
where T: Into<ManagedMap<'e, Ipv4Address, ()>>
|
where T: Into<ManagedMap<'a, Ipv4Address, ()>>
|
||||||
{
|
{
|
||||||
self.ipv4_multicast_groups = ipv4_multicast_groups.into();
|
self.ipv4_multicast_groups = ipv4_multicast_groups.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the Neighbor Cache the interface will use.
|
/// Set the Neighbor Cache the interface will use.
|
||||||
pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'b>) -> Self {
|
pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'a>) -> Self {
|
||||||
self.neighbor_cache = Some(neighbor_cache);
|
self.neighbor_cache = Some(neighbor_cache);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -240,7 +232,7 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
///
|
///
|
||||||
/// [ethernet_addr]: #method.ethernet_addr
|
/// [ethernet_addr]: #method.ethernet_addr
|
||||||
/// [neighbor_cache]: #method.neighbor_cache
|
/// [neighbor_cache]: #method.neighbor_cache
|
||||||
pub fn finalize(self) -> Interface<'b, 'c, 'e, DeviceT> {
|
pub fn finalize(self) -> Interface<'a, DeviceT> {
|
||||||
match (self.ethernet_addr, self.neighbor_cache) {
|
match (self.ethernet_addr, self.neighbor_cache) {
|
||||||
(Some(ethernet_addr), Some(neighbor_cache)) => {
|
(Some(ethernet_addr), Some(neighbor_cache)) => {
|
||||||
let device_capabilities = self.device.capabilities();
|
let device_capabilities = self.device.capabilities();
|
||||||
|
@ -255,8 +247,6 @@ impl<'b, 'c, 'e, DeviceT> InterfaceBuilder<'b, 'c, 'e, DeviceT>
|
||||||
routes: self.routes,
|
routes: self.routes,
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
ipv4_multicast_groups: self.ipv4_multicast_groups,
|
ipv4_multicast_groups: self.ipv4_multicast_groups,
|
||||||
#[cfg(not(feature = "proto-igmp"))]
|
|
||||||
_ipv4_multicast_groups: PhantomData,
|
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
igmp_report_state: IgmpReportState::Inactive,
|
igmp_report_state: IgmpReportState::Inactive,
|
||||||
}
|
}
|
||||||
|
@ -385,7 +375,7 @@ enum IgmpReportState {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'c, 'e, DeviceT> Interface<'b, 'c, 'e, DeviceT>
|
impl<'a, DeviceT> Interface<'a, DeviceT>
|
||||||
where DeviceT: for<'d> Device<'d> {
|
where DeviceT: for<'d> Device<'d> {
|
||||||
/// Get the Ethernet address of the interface.
|
/// Get the Ethernet address of the interface.
|
||||||
pub fn ethernet_addr(&self) -> EthernetAddress {
|
pub fn ethernet_addr(&self) -> EthernetAddress {
|
||||||
|
@ -495,7 +485,7 @@ impl<'b, 'c, 'e, DeviceT> Interface<'b, 'c, 'e, DeviceT>
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// This function panics if any of the addresses are not unicast.
|
/// This function panics if any of the addresses are not unicast.
|
||||||
pub fn update_ip_addrs<F: FnOnce(&mut ManagedSlice<'c, IpCidr>)>(&mut self, f: F) {
|
pub fn update_ip_addrs<F: FnOnce(&mut ManagedSlice<'a, IpCidr>)>(&mut self, f: F) {
|
||||||
f(&mut self.inner.ip_addrs);
|
f(&mut self.inner.ip_addrs);
|
||||||
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
|
||||||
}
|
}
|
||||||
|
@ -511,11 +501,11 @@ impl<'b, 'c, 'e, DeviceT> Interface<'b, 'c, 'e, DeviceT>
|
||||||
self.inner.ipv4_address()
|
self.inner.ipv4_address()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes(&self) -> &Routes<'e> {
|
pub fn routes(&self) -> &Routes<'a> {
|
||||||
&self.inner.routes
|
&self.inner.routes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes_mut(&mut self) -> &mut Routes<'e> {
|
pub fn routes_mut(&mut self) -> &mut Routes<'a> {
|
||||||
&mut self.inner.routes
|
&mut self.inner.routes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +742,7 @@ impl<'b, 'c, 'e, DeviceT> Interface<'b, 'c, 'e, DeviceT>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
impl<'a> InterfaceInner<'a> {
|
||||||
fn check_ethernet_addr(addr: &EthernetAddress) {
|
fn check_ethernet_addr(addr: &EthernetAddress) {
|
||||||
if addr.is_multicast() {
|
if addr.is_multicast() {
|
||||||
panic!("Ethernet address {} is not unicast", addr)
|
panic!("Ethernet address {} is not unicast", addr)
|
||||||
|
@ -1730,8 +1720,7 @@ mod test {
|
||||||
|
|
||||||
use super::{EthernetPacket, IpPacket};
|
use super::{EthernetPacket, IpPacket};
|
||||||
|
|
||||||
fn create_loopback<'a, 'b, 'c>() -> (EthernetInterface<'static, 'b, 'c, Loopback>,
|
fn create_loopback<'a>() -> (EthernetInterface<'a, Loopback>, SocketSet<'a>) {
|
||||||
SocketSet<'a>) {
|
|
||||||
// Create a basic device
|
// Create a basic device
|
||||||
let device = Loopback::new();
|
let device = Loopback::new();
|
||||||
let ip_addrs = [
|
let ip_addrs = [
|
||||||
|
@ -1757,7 +1746,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
fn recv_all<'b>(iface: &mut EthernetInterface<'static, 'b, 'static, Loopback>, timestamp: Instant) -> Vec<Vec<u8>> {
|
fn recv_all(iface: &mut EthernetInterface<'_, Loopback>, timestamp: Instant) -> Vec<Vec<u8>> {
|
||||||
let mut pkts = Vec::new();
|
let mut pkts = Vec::new();
|
||||||
while let Some((rx, _tx)) = iface.device.receive() {
|
while let Some((rx, _tx)) = iface.device.receive() {
|
||||||
rx.consume(timestamp, |pkt| {
|
rx.consume(timestamp, |pkt| {
|
||||||
|
@ -2533,7 +2522,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "proto-igmp")]
|
#[cfg(feature = "proto-igmp")]
|
||||||
fn test_handle_igmp() {
|
fn test_handle_igmp() {
|
||||||
fn recv_igmp<'b>(mut iface: &mut EthernetInterface<'static, 'b, 'static, Loopback>, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
|
fn recv_igmp(mut iface: &mut EthernetInterface<'_, Loopback>, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
|
||||||
let checksum_caps = &iface.device.capabilities().checksum;
|
let checksum_caps = &iface.device.capabilities().checksum;
|
||||||
recv_all(&mut iface, timestamp)
|
recv_all(&mut iface, timestamp)
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in New Issue