These were flagged by `cargo clippy`:
warning: called `is_some()` after searching an `Iterator` with find.
This is more succinctly expressed by calling `any()`.
warning: this `.into_iter()` call is equivalent to `.iter_mut()` and
will not consume the `BTreeMap`
warning: called `skip_while(p).next()` on an `Iterator`
The skip_while conversion is a little tricky. Clippy notes that:
warning: called `skip_while(p).next()` on an `Iterator`
help: this is more succinctly expressed by calling `.find(!p)` instead
So the condition of the skip_while is inverted and then simplified using
De Morgan's laws.
These were flagged by `cargo clippy`:
warning: explicit lifetimes given in parameter types where they
could be elided (or replaced with `'_` if needed by type
declaration)
These were flagged by `cargo clippy`:
warning: this seems like a manual implementation of the
non-exhaustive pattern
The non_exhaustive attribute isn't available until we increase the
minimum Rust version to 1.40, so we should just silence these warnings
in the meantime.
These were flagged by `cargo clippy`:
warning: you don't need to add `&` to all patterns
This should have happened in ac830e8b, but I guess I missed it.
These were flagged by `cargo clippy`:
warning: you seem to be trying to use match for destructuring a
single pattern. Consider using `if let`
This also silences a few cases where the match couldn't be replaced with
an if because of the following error:
error: attributes are not yet allowed on `if` expressions
Once we increase the minimum Rust version to 1.43, these can be updated
as well.
Functions that only deal with IP packets take/return IpPacket's. IpPacket's
are wrapped into EthernetPacket's as late as possible.
This will later allow generalizing Interface to handle both Ethernet
and pure-IP mediums.
This commit fixes a small bug, where the TcpSocket computed the maximum
size per payload in a tx_buffer without taking into account the MTU
defined by the underlying network device.
Prior to this change, the neighbor cache would get limited even when the
device failed to process our arp packet, which could put the socket in
the waiting state in the next poll.
This change only limits the cache rate if the device successfully
consumed our packet.
Previously, the window update was sent anytime it changed. This is
not desirable for 2 reasons:
- It would send window updates in TimeWait or Closed states, which is incorrect.
- It would send window updates in states where we've already received the
remote side's FIN, such as CloseWait. This is not necessarily incorrect, but
is useless, since the remote side is not going to send us more data, therefore
it's not interested in our window size anymore.
This allows applications to distinguish whether the remote end has
gracefully closed the connection with a FIN (in which case it has
received all the data intact), or the connection has failed due to e.g. a
RST or a timeout (in which case the received data may be truncated).
Previously, `ack_reply()` was sending the ack number present in `remote_last_ack`,
which is only updated by `dispatch`. This means the ack replies could contain
a wrong, old ack number.
Most of the time this simply caused wasting an extra roundtrip until the socket state
settles down, but in extreme cases it could lead to an infinite loop of packets, such
as in https://github.com/smoltcp-rs/smoltcp/issues/338Fixes#338
This fixes build on latest nightly. The cause of the breakage
is this commit:
7c4ca59f4b
which added a #[must_use = "if you don't need the old value, you
can just assign the new value directly"] hint to mem::replace.
When packet buffer's payload buffer does not have enough contiguous
window left, the ring buffer roll over uses an incorrect size
causing the ring buffer pointer not resetting to the head.
When the payload enqueued is larger than 1/2 of the payload ring
buffer, this bug will cause the slice returned by
`PacketBuffer::enqueue` to not match the requested size, and
trigger `debug_assert` in debug profile or size mismatch panic in
`copy_from_slice` when compiled in release profile.
Although ordering is not specified in the spec, some implementations expect
some ordering (unforntunately I have found one that does, and blocks outbound
packets due to 'invalid tcp options').
Instead of configuring the ifaces ip address when a dhcp server offers
and ip, we now use the requested_ip option, based on the offered ip
(yiaddr). The user now only has to configure the iface once the dhcp
transaction has completed (Ack'd).
Disable ethernet-related features and framing based on a feature gate.
Add a no-ethernet option to Travis.
notes:
- allow(unused) is added when not using ethernet feature
- Don't run pretty-print doctest, ethernet is optional.
Closes: #308
Approved by: whitequark
The OPT_DOMAIN_NAME_SERVER DHCP option field can advertise an unbounded
DNS servers, but we currently use a fixed length array to store these
servers. This commit ensures only the first 3 (highest priority) servers
are used.
Fixes#305.
`TCPSocket` buffers are type `RingBuffer<'a, _>` whilst other
socket types have buffers with type `PacketBuffer<'a, 'b,
_>`.
There is an enum over socket types `pub enum Socket<'a, 'b: 'a>`,
which is in turn used by `set::Item` and `SocketSet`. The lifetime
`'b` is not required for `TcpSocket`, but the `Into<Socket>`
implementation for `TCPSocket` specifies the `'static` lifetime for
`'b`.
Therefore using `TCPSocket` in a `SocketSet` currently requires the
lifetime `'b` for other sockets to be `'static` which is unnecessarily
restrictive. This patch fixes this.
The lifetime signature of socket specifies `'b: 'a`, that is `'b`
outlives `'a`. Instead of `'static`, this is also satisfied by
`impl<'a> Into<Socket<'a, 'a>> for TcpSocket<'a>` as `'a` "outlives"
`'a` by definition.
The example
[here](https://gist.github.com/richardeoin/b562e79d0d499e00a8bf4944f00594d9)
fails to compile without this patch.
Closes: #304
Approved by: whitequark
Using move semantics allows an Option to keep track of the
initialization state while satisfying the borrow checker. This replaces
the functionality that the 'consumed' flag had before. It also retains
the smaller object size since the Option of a reference can use the
representation of the null pointer, which is an invalid reference, as a
niche for the None variant.
Closes: #301
Approved by: whitequark
Since 0.4.4, log uses #[macro_export(local_inner_macros)], which is
the right thing to do, but it breaks our CI because of a now-unused
\#[macro_use(log)].
This didn't ever actually cause UB because the drop implementation
should have compiled to a no-op under all conditions; `finish` is
a part of a patchset that never got in. (Even if it didn't, the code
should have been dynamically sound, under all but the most strict
interpretations of Rust's aliasing requirements.)
But it's still a problem, at least because there is a warning for
this potential unsoundness that will become an error in the future.
So everything else aside, we can't use this pattern going forward.
For now, remove the Drop impl, exploiting the fact that `finish`
is a no-op. Going forward this will likely require unsafe code, or
some fundamental change in the way SocketRef is implemented, but
I could not come up with any way to do it. :(
Actually, this is not a new requirement at all; because we do not
check the minimum version on CI, some dependencies on 1.28 have
already sneaked in. In particular, our required version of the crate
managed only works on 1.28+.
This allows us to use:
(1.28)
- ops::RangeBounds
- num::NonZero
Some trait bounds were added to make sure everything builds on 1.28.
This doesn't affect downstream code because log 0.3.9 is a facade
crate implemented in terms of log 0.4, and so log 0.3 and log 0.4
APIs can be used together.
This allows us to use:
(1.26)
- impl Trait
- autoderef in pattern matching
- fixed slice patterns
- inclusive ranges
(1.27)
- dyn Trait
- #[must_use] on functions
To prepare for edition change, dyn is added where applicable. Other
edition changes would require bumping the requirement even higher,
and so they are not applied for now.
Adds accessor functions to the device implementing the phy::Device trait
within an ethernet interface. The intent is to allow access to read-only
methods such as gathering of device statistics or other diagnostics
while the interface is running. The interface does not hold any internal
invariants on the device, so that a mutable accessor can be added as
well.
Closes: #289
Approved by: whitequark
Allow the control flow to continue when udp parsing encounters an
invalid checksum within an ipv4 packet, instead of returning with an
error. Additionally adds a test to ensure the correct behaviour.
Closes: #280Closes: #290
Approved by: whitequark
Fixes a denied lint uncovered on a recent nightly compiler version,
apparently through improved analysis. The code in question is only
compiled with the proto-ipv6 feature and older compiler versions did not
detect the unused qualifier, sometime around 2019-04-23.
Closes: #291
Approved by: whitequark
A regression meant broadcast IPv4 packets were ignored. Restore
handling those packets and also reply to broadcast ICMPv4 echo requests.
Closes#287.
Closes: #288
Approved by: whitequark
Converting from `::std::net::*` types to the ip related library structs
previously required both ip-version features to be enabled. This
introduced dedicated converters from the ip-version specific standard
address and endpoint representations (`IpV4Addr`, `IpV6Addr`,
`SocketAddrV4`, and `SocketAddrV6`) that are enabled without requiring
the other ip-version feature to be selected.
Closes: #286
Approved by: whitequark
This allows any type that can be converted into an `i64` to be used when
creating an Instant. Because this is no longer a concrete type, this
change may break existing code like the following:
error: attempt to multiply with overflow
--> src/time.rs:282:37
|
282 | epoc = Instant::from_millis(2085955200 * 1000).into();
| ^^^^^^^^^^^^^^^^^
|
= note: #[deny(const_err)] on by default
Closes: #272
Approved by: whitequark
Only allowing four missing packets is hurting
performance for large receive windows.
The new value was picked by observing good
performance with 500 kB socket buffers.
Closes: #264
Approved by: whitequark
The current hole was always shrinked even if the
packet assembler rejected adding a packet due to
not being able to insert a new hole.
Shrink only after a new hole was added.
Shrinking before or after does not make a difference
because offset + size < hole_size and thus
contigs[index] is not empty, passing the
debug_assert in add_contig_at.
https://github.com/m-labs/smoltcp/issues/261Closes: #265
Approved by: whitequark
This cargo feature only exists because (a) ARTIQ uses a fork of Rust,
(b) Rust has some ridiculous renaming going on in the alloc crate,
(c) smoltcp exists because of ARTIQ.
Such features will not be ordinarily provided by smoltcp.
The presence of TCP options will only increase
the header length to muliples of 4. The added
padding consists of zeros.
This also fixes an emit panic when the Window
Scale and MSS options result in a length of 27
which then gets floored to 24 when applied to
the header.
Closes: #251
Approved by: whitequark
The size of the contiguous window should be prioritized over the size of
the contiguous window if padding were added.
For example, given the following packet buffer:
1 2 3
|---|----|------|
If 2 is used and 1 and 3 are empty, enqueing a buffer of size 4 should
be placed in contiguous window 3 and the size of 1 should not cause
any issues in enqueue.
Closes: #247
Approved by: whitequark
Using Routes<'static> used to make these functions impossible because it created a reference that needed to be valid for the static lifetime
Closes: #243
Approved by: dlrobertson
Improve detection of duplicate ACKs by checking that the segment does
not contain data.
Move implementation from the 'reject unacceptable acknowledgements'
to later in the process function, because a duplicate ACK is not an
'unacceptable' acknowledgement but rather a condition to update state.
Implement more tests to verify the operation of the fast retransmit
implementation.
Related issue: #224Closes: #225
Approved by: whitequark
- Add a helper function for returning an error in the implementation of
next
- Add an assert in Ipv6OptionsIterator::new that ensures that an
iterator is not created with a length field larger than that of the
data buffer we're iterating over.
Closes: #230
Approved by: dlrobertson
The IPv6 Option representation layer structure includes the type value
as the raw u8. This should be stored as the Type enum.
Closes: #229
Approved by: whitequark
- Do not require the packet structure of the header have the same
lifetime as the underlying bytes or the parsed representation.
- Add the bytes of the contained options to the parsed representation
structure.
- Add the IPv6OptionsIterator structure to make iterating over the
contained options easier.
Closes: #212
Approved by: whitequark
This optimization makes sure that enqueueing to an empty ring buffer
would never wrap around, in turn ensuring that enqueueing to an empty
packet buffer would never use more than one metadata entry.
Right now, pushing buffer-sized packets into a packet buffer requires
at least two metadata entries, which is surprising and wasteful.
Implement a simple way to discover and respond to three duplicate ACKs
from the reciver of the data. This leads to a fast retransmit of the
last unacknowledged seqment. This is feature is described in [RFC 5681].
Closes: #104Closes: #214
Approved by: whitequark
Add the FailureType enumeration that can be acquired from a IPv6
extension header option which determines the required action if the
extension header option type is not known or is not supported.
Closes: #204
Approved by: whitequark
Only ACKs generated by `dispatch` were updating
`remote_last_win` but not the ACKs generated by
`process`, failing to keep track of the last
announced receive window. This left
`window_to_update` to return false in `dispatch`
after the RX buffer was emptied, thus not announcing
that the receive window is not zero anymore.
The change updates `remote_last_win` for immediate
ACKs generated by `process`.
Closes: #200
Approved by: whitequark
Each given NDISC packet type may only include one of a few options.
Instead of including the options in the NDISC repr as a &[u8] include
the packet types available options as `Option<T>`.
Closes: #194
Approved by: whitequark
- Add a function to EthernetInterface useful for determining if a
received packet with the source address being a solicited node
address is the solicited node address for an IPv6 address assigned
to the interface.
- Add SOLICITED_NODES_PREFIX to Ipv6Cidr
- Fix some nits
Closes: #175
Approved by: whitequark
- Correct from_system_time implementation
- Add missing functions and implementations to Instant type
- Add missing frnction to Duration type
Closes: #141
Approved by: whitequark
- Update documentation about current support in the wire module
- Ensure the possible panic is documented for Ipv6Option::data_mut
- Add a Repr structure for Ethernet II headers
Add basic ICMPv6 handling
- ICMPv6
- Handle ICMPv6 echo requests
- Send ICMPv6 error messages
- When know listening UDP socket is found in process_udp
- When the next header is not known
- Update icmpv6 test to be more useful
- ICMPv4
- Handle one more case where we are sending too much data
- Improve TimeExceeded support
- Add support for message codes
- Add the TimeExceeded enum type
- Improve ParamProblem support
- Add support for message codes
- Add the ParamProblem enem type
Closes: #152
Approved by: whitequark
- Add `process_ipv6` to `EthernetInterface`
- Add basic test for `process_ipv6`
- Add `deny(unused)` if either proto-ipv4 or proto-ipv6 is enabled
- Add `cfg`s where needed to avoid compile time errors due to the above
* The IPv6 address parser now handles IPv4 mapped IPv6 addresses which
take on the form ::ffff:x.x.x.x.
* Implement Display for IPv4 mapped IPv6 addresses
* Implement From<IPv4Address> for IPv6Address
Fixes#86
- There are several warnings that are thrown when running `cargo doc`. Fix
these warnings.
- Convert all module documentation to use /*! for consistency.
- Add MIN_MTU constants to the IP version modules.
- Ensure that ICMPv4 error replies comply with the size requirements
specified in RFC 1812 § 4.3.2.3.
The previous model was flawed. Consider the following case:
* The main loop looks as follows (pseudocode):
loop {
let _ = (tcp:1234).read_all()
wait(iface.poll())
}
* The remote end is continuously transmitting data and at some
point fills the window of (tcp:1234), stopping the transmission
afterwards.
* The local end processes the packets and, as a part of egress
routine, emits an ACK. That also updates the window, and
the socket's poll_at() routine returns None, since there is
nothing to transmit or retransmit.
* The local end now waits indefinitely even though it can start
processing the data in the socket buffers right now.
This would result in results near usize::MAX, and is indicative of
a bug. A panic is always used instead of a debug_assert!() because
debug builds are easily slow enough so that the underlying bugs
are not tripped.
Related to #62.
- Add the ipv6 feature
- Ensure a travis build with the ipv6 feature enabled.
- Add the necessary infrastructure to wire for ipv6 support.
- Ipv6Address
- Ipv6Cidr
- Add Ipv6 Address and Cidr parsing to parsers
- Add basic tests.
The rate of emission of neighbor discovery packets is already
limited at the level of the entire neighbor cache, but poll()
would uselessly spin until the answer arrives (if ever).