Fail-free ingress
This commit is contained in:
parent
8d4e255090
commit
95829934db
|
@ -667,6 +667,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
|
|||
let response = $response;
|
||||
neighbor_addr = Some(response.ip_repr().dst_addr());
|
||||
device_result = inner.dispatch_ip(tx_token, timestamp, response);
|
||||
device_result
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -694,7 +695,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT>
|
|||
#[cfg(feature = "proto-ipv6")]
|
||||
(IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) =>
|
||||
respond!(IpPacket::Icmpv6((ipv6_repr, icmpv6_repr))),
|
||||
_ => panic!("Invalid ICMP represnetation"),
|
||||
_ => Err(Error::Unaddressable),
|
||||
}
|
||||
}),
|
||||
#[cfg(feature = "socket-udp")]
|
||||
|
|
|
@ -298,7 +298,7 @@ impl Dhcpv4Socket {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&mut self, now: Instant, ethernet_addr: EthernetAddress, ip_mtu: usize, emit: F) -> Result<()>
|
||||
where F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) {
|
||||
where F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()> {
|
||||
|
||||
// Worst case biggest IPv4 header length.
|
||||
// 0x0f * 4 = 60 bytes.
|
||||
|
@ -350,7 +350,7 @@ impl Dhcpv4Socket {
|
|||
// send packet
|
||||
net_debug!("DHCP send DISCOVER to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
|
||||
ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr));
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr))?;
|
||||
|
||||
// Update state AFTER the packet has been successfully sent.
|
||||
state.retry_at = now + DISCOVER_TIMEOUT;
|
||||
|
@ -376,7 +376,7 @@ impl Dhcpv4Socket {
|
|||
|
||||
net_debug!("DHCP send request to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
|
||||
ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr));
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr))?;
|
||||
|
||||
// Exponential backoff: Double every 2 retries.
|
||||
state.retry_at = now + (REQUEST_TIMEOUT << (state.retry as u32 / 2));
|
||||
|
@ -405,7 +405,7 @@ impl Dhcpv4Socket {
|
|||
|
||||
net_debug!("DHCP send renew to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
|
||||
ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr));
|
||||
emit((ipv4_repr, udp_repr, dhcp_repr))?;
|
||||
|
||||
// In both RENEWING and REBINDING states, if the client receives no
|
||||
// response to its DHCPREQUEST message, the client SHOULD wait one-half
|
||||
|
|
|
@ -402,7 +402,7 @@ impl<'a> IcmpSocket<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&mut self, emit: F) -> Result<()>
|
||||
where F: FnOnce((IpRepr, IcmpRepr))
|
||||
where F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>
|
||||
{
|
||||
let handle = self.meta.handle;
|
||||
let hop_limit = self.hop_limit.unwrap_or(64);
|
||||
|
@ -413,13 +413,7 @@ impl<'a> IcmpSocket<'a> {
|
|||
#[cfg(feature = "proto-ipv4")]
|
||||
IpAddress::Ipv4(ipv4_addr) => {
|
||||
let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
|
||||
let repr = match Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored()) {
|
||||
Ok(repr) => repr,
|
||||
Err(err) => {
|
||||
net_debug!("ICMPv4 represnetation invalid: {}", err);
|
||||
return
|
||||
},
|
||||
};
|
||||
let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?;
|
||||
let ip_repr = IpRepr::Ipv4(Ipv4Repr {
|
||||
src_addr: Ipv4Address::default(),
|
||||
dst_addr: ipv4_addr,
|
||||
|
@ -433,14 +427,7 @@ impl<'a> IcmpSocket<'a> {
|
|||
IpAddress::Ipv6(ipv6_addr) => {
|
||||
let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
|
||||
let src_addr = Ipv6Address::default();
|
||||
let repr = match Icmpv6Repr::parse(&src_addr.into(), &ipv6_addr.into(), &packet,
|
||||
&ChecksumCapabilities::ignored()) {
|
||||
Ok(repr) => repr,
|
||||
Err(err) => {
|
||||
net_debug!("ICMPv6 represnetation invalid: {}", err);
|
||||
return
|
||||
},
|
||||
};
|
||||
let repr = Icmpv6Repr::parse(&src_addr.into(), &ipv6_addr.into(), &packet, &ChecksumCapabilities::ignored())?;
|
||||
let ip_repr = IpRepr::Ipv6(Ipv6Repr {
|
||||
src_addr: src_addr,
|
||||
dst_addr: ipv6_addr,
|
||||
|
@ -450,7 +437,7 @@ impl<'a> IcmpSocket<'a> {
|
|||
});
|
||||
emit((ip_repr, IcmpRepr::Ipv6(repr)))
|
||||
},
|
||||
_ => net_debug!("ICMP destination unaddressable"),
|
||||
_ => Err(Error::Unaddressable)
|
||||
}
|
||||
})?;
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ impl<'a> RawSocket<'a> {
|
|||
|
||||
pub(crate) fn dispatch<F>(&mut self, checksum_caps: &ChecksumCapabilities, emit: F) ->
|
||||
Result<()>
|
||||
where F: FnOnce((IpRepr, &[u8])) {
|
||||
where F: FnOnce((IpRepr, &[u8])) -> Result<()> {
|
||||
fn prepare<'a>(protocol: IpProtocol, buffer: &'a mut [u8],
|
||||
_checksum_caps: &ChecksumCapabilities) -> Result<(IpRepr, &'a [u8])> {
|
||||
match IpVersion::of_packet(buffer)? {
|
||||
|
@ -275,6 +275,8 @@ impl<'a> RawSocket<'a> {
|
|||
net_debug!("{}:{}:{}: dropping outgoing packet ({})",
|
||||
handle, ip_version, ip_protocol,
|
||||
error);
|
||||
// Return Ok(()) so the packet is dequeued.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
|
|
@ -1669,7 +1669,7 @@ impl<'a> TcpSocket<'a> {
|
|||
|
||||
pub(crate) fn dispatch<F>(&mut self, timestamp: Instant, ip_mtu: usize,
|
||||
emit: F) -> Result<()>
|
||||
where F: FnOnce((IpRepr, TcpRepr)) {
|
||||
where F: FnOnce((IpRepr, TcpRepr)) -> Result<()> {
|
||||
if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) }
|
||||
|
||||
if self.remote_last_ts.is_none() {
|
||||
|
@ -1867,7 +1867,7 @@ impl<'a> TcpSocket<'a> {
|
|||
// to not waste time waiting for the retransmit timer on packets that we know
|
||||
// for sure will not be successfully transmitted.
|
||||
ip_repr.set_payload_len(repr.buffer_len());
|
||||
emit((ip_repr, repr));
|
||||
emit((ip_repr, repr))?;
|
||||
|
||||
// We've sent something, whether useful data or a keep-alive packet, so rewind
|
||||
// the keep-alive timer.
|
||||
|
|
|
@ -296,7 +296,7 @@ impl<'a> UdpSocket<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn dispatch<F>(&mut self, emit: F) -> Result<()>
|
||||
where F: FnOnce((IpRepr, UdpRepr, &[u8])) {
|
||||
where F: FnOnce((IpRepr, UdpRepr, &[u8])) -> Result<()> {
|
||||
let handle = self.handle();
|
||||
let endpoint = self.endpoint;
|
||||
let hop_limit = self.hop_limit.unwrap_or(64);
|
||||
|
|
|
@ -30,4 +30,4 @@ impl WakerRegistration {
|
|||
pub fn wake(&mut self) {
|
||||
self.waker.take().map(|w| w.wake());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -125,7 +125,7 @@ impl<'a, H> PacketBuffer<'a, H> {
|
|||
/// Call `f` with a single packet from the buffer, and dequeue the packet if `f`
|
||||
/// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
|
||||
pub fn dequeue_with<'c, R, F>(&'c mut self, f: F) -> Result<R>
|
||||
where F: FnOnce(&mut H, &'c mut [u8]) -> R {
|
||||
where F: FnOnce(&mut H, &'c mut [u8]) -> Result<R> {
|
||||
self.dequeue_padding();
|
||||
|
||||
let Self { ref mut metadata_ring, ref mut payload_ring } = *self;
|
||||
|
@ -136,9 +136,12 @@ impl<'a, H> PacketBuffer<'a, H> {
|
|||
payload_ring.dequeue_many_with(|payload_buf| {
|
||||
debug_assert!(payload_buf.len() >= size);
|
||||
|
||||
(size, Ok(f(header.as_mut().unwrap(), &mut payload_buf[..size])))
|
||||
match f(header.as_mut().unwrap(), &mut payload_buf[..size]) {
|
||||
Ok(val) => (size, Ok(val)),
|
||||
Err(err) => (0, Err(err)),
|
||||
}
|
||||
}).1
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
||||
/// Dequeue a single packet from the buffer, and return a reference to its payload
|
||||
|
|
|
@ -136,14 +136,18 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
|
|||
/// Call `f` with a single buffer element, and dequeue the element if `f`
|
||||
/// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
|
||||
pub fn dequeue_one_with<'b, R, F>(&'b mut self, f: F) -> Result<R>
|
||||
where F: FnOnce(&'b mut T) -> R {
|
||||
where F: FnOnce(&'b mut T) -> Result<R> {
|
||||
if self.is_empty() { return Err(Error::Exhausted) }
|
||||
|
||||
let next_at = self.get_idx_unchecked(1);
|
||||
let result = f(&mut self.storage[self.read_at]);
|
||||
self.length -= 1;
|
||||
self.read_at = next_at;
|
||||
Ok(result)
|
||||
match f(&mut self.storage[self.read_at]) {
|
||||
Ok(result) => {
|
||||
self.length -= 1;
|
||||
self.read_at = next_at;
|
||||
Ok(result)
|
||||
}
|
||||
Err(error) => Err(error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Dequeue an element from the buffer, and return a reference to it,
|
||||
|
@ -151,7 +155,7 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
|
|||
///
|
||||
/// This function is a shortcut for `ring_buf.dequeue_one_with(Ok)`.
|
||||
pub fn dequeue_one(&mut self) -> Result<&mut T> {
|
||||
self.dequeue_one_with(|buf| buf)
|
||||
self.dequeue_one_with(Ok)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue