Commit Graph

623 Commits

Author SHA1 Message Date
whitequark 7c0bae7d36 Simplify. NFC. 2017-12-27 00:09:50 +00:00
Dan Robertson 439e0a2cc1 Add the proto-ipv4 feature. 2017-12-24 13:28:59 +00:00
Herman J. Radtke III 260e3d996f Implement FromStr for IpEndpoint
Fixes #81
2017-12-24 12:08:16 +00:00
Josh Gangloff fe3e67d544 Make IP checksum loop use larger chunks to ease autovectorization. 2017-12-23 22:26:16 +00:00
whitequark d8685dbb1e Unswitch the IP checksum loop for 30% improvement in performance. 2017-12-23 12:17:39 +00:00
whitequark b2c2214725 Convert all assert!s not documented as panics into debug_assert!s.
Document the rest.
2017-12-22 20:38:54 +00:00
whitequark 436f4ef624 Correctly handle retransmission of lost-received-lost TCP segments.
Thanks @pothos for initial analysis of the issue.
2017-12-22 19:31:04 +00:00
whitequark ae17151f2a Fix a few documentation issues. NFC. 2017-12-22 13:13:43 +00:00
whitequark a45b3d9eab TcpSocket::recv_impl should have never been public, oops. 2017-12-22 13:11:11 +00:00
whitequark 85487bf3bc EthernetInterface::set_ipv4_gateway should panic on non-unicast addrs. 2017-12-22 13:07:11 +00:00
whitequark f1a7fbe973 Split `poll_at`/`poll_delay` out of `poll`.
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.
2017-12-22 12:59:52 +00:00
whitequark fec3bb32eb Make the log crate properly optional. 2017-12-22 09:57:38 +00:00
whitequark 8b6050f711 Clean up our feature story and more aggressively test features. 2017-12-22 08:54:58 +00:00
whitequark 3029341d5a Panic on an attempt of subtracting sequence numbers with underflow.
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.
2017-12-21 12:35:15 +00:00
whitequark bd40265d3a Use a more specific log message for keep-alive or probe TCP packets. 2017-12-21 10:39:54 +00:00
whitequark bf53b73e09 Fix accidental conversion of a slice to owned.
This broke #![no_std] builds.
2017-12-18 15:03:38 +00:00
whitequark 946376897e Make EthernetInterfaceBuilder::ip_addrs optional.
It's perfectly reasonable to have an interface with no addresses
assigned to it.
2017-12-18 13:53:27 +00:00
Dan Robertson c5c2264cdc Use hop limit instead of ttl
Use hop limit instead of ttl for method and member names.
2017-12-18 13:47:34 +00:00
Dan Robertson ee60efefd3 Add Ipv6Repr and Ipv6Packet to wire
- Add the Ipv6Repr and Ipv6Packet structures to the wire module
 - Add basic tests for the new structures
 - Update IpRepr to include the Ipv6 variant
2017-12-18 13:47:34 +00:00
Dan Robertson 4a98190f9b Replace EthernetInterface::new with EthernetInterfaceBuilder. 2017-12-18 13:29:29 +00:00
whitequark 278bb4b2c9 Trace the TCP socket acknowledging incoming segment. 2017-12-18 12:47:42 +00:00
whitequark 05677dbd76 Fix 14185a16. 2017-12-18 11:42:55 +00:00
whitequark 19f52bd46c Do not fill neighbor cache with IPs not on the same network as us.
This is pointless (`route` doesn't even check the cache in that case)
and wastes cache space.
2017-12-18 11:06:26 +00:00
whitequark 8dd9bdeaad Trace neighbor discovery status on a per-socket basis.
This avoids delaying the first packets for new neighbors by
(at least) the ARP cache silence time, or potentially even
indefinitely.
2017-12-18 11:06:24 +00:00
whitequark 16b59eefad Style. NFC. 2017-12-16 21:45:24 +00:00
whitequark 75e371d947 Rework the pretty printer to avoid superfluous trailing newlines. 2017-12-16 21:42:19 +00:00
whitequark c19bd1da7c Make elaborated reasons for sending a TCP packet more precise. 2017-12-15 06:31:50 +00:00
whitequark 1c7ce85004 Log an elaborated reason for sending a TCP packet.
Otherwise, it is hard to debug e.g. ACK loops.
2017-12-15 05:24:17 +00:00
Dan Robertson 888b098dca Process the Icmpv4Repr in IcmpSocket::process
- Use the Icmpv4Repr in IcmpSocket::process instead of the raw payload.
 - Update the IcmpSocket tests.
2017-12-09 00:10:09 +00:00
whitequark 26b8052ee9 Make packet dumps emitted for broken packets more useful.
Before this commit, only the outermost frame (the Ethernet one)
would be shown, which is really no help at all.
2017-12-08 07:11:08 +00:00
Dan Robertson be43f4067a Minor doc improvements to wire::ipv6
- Add links to the Addressing Achitecture RFC where appropriate
 - Add comments to functions where appropriate
2017-11-30 19:20:42 +00:00
Dan Robertson b97c592671 Add IPv6 address and cidr to wire
- 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.
2017-11-29 12:57:22 +00:00
Jeremy Soller 8604eaa8f9 Allow receiving broadcast packets via UDP sockets. 2017-11-23 07:01:35 +00:00
Dan Robertson 308afc5a25 Remove debug println in test_evict
The println's surrounding the final cache fill in test_evict that causes
PADDR_B to be evicted are not needed.
2017-11-22 08:03:39 +00:00
whitequark ff530020dd Style. NFC. 2017-11-22 07:44:03 +00:00
whitequark 98a3ec8c3a Limit the rate at which sockets will request neighbor discovery.
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).
2017-11-22 07:20:31 +00:00
whitequark 6c83936872 Extract socket handle into a new SocketMeta structure.
This paves way for adding more metadata apart from handles,
such as caches and so on.

This commit also removes SocketHandle::EMPTY in favor of
SocketHandle::default() since they are functionally identical.
2017-11-22 03:50:09 +00:00
whitequark 715aa4b217 Add a missing feature check. 2017-11-21 12:02:25 +00:00
whitequark 52a6e27206 Implement eviction in neighbor cache for fixed storage size. 2017-11-21 11:53:26 +00:00
whitequark 29a338228d Fix a broken macro invocation. 2017-11-21 11:06:53 +00:00
whitequark eaa50d0003 Rewrite the ARP cache to allow for flood protection and expiration. 2017-11-21 10:53:55 +00:00
Kai Lüke 2a52234d53 Don't panic on TCP sequence number wrapping in debug mode. 2017-11-13 18:03:36 +00:00
Egor Karavaev 1e809daf7a Make `Error::Unaddressable` ignored for ICMP sockets as well. 2017-11-13 14:16:03 +00:00
Egor Karavaev eb7d0e346e ICMP sockets don't end ICMP packets processing. 2017-11-13 14:16:03 +00:00
Kai Lüke 3db035bbac Preserve retransmission timer for Dup-ACKs
Duplicate ACKs should not replace the retransmission timer,
but if not in retransmission, still set the keep-alive timer
as normal ACKs do.
2017-11-13 06:26:26 +00:00
whitequark 959e4829a9 Fix ICMP socket documentation. NFC. 2017-11-13 04:54:49 +00:00
whitequark 19373c58c8 Style. NFCI. 2017-11-09 02:07:24 +00:00
whitequark 65c8aea921 Remove impl Ord/PartialOrd for Cidr.
It's not obvious that CIDRs are ordered in any particular meaningful
way.
2017-11-09 01:50:34 +00:00
Dan Robertson adb5014780 Add ICMP sockets
- Add support for ICMP sockets
 - Add tests for ICMP sockets
 - Rename proto-<type> features to socket-<type>
 - Update documentation
2017-11-09 00:08:24 +00:00
Philipp Oppermann c3e07dad9a Store plain DeviceT instead of Managed<_> in EthernetInterface 2017-11-08 09:34:35 +00:00
whitequark d9fa7f6bc6 Rename proto-* features back to socket-*.
A proto-* feature does not make sense for ICMP, where the protocol
is always enabled, but sockets, not.
2017-11-06 09:51:03 +00:00
whitequark c2994b9757 Reimplement {RawSocket,TapInterface}::receive correctly. 2017-11-06 09:38:44 +00:00
whitequark 7039ec8b04 Rename a few tests. NFC. 2017-11-04 02:42:51 +00:00
whitequark 9e783cb570 Add CODE_STYLE.md. 2017-11-03 23:34:12 +00:00
Philipp Oppermann 6a8e21cec0 Redesign the phy::Device trait to avoid Drop impls. 2017-11-03 23:15:07 +00:00
Dan Robertson b64257812b Do not send ICMPv4 responses to broadcasts
- Do not send ICMPv4 responses for packets with a broadcast destination
   address.
   - Do not send DstUnreachable with ProtoUnreachable on receipt of a
     packet with an unknown protocol with a non-unicast destination
     address.
   - Do not send DstUnreachable with PortUnreachable on receipt of a
     UDP packet when no sockets are listening on the destination port
     and the destination address is a non-unicast address.
 - Send the correct amount of the original datagram when sending Destination
   Unreachable error responses.
   - Do not assume that a ip datagram has a payload when sending a proto
     unreachable ICMPv4 error response.
 - Add tests to iface tests.
   - Ensure ICMP error responses are correctly formed when the
     datagram has no payload.
   - Ensure ICMP error responses are correctly handled for UDP packets
     when no socket is listening on the destination port.
   - Ensure the correct amount of the original payload is returned in
     Destination Unreachable responses.
2017-11-01 06:34:10 +00:00
whitequark fe6b04a29a Rework TcpSocket::{send,recv} to remove need for precomputing size.
Now, these functions give you the largest contiguous slice they can
grab, and you return however much you took from it.
2017-10-31 19:24:54 +00:00
whitequark 0b22943ddd Fix Cidr::contains_addr for zero length prefixes. 2017-10-30 08:25:32 +00:00
whitequark 33fa859665 Do not parse an empty string as an IpAddress.
This is more likely to result in downstream confusion than not.
Let downstream code decide exactly what it wants to do with
an empty string; be conservative here.
2017-10-30 07:20:55 +00:00
Dan Robertson 1cafcfc19f Tests: Add basic interface tests
- Add tests for the following
   - ICMP error responses are not sent in response to broadcast requests
   - ARP requests are responded to and inserted into the cache
   - ARP requests for someone else are not responded to, but the sender
     is still inserted in the cache
2017-10-28 19:33:01 +00:00
whitequark d37f4ef254 Use a much more sensible method naming for SocketRef. 2017-10-25 02:16:23 +00:00
whitequark 103fff9233 Expose wrapping and unwrapping of SocketRefs. 2017-10-25 01:28:59 +00:00
whitequark a9a00baa49 Rename Cargo features: socket-* → proto-*. 2017-10-25 00:20:40 +00:00
whitequark e495544a85 Fix a naming mishap. NFCI. 2017-10-24 23:55:58 +00:00
whitequark a7e6a1b5ae Simplify. NFC. 2017-10-24 23:12:55 +00:00
whitequark 1cd3625bf4 Small adjustments to TTL code; style, docs, and tests. NFCI. 2017-10-24 23:12:55 +00:00
Dan Robertson eef65d2676 Implement set_ttl for Tcp and Udp sockets
- Add the ttl member to the IpRepr
 - Add the ttl member along with setters and getters to the tcp and udp
   socket types
 - Add unit tests for the new set_ttl parameter
 - Update usage of IpRepr to include the ttl value
2017-10-24 23:02:18 +00:00
whitequark 4f689be81b Dump malformed ingress packets at DEBUG log level. 2017-10-24 20:37:52 +00:00
whitequark fa636b9fcb Style fixes. 2017-10-24 18:08:22 +00:00
whitequark af69c6de82 Fix a (future) syntax error in the net_log macro. 2017-10-15 10:10:08 +00:00
Egor Karavaev 19b1b764ed Implement a SocketRef smart pointer to detect state changes. 2017-10-05 03:44:20 +00:00
whitequark 52600cd521 Replace "socket debug identifiers" with just socket handles.
This is basically a rename that now calls an apple an apple,
except user code can no longer change it. It's not obvious if
user code getting the socket handle from the socket is very useful,
but it's not harmful either, so why not.
2017-10-05 03:02:41 +00:00
whitequark eb33cdcf68 Fix a typo. 2017-10-04 01:54:39 +00:00
whitequark b2cfb94b48 Explain the return value of poll(). 2017-10-03 20:41:45 +00:00
whitequark bf9584555c Drop the pretense that anyone cares about non-IP over Ethernet.
To be precise, I'm talking about IPX, AppleTalk and DECnet here,
not things like PPPoE, ATAoE, FCoE, or PTP, which make sense
to implement on top of EthernetInterface but do not work on
the same level on top of it as IP.
2017-10-03 15:17:29 +00:00
Egor Karavaev 5be76b8dc1 Add support for IPv4 default gateway. 2017-10-03 15:17:29 +00:00
Egor Karavaev f57de10625 Implement wire::{IpCidr/Ipv4Cidr}. 2017-10-03 14:27:17 +00:00
whitequark 72481c2661 Formatting. NFC. 2017-10-03 14:27:01 +00:00
whitequark e4fb2b2997 Make sure IpAddress prohibits exhaustive matches.
I forgot to ensure this.
2017-10-03 13:22:09 +00:00
whitequark 3fa1d60be0 Only verify checksum in pretty printers, do not bail out if invalid.
This lets us e.g. deal with checksum offload on egress packets.
2017-10-03 07:09:53 +00:00
whitequark cf986bf20b Fix insufficient length validation in IPv4 packets.
Found via cargo-fuzz.
2017-10-02 23:03:41 +00:00
whitequark f60e689b04 Reword checksum-related documentations.
cc @steffengy
2017-10-02 21:52:30 +00:00
whitequark 30754efc4f Formatting. NFC. 2017-10-02 21:51:43 +00:00
Steffen Butzer 61cb64406d support hardware based checksum settings in during packet send/recv
- makes sure the checksum is zeroed when not emitted by software
  (This is required by some implementations such as STM32 to work properly)
2017-10-02 21:40:08 +00:00
Steffen Butzer f9093d15aa phy: introduce hardware based checksum settings, rename DeviceLimits
this contains a rename of occurrences of
DeviceLimits -> DeviceCapabilities.
2017-10-02 21:40:08 +00:00
whitequark ba93552ccd Fix many warnings. 2017-09-25 00:55:54 +00:00
whitequark dd0f4b706a Enforce some lints. 2017-09-25 00:46:53 +00:00
whitequark 4826d37c45 Allow disabling any of: raw, TCP or UDP sockets. 2017-09-25 00:20:22 +00:00
whitequark 0a8a962e94 Reorganize features using namespaces, to match module hierarchy.
I'm about to add a whole lot more features, and it's going to get
quite confusing otherwise.
2017-09-24 23:51:19 +00:00
whitequark 38f648affb Add some docs. 2017-09-24 23:29:42 +00:00
Egor Karavaev 0e88617b82 Uncomment associated constants. 2017-09-24 23:25:18 +00:00
whitequark 9c3534e452 A few cosmetic changes to TCP socket trace messages.
No functional change.
2017-09-24 13:39:23 +00:00
whitequark 32d720831a Completely redo the logic of TCP socket polling.
The previous implementation made no sense. It is obvious that
poll_at() should use the same mechanisms to decide whether dispatch()
should be called as dispatch() itself uses to decide whether to send
anything.

This fixes numerous busy looping issues that arise if the return
value of poll() is used for waiting.
2017-09-24 13:20:56 +00:00
whitequark 96b284a30f Fix two issues that may cause TCP sockets to be polled too late.
1. Apart from non-empty transmit buffer, a state which transmits
   a FIN flag should also be considerd. Otherwise, closing a socket
   with an empty transmit buffer may retransmit the FIN flag forever.
2. Timeout poll requests should only be overridden by timer poll
   requests when the latter is earlier.
2017-09-24 11:04:55 +00:00
whitequark 8db752eb7a Fix a typo in documentation. 2017-09-24 08:23:46 +00:00
whitequark 8e13333988 Remove all remnants of the collections feature. 2017-09-22 20:40:13 +00:00
whitequark 711c05f7b1 Make TCP more RFC 5681 compliant wrt immediate ACKs. 2017-09-22 18:57:47 +00:00
whitequark a5a9bb44c9 Clarify inline TCP documentation. 2017-09-22 18:40:23 +00:00
whitequark a1b2605af7 Revert "Keep dispatching packets from a socket as long as there are any."
This reverts commit 51b2f18d1165bf7257de8894df101299cc93b094.

There's no throughput difference so far as I could measure, but
this greatly increases worst-case latency. At some later point
we could perhaps pass a deadline to the poll function, but for now
reverting this is simple enough.
2017-09-22 18:09:18 +00:00
whitequark 05a480575c Keep dispatching packets from a socket as long as there are any.
Typically, the poll function is used as a part of a larger RTOS.
If we only dispatch one packet per socket per poll() call,
then we have to wait for a complete scheduler roundtrip,
which is potentially a lot of time, and as a result we are
not filling the peer's window efficiently.
2017-09-22 17:55:49 +00:00
whitequark b90cee43bb Fix a warning. 2017-09-22 17:38:58 +00:00
whitequark 8166037a91 Handle buffer wraparound in TCP reassembly code. 2017-09-22 17:10:51 +00:00
whitequark 075a2ebb83 Make sure all side-effectful RingBuffer methods are #[must_use].
Some of them already use Result, but the ones that can return
an empty slice (or a slice shorter than requested) also must have
their return value (at least) checked.
2017-09-22 17:08:46 +00:00
whitequark 0bbab2aeed Add RingBuffer::{enqueue_allocated,dequeue_allocated}.
These should be used instead of enqueue_many because they do not
require the caller to handle wraparound explicitly.
2017-09-22 17:04:56 +00:00
whitequark e6bf27d078 Add RingBuffer::{read_allocated,write_unallocated}. 2017-09-22 16:23:37 +00:00
whitequark 5aae15aaba Fix an issue where TCP packets would have zero IP payload length. 2017-09-22 10:14:26 +00:00
whitequark a9d6a9b7b8 Fix a few warnings. 2017-09-22 10:06:40 +00:00
whitequark 7a2cd7842d Implement reassembly of out-of-order TCP segments. 2017-09-22 10:06:40 +00:00
whitequark b6e4e23868 Clean up PSH flag handling. 2017-09-22 08:15:29 +00:00
whitequark d7da46fd3b Do not clear remote_last_ts in TcpSocket::set_timeout().
After this change, if an 1s timeout is set on a socket that received
no packet for 2s, it will be instantly aborted, which seems
more reasonable. Also, this makes the `self.remote_last_ts.is_none()`
branch in TcpSocket::dispatch() actually behave as described.
2017-09-22 06:16:58 +00:00
whitequark f23bfe2014 Clean up and document TCP MSS calculations. 2017-09-22 06:02:03 +00:00
whitequark ba2d7f483a Implement a buffer (re)assembler. 2017-09-20 20:46:15 +00:00
whitequark 2c4222a0b6 smoltcp;:parsing → smoltcp::parsers. 2017-09-20 20:18:50 +00:00
whitequark 9281733209 Implement TCP timeouts. 2017-09-18 11:05:40 +00:00
whitequark fe80bca19d Implement TCP keep-alive. 2017-09-16 10:54:59 +00:00
whitequark be0dcb145c Fix warnings. 2017-09-15 06:05:41 +00:00
whitequark e8788be3a0 RingBuffer::{empty,full}→is_{empty,full}.
Query methods in Rust conventionally start with the "is" prefix.
2017-09-08 23:23:40 +00:00
whitequark 5ffce2c1a6 Remove Error::Rejected.
This wasn't an actual error, just a poorly designed communication
mechanism between sockets and whatever lies on the layer below them.
2017-09-08 00:59:46 +00:00
Egor Karavaev 8404fe908c Factor out TcpSocket::accepts. 2017-09-08 00:57:42 +00:00
Egor Karavaev 02b699e18c Factor out UdpSocket::accepts. 2017-09-08 00:57:19 +00:00
Egor Karavaev b4d6a53e34 Factor out RawSocket::accepts. 2017-09-08 00:56:42 +00:00
whitequark 9b242c7099 Send a challenge ACK in response to an unacceptable TCP ACK. 2017-09-08 00:11:44 +00:00
whitequark 844843c4bc Remove RingBuffer::set_len().
set_len() with a positive length change is better represented
with enqueue(), and set_len() with a negative length change
is not really a valid operation on its own.
2017-09-07 23:54:39 +00:00
whitequark 1102bd94e7 Refactor the "random access" ring buffer interface. 2017-09-07 23:47:42 +00:00
whitequark 5dc0353b2a Refactor the "continuous" ring buffer interface.
This also makes TcpSocket::{send,recv}_slice slightly more efficient
in case when the slice wraps around the corresponding buffer,
halving the necessary amount of calls.
2017-09-07 21:17:31 +00:00
whitequark a9719f4a13 Merge the TCP ring buffer and generic ring buffer.
This adds a few methods to RingBuffer that don't quite fit into
its interface (the slice ones), but we can fix that later.
2017-09-07 00:09:34 +00:00
whitequark 27a23ed3c3 Don't instantly ACK every received TCP segment.
This is prohibited by RFC 1122. Instead, aggregate them, and respond
once in the egress function.

However, still instantly send challenge ACKs to trigger fast
retransmit.
2017-09-05 23:23:50 +00:00
whitequark 8876d71802 According to RFC 1122, unsupported IP options MUST be ignored. 2017-09-01 19:31:09 +00:00
whitequark 7db21529e5 An unaddressable egress packet should not be a reportable error. 2017-09-01 10:30:56 +00:00
whitequark f8edf0faea Unbreak traffic shaper in the fault injector. 2017-08-31 21:39:01 +00:00
whitequark b585fbd368 Exhaustion of transmit buffers should not be a reportable error. 2017-08-31 16:27:50 +00:00
whitequark 6da3e5f217 Fix an inaccurate comment. 2017-08-31 14:33:10 +00:00
whitequark 47770a5ec2 Fix an unused import warning. 2017-08-31 14:31:32 +00:00
whitequark a71542b2f2 Allow querying the size of the TCP transmit and receive buffers.
This may be useful to e.g. ensure the complete transmit buffer
is flushed before proceeding.
2017-08-31 13:22:20 +00:00
whitequark 13dbe09fba TCP socket debug messages "sending <flags>" should be at DEBUG level.
They're not exceptional.
2017-08-31 12:39:05 +00:00
whitequark 80e510c9e2 Dispatch a TCP ACK every time window increases at all.
Commit 21282fdb was not completely sufficient because e.g. receiving
one octet and then blocking meant that an ACK with window length
of one is then sent, and this isn't motivating the other TCP stacks
all that much.

In any case, preemptively notifying the peer of window size increase
can only be beneficial, modulo network congestion.
2017-08-31 00:14:29 +00:00
whitequark 5e48567297 Send a TCP ACK after window increases from zero to non-zero. 2017-08-30 23:09:31 +00:00
whitequark 6324d3384a More rigorously treat the TcpSocket::remote_last_ack field.
Zero is a valid sequence number, treating it as an absence of value
isn't any good. This is unlikely to cause any real harm but it
just isn't good practice, nor does it make for understandable code.
2017-08-30 22:40:07 +00:00
whitequark 41ceeea9ac Fix the TCP SEQ acceptability check.
It has nothing to do with the last ACK transmitted.
2017-08-30 22:26:35 +00:00
whitequark c2bc20e9bf Move the TCP receive window clamping hack downwards in stack.
Otherwise, our response ACKs did not get the clamping treatment,
and severe packet loss resulted.

Also, explain why it's needed and how it works.
2017-08-30 14:00:14 +00:00
whitequark d53bdab029 Fix Ipv4Packet::payload{,_mut}() returning overly long buffers.
These functions only skipped the header, but what they should have
done is cut the packet at its total length and skip the header.
Otherwise, if the buffer the IP packet is constructed from contains
padding, such as Ethernet packets, the payload would be too long.
2017-08-30 13:34:50 +00:00
whitequark 5a066fbc6c Return from EthernetInterface::poll() on errors, don't swallow them.
We still print them into our debug log though, because it has more
context; the caller may opt to ignore any poll errors and only
use the smoltcp debug log as a, well, debugging aid, or it could
print user-visible warnings to alert the user to unusual network
conditions.
2017-08-30 10:20:11 +00:00
whitequark 7b3574e6ee Rework TCP retransmit logic to be much more robust.
Before this commit, if the amount of data in the buffer caused it
to be split among many outgoing packets, and retransmit timer
was active, the socket would behave very erratically and flood
the peer.
2017-08-30 10:12:53 +00:00
whitequark 996389d653 Compute soft deadline in poll() and use nonblocking sockets.
Before this commit, anything that touched RawSocket or TapInterface
worked partly by accident and partly because of a horrible crutch
that resulted in massive latencies as well as inevitable packet loss
every time an ARP request had to be issued. Also, there was no way
to use poll() other than by continuously calling it in a busy loop.

After this commit, poll() indicates when the earliest timer expires,
and so the caller can sleep until that moment (or until packets
arrive).

Note that there is a subtle problem remaining: every time poll()
is called, every socket with a pending outbound packet whose
IP address doesn't correspond to a MAC address will send a new
ARP request, resulting in potentially a whole lot of such requests.
ARP rate limiting is a separate topic though.
2017-08-29 19:47:11 +00:00
whitequark 7cd7bd4683 Reset the timer transitioning from TCP FIN-WAIT-1 to FIN-WAIT-2.
We don't transmit anything in FIN-WAIT-2, so we don't need the timer
running, or we'll get spurious log messages about retransmissions.
This also makes logic cleaner, although with no functional change.
2017-08-29 19:47:11 +00:00
whitequark cdf236412f Clarify a function name. 2017-08-28 12:45:33 +00:00
whitequark f84b234a38 Add a test for TCP sockets returning ACKs even with zero window. 2017-08-28 06:01:21 +00:00
whitequark 695c61fd05 Break up the EthernetInterface::dispatch macro atrocity into functions.
There wasn't any real reason for it to be a macro, it was ugly
and unreadable, and it resulted in combinatorial bloat when compiled.
2017-08-28 05:49:56 +00:00
whitequark 34db543cac Factor out packet parsing from Socket::process.
Not only is it incredibly wasteful, but this information is
in any case already necessary within the EthernetInterface::process_*
methods.
2017-08-28 05:48:16 +00:00
whitequark 379bc60924 Get rid of unused arguments in Socket::{process,dispatch}.
I've left those "for consistency" but it just implies data
dependencies where there are none, and bloats signatures.
2017-08-28 04:14:25 +00:00
whitequark 760174048d Get rid of IpPayload and indirection in Socket::dispatch.
This was just completely pointless, and only served to obfuscate
the data path and make testing harder.
2017-08-28 03:56:34 +00:00
whitequark bab5c0b7aa Unify EthernetInterface::{send_response,emit} transmit paths. 2017-08-28 02:11:04 +00:00
whitequark 1d01189278 Use FnOnce, not FnMut, in Socket::dispatch() functions.
There was never any reason to use FnMut and this significantly
simplifies the job of the borrow checker.
2017-08-28 00:59:33 +00:00
whitequark 4878f0f1d6 Fix a TCP retransmit loop after transition from SYN-SENT to ESTABLISHED. 2017-08-25 06:47:12 +00:00
whitequark 3035ef07fb Fix a bug that caused TCP packets with PSH bit to be dropped. 2017-08-25 06:27:00 +00:00
whitequark afdf73ffef TcpRepr::push → TcpControl::Psh.
This is done for simplification. FIN implies PSH, RST doesn't have
any meaning with PSH, and SYN|PSH only makes sense in the context
of TCP Fast Open, in the context of which, any data in the original
SYN already implies PSH.
2017-08-25 06:05:17 +00:00
whitequark 5396687d52 Immediately ACK payload in response to TCP packets that have any.
This will lower the average software RTT by about a factor of two.
2017-08-25 05:50:43 +00:00
whitequark 5b2de544c8 Radically simplify and optimize TCP packet dispatch.
This commit completely reworks packet dispatch in TCP sockets,
and brings significant improvements to processing as well.

In particular:
  * Challenge ACKs now do not reset retransmit timer; instead,
    TcpSocket::process directly returns a TcpRepr without altering
    any internal state at all.
  * Retransmit and close (aka TIME-WAIT) timers are unified
    and restructured into a enum that actually matches semantics
    of the timers.
  * If a packet cannot be emitted, no internal state is changed.
  * The dispatch of RST packets in case of connection abort
    is brought in line with dispatch of all other packets.
  * Packet dispatch now follows a series of steps with clean
    separation of concerns, like packet processing:
      1. If we should retransmit, update state to assume that
         all in-flight packets are lost.
      2. Prepare the packet that would be sent next, considering
         the in-flight packets, if any.
      3. Check if the packet contains anything new, or it's the same
         as the one already in flight. If it is, bail.
      4. Finalize and try to actually transmit the packet.
         If we can't do that, bail.
      5. Update the internal state to reflect that the packet
         we've just sent is in flight.
2017-08-25 03:53:31 +00:00
whitequark a0d359fc53 Make TCP packets not matching socket state return Error::Dropped.
Error::Malformed is only for internally inconsistent packets,
like SYN|FIN.
2017-08-25 03:52:30 +00:00
whitequark ae7e956573 Add a missing \0 in a C string. 2017-08-24 12:18:07 +00:00
whitequark 9d0084171f Rework responses to TCP packets and factor in RST replies to TcpSocket. 2017-08-22 22:32:05 +00:00
whitequark 7c9a072dd2 Fix a typo that broke ARP replies. 2017-08-22 07:44:43 +00:00
whitequark f9c6c0249b Listening TCP sockets should reject, not drop, ACKs. 2017-08-21 07:29:32 +00:00
whitequark 39f328b80f Add TcpSocket::{peek,peek_slice}. 2017-08-21 07:28:38 +00:00
whitequark 925e13b61a Simplify ARP handling code in EthernetInterface. 2017-08-21 07:28:38 +00:00
whitequark 15085bd8ba Fix a file descriptor leak in TapInterfaceDesc::interface_mtu. 2017-08-21 07:28:32 +00:00
whitequark be1038f382 Assert that the transmit frame returned by driver has right length.
We checked for frames too short before, but frames too long are
troublesome too, since e.g. TCP and UDP do not carry an explicit
payload length in their headers.
2017-08-06 15:09:55 +00:00
David Coffill 55ac6737b2 Fix build on i686 by using libc::suseseconds_t instead of i64 2017-08-02 07:12:36 +00:00
whitequark e0d8fcfb72 Emit exceptional events with the DEBUG log level, not TRACE. 2017-08-01 11:21:58 +00:00
whitequark db5ecb353a Only return Err(Rejected) from TcpSocket::process on endpoint mismatch.
Otherwise, a future SocketSet that tries to route packets by using
IP/port numbers instead of brute force would result in different
semantics.
2017-08-01 11:15:12 +00:00
whitequark ffbb885586 Remove IpEndpoint::accepts.
Unclear purpose, one use, we don't need it.
2017-08-01 11:08:48 +00:00
whitequark 8724157b54 Fix warnings. 2017-07-31 07:59:01 +00:00
whitequark 7825bc6070 Implement fmt::Write for TcpSocket. 2017-07-30 06:59:01 +00:00
whitequark a1f865f6d3 Rework and test raw sockets. 2017-07-30 02:02:41 +00:00
whitequark ae903e8841 Add UdpSocket::is_open, similar to TcpSocket::is_open in function.
Fixes #31.
2017-07-30 01:17:58 +00:00
whitequark be0854127a Remove unused imports. 2017-07-30 01:09:14 +00:00
whitequark f44c9a808a Simplify signature of UdpSocket::send_slice.
UdpSocket::send_slice always returns Ok(data.len()) or an error,
so the result isn't meaningful.
2017-07-29 08:36:55 +00:00
whitequark 02f005a2bb Put the debug_id field first in sockets.
This has been annoying me far too long.
2017-07-28 11:55:59 +00:00
whitequark ad12573f62 Rework and test UDP sockets.
Before, errors such as packets not fitting into a buffer would have
resulted in panics, and errors such as unbound sockets were
simply ignored.
2017-07-27 22:30:01 +00:00
whitequark 8d8a4ea583 Get rid of Result<_, ()>.
The use of this type has several drawbacks:
  * It does not allow distinguishing between different error
    conditions. In fact, we wrongly conflated some of them
    before this commit.
  * It does not allow propagation via ? and requires manual use
    of map_err, which is especially tiresome for downstream code.
  * It prevents us from expanding the set of error conditions
    even if right now we have only one.
  * It prevents us from blanket using Result<T> everywhere
    (a nitpick at most).

Instead, use Result<T, Error> everywhere, and differentiate error
conditions where applicable.
2017-07-27 13:55:47 +00:00
whitequark 7838434165 Remove useless redundant tests. 2017-07-27 13:38:31 +00:00
whitequark 8a2432dcd7 Rework error handling in TcpSocket::connect. 2017-07-27 12:27:33 +00:00
whitequark a61c1a5d2e Rearrange errors and clarify their semantics. 2017-07-27 12:10:04 +00:00
whitequark 24bb0eab9d Update a stale docstring. 2017-07-27 11:26:39 +00:00
whitequark a3423b35f4 as_unspecified → to_unspecified 2017-07-27 11:26:07 +00:00
whitequark 83c41fd760 Simplify impls of AsSocket. 2017-07-24 17:00:00 +00:00
whitequark d35fd9940e Fix ICMP error returned by EthernetInterface for unknown IP protocols. 2017-07-24 07:07:43 +00:00
whitequark 936bd44f8f Clean up socket error handling in EthernetInterface. 2017-07-24 07:01:35 +00:00
whitequark c8d714cd87 Reorganize EthernetInterface impl. NFC. 2017-07-24 06:56:06 +00:00
whitequark 776ca6eada Rename RingBuffer::{dequeue_mut→dequeue}, remove RingBuffer::dequeue.
There's nothing dequeue can do that dequeue_mut cannot.
2017-07-24 05:30:22 +00:00
whitequark 38afc64f61 Accept TCP FIN packets in SYN-RECEIVED state. 2017-07-23 23:51:56 +00:00
whitequark 1c41f2d7fa Fix determination of local address from incoming packets.
We've advertised this capability before in examples, but it did not
actually work.
2017-07-23 23:07:55 +00:00
whitequark 7ba49607bf Update fault injector so that rate limiting works without std. 2017-07-23 15:10:57 +00:00
whitequark 250a84e513 Implement a Device that emits a stream in libpcap format. 2017-07-23 14:56:24 +00:00
whitequark a9e6b49aa6 Rename into_lower → into_inner. 2017-07-23 10:20:05 +00:00
whitequark aeba4f9bc6 Clean up some type variable names and trait bounds. NFC. 2017-07-23 10:15:56 +00:00
whitequark b97cacd521 Inject the current timestamp into Device::{transmit,receive}.
Various parts of smoltcp require an arrow of time; a monotonically
increasing timestamp. Most obviously this is TCP sockets, but
the tracer and the pcap writer devices also benefit from having
timestamps. There are a few ways this could be implemented:
  1. using a static Cell, global for the entire smoltcp crate;
  2. using a static method on Device;
  3. using an instance method on Device;
  4. passing the current timestamp into *Interface::poll.

The first two options are undesirable because they create a notion
of global clock, and interfere e.g. with mocking.
The third option is undesirable because not all devices are
inherently tied to a particular clock, e.g. a loopback device isn't.

Therefore, the timestamp is injected into both sockets and devices
through the *Interface::poll method.
2017-07-23 09:48:14 +00:00
whitequark fe6fb087e5 Move macros into their own module.
This allows us to use `enum_with_unknown` in `phy`.
2017-07-23 07:54:36 +00:00
whitequark eae7907f60 Add EthernetTracer, a specialization of Tracer for EthernetFrame.
This makes the loopback example much nicer, #[cfg]-wise.
2017-07-23 06:28:00 +00:00
whitequark bdfc47d633 Log correct delay when performing TCP retransmit.
Before, the delay was erroneously multiplied by 2 and also did not
take processing delay into account.
2017-07-23 05:09:38 +00:00
whitequark 051169a49d Determine MTU in TapInterface instead of hardcoding 1536. 2017-07-23 04:40:35 +00:00
whitequark 94796a566b Document the loopback. 2017-07-14 03:30:00 +00:00
whitequark 312ff93c86 Remove default impl for Device::limits().
We should not assume any default MTU.
2017-07-14 03:18:11 +00:00
whitequark f3e54966fd LoopbackInterface → Loopback. 2017-07-14 01:17:06 +00:00
whitequark 63ab7d4e7a Implement loopback interfaces.
This also adds a default implementation of Device::limits.
2017-07-14 01:14:40 +00:00
whitequark 5556f09351 Annotate all simple getters with #[inline]. 2017-07-04 18:46:36 +00:00
whitequark 3f9805b2c1 Remove *Socket::{process,dispatch} from public interface.
These no longer have to be public, since our required Rust version
has pub(crate).
2017-06-30 20:55:46 +00:00
whitequark 938fb99070 In {Tcp,Udp}Socket::process, make protocol check an assertion.
We filter sockets by type upstream of the process() calls.
2017-06-30 19:17:14 +00:00
whitequark 2c1e234b91 Remove Socket::{process,dispatch} from public interface.
These no longer have to be public, since our required Rust version
has pub(crate). In addition Socket::process is not used at all.
2017-06-29 15:56:03 +00:00
whitequark 6ad8fea31f Fix a typo in 5c3fc493. 2017-06-27 21:51:56 +00:00
whitequark 04bd8a0051 Discard packets with non-unicast source addresses at IP level.
This is required by RFC 1122 and helps avoid "broadcast storms".
2017-06-26 17:01:23 +00:00
whitequark 6cd8cb4422 Transmit actual UDP checksum of all-zeroes as all-ones instead. 2017-06-26 16:57:21 +00:00
whitequark cbf6e5cdbc Try to trigger fast retransmit when we detect a missing TCP segment.
The changes in this commit affect the following scenario:
  * Remote end sends octets 1..2, they are delivered and buffered
    on local end;
  * Remote end sends octets 3..4, they are lost;
  * Remote end sends octets 5..6, they are delivered but cannot
    be buffered on local end because we don't perform reassembly.

Before this commit, we would silently drop the segment with octets
5..6, relying on retransmission timer on the remote end. This works,
but can result in severe decrease in throughput. After this commit,
we send a duplicate ACK, which may trigger fast retransmit, if
implemented by the congestion control algorithm on the remote end.
2017-06-26 08:44:07 +00:00
whitequark 2704a10dd8 Add missing #[derive]s on wire::IpVersion. 2017-06-26 06:06:18 +00:00
Egor Karavaev 4f2804e104 Don't reply to a TCP RST packet with another TCP RST packet. 2017-06-26 05:48:30 +00:00
Egor Karavaev 1e8cd1a65f Refactor EthernetInterface::poll.
Also, after this commit, we stop iterating over TCP/UDP sockets after
finding one that accepts the packet.
2017-06-26 05:48:27 +00:00
whitequark 0f0c545755 Make sure representation emission covers every octet of the buffer.
Also fix a bug where TcpRepr::emit would not clear the urgent
pointer.
2017-06-26 03:44:36 +00:00
whitequark 050dd788c1 Set TCP PSH flag when sending the last buffered data. 2017-06-25 23:12:30 +00:00
whitequark b86d22701d Expose PSH flag in TcpRepr. 2017-06-25 08:20:25 +00:00
whitequark db75f70fa3 Fix a few typos in TCP socket code (NFC). 2017-06-25 08:05:37 +00:00
whitequark 0a9c5d52dd Remove an unnecessary length check. 2017-06-24 16:34:55 +00:00
whitequark 74823b0dff try! → ? 2017-06-24 16:34:32 +00:00
whitequark 023d8deea5 Disable checksum validation on wire level when fuzzing. 2017-06-24 15:26:15 +00:00
whitequark fce23593fc Fix insufficient length validation in TCP packets.
Found via cargo-fuzz.
2017-06-24 12:29:39 +00:00
whitequark c73af2b247 Fix insufficient length validation in UDP packets.
Found via cargo-fuzz.
2017-06-24 12:15:18 +00:00
whitequark 6790eac6d9 Fix a crash parsing a malformed IPv4 packet.
Found via cargo-fuzz.
2017-06-24 12:02:34 +00:00
whitequark 9f8db1d8f9 Factor out wire::tcp::field::OPTIONS. 2017-06-24 12:02:34 +00:00
whitequark 315b51d7da Fix a crash parsing a truncated TCP packet with options.
Found via cargo-fuzz.
2017-06-24 11:48:17 +00:00
whitequark 6842d7013d Fix a crash parsing malformed TCP options.
Found via cargo-fuzz.
2017-06-24 11:48:17 +00:00
whitequark c09e96a657 Fix a crash printing a malformed TCP packet.
Found via cargo-fuzz.
2017-06-24 11:48:13 +00:00
whitequark 8b27330c8b Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.

This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
  * `fn check_len(&self) -> Result<(), Error>`, purely a validator;
  * `fn new(T) -> Self`, purely a wrapper;
  * `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.

This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).

Fixes #17.
2017-06-24 11:42:32 +00:00
whitequark cc5fb0e5ef Clean up a few doctests. 2017-06-24 09:02:12 +00:00
whitequark be29789192 Fix an unimplemented!() invocation that should be unreachable!(). 2017-06-22 00:38:45 +00:00
whitequark 83cf86f1d0 Unbreak parsing of ICMP unreachable messages.
Fixes #16.
2017-06-21 04:08:33 +00:00
whitequark adc51fab7f Actually export socket::SocketSetItem publicly.
It was unintentionally left unnameable. Fixes #14.
2017-06-21 03:57:13 +00:00
Egor Karavaev ca56baca65 Add `RawSocket`. 2017-06-21 03:29:31 +00:00
Egor Karavaev e927b09ba8 `IpRepr::lower` replaces unspecified src_addr in Ipv4Repr as well. 2017-06-21 03:01:15 +00:00
Egor Karavaev c1c4ed68c5 Factor out the `RingBuffer` container. 2017-06-21 02:50:10 +00:00
Egor Karavaev 59fc0c0358 Factor out the "raw_socket" and "tap_interface" features
This makes it possible to build smoltcp with the "std" feature on platforms
without libc, such as redox.
2017-06-15 10:12:11 +00:00
whitequark f29b610801 Remove accidentally committed change. 2017-05-29 17:15:35 +00:00
whitequark 5bac3e5a02 Fix no-std build. 2017-05-29 11:04:49 +00:00
whitequark 91ef5c60c3 Add packet shaping to the fault injector. 2017-05-29 10:53:30 +00:00
whitequark 73bb4b8593 Implement TCP TIME-WAIT timeouts. 2017-04-21 16:01:49 +00:00
whitequark 8087bf3755 Fix a typo in documentation. 2017-04-21 15:59:55 +00:00
whitequark 555825e49e Clamp TCP receive window to MSS multiplied by maximum burst size.
This is a conservative bound; if we don't have enough buffers
to receive more than four segments, clearly we shouldn't advertise
our ability to.

It however will only work reliably with exactly one TCP connection
continuously receiving; for two, another window adjustment mechanism
will be needed for reliable reception.
2017-03-07 11:21:49 +00:00
whitequark 1d46ccf432 fn Device::mtu() -> usize → Device::limits() -> DeviceLimits 2017-03-07 11:10:26 +00:00
whitequark c73298f01e Improve handling of TCP ACK packets in FIN-* states.
Previously, sockets could get stuck in the CLOSING state, after
the sequence described in the new test_mutual_close_with_data_2.
The root cause was that some state machine transitions got
folded into ACK handling.

Now, all transitions are handled in the same match statement,
and ACK handling is broken up around it.
2017-03-07 10:17:30 +00:00
whitequark 393ebbe682 Don't put non-unicast (IP or Ethernet) addresses into ARP cache.
Thanks @little-dude for pointing this out--it's probably a DoS bug.
2017-03-07 06:32:18 +00:00
whitequark b305797cb4 Trace eviction and fill in SliceArpCache. 2017-03-07 06:25:47 +00:00
Corentin Henry 0f2b05ede7 arp: increment lru when inserting a new entry 2017-03-07 06:04:40 +00:00