Age | Commit message (Collapse) | Author |
|
IPv4 options extend the size of the IP header and have a basic known
format. The framework can process that format without needing to know
about every possible option. We can add more code to handle additional
option types as we need them. Bad options or mangled option entries
can result in ICMP Parameter Problem packets. The first types we
support are the Timestamp option and the Record Route option, included
in this change.
The options are processed at several points in the packet flow within
the Network stack, with slightly different requirements. The framework
includes a mechanism to control this at each point. Support has been
added for such points which are only present in upcoming CLs such as
during packet forwarding and fragmentation.
With this change, 'ping -R' and 'ping -T' work against gVisor and Fuchsia.
$ ping -R 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(124) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.990 ms
NOP
RR: 192.168.1.1
192.168.1.2
192.168.1.1
$ ping -T tsprespec 192.168.1.2 192.168.1.1 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(124) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.20 ms
TS: 192.168.1.2 71486821 absolute
192.168.1.1 746
Unit tests included for generic options, Timestamp options
and Record Route options.
PiperOrigin-RevId: 339379076
|
|
This change wakes up any waiters when we receive an ICMP port unreachable
control packet on an UDP socket as well as sets waiter.EventErr in
the result returned by Readiness() when e.lastError is not nil.
The latter is required where an epoll()/poll() is done after the error
is already handled since we will never notify again in such cases.
PiperOrigin-RevId: 339370469
|
|
Drain the notification channel after first accept as in case the first accept
never blocked then the notification for the first accept will still be in the
channel causing the second accept to fail as it will try to wait on the channel
and return immediately due to the older notification even though there is no
connection yet in the accept queue.
PiperOrigin-RevId: 338710062
|
|
The SO_ACCEPTCONN option is used only on getsockopt(). When this option is
specified, getsockopt() indicates whether socket listening is enabled for
the socket. A value of zero indicates that socket listening is disabled;
non-zero that it is enabled.
PiperOrigin-RevId: 338703206
|
|
Earlier the count was dropped only after calling e.deliverAccepted. This lead to
an issue where there were no connections in SYN-RCVD state for the listening
endpoint but e.synRcvdCount would not be zero because it was being reduced only
when handleSynSegment returned after deliverAccepted returned.
This issue is seen when the Nth SYN for a listen backlog of size N which would
cause the listen backlog to be full gets dropped occasionally. This happens when
the new SYN comes at when the previous completed endpoint has been delivered to
the accept queue but the synRcvdCount hasn't yet been decremented because the
goroutine running handleSynSegment has not yet completed.
PiperOrigin-RevId: 338690646
|
|
Previously a link endpoint was passed to
stack.LinkAddressResolver.LinkAddressRequest. With this change,
implementations that want a route for the link address request may
find one through the stack. Other implementations that want to send
a packet without a route may continue to do so using the network
interface directly.
Test: - arp_test.TestLinkAddressRequest
- ipv6.TestLinkAddressRequest
PiperOrigin-RevId: 338577474
|
|
PiperOrigin-RevId: 338168977
|
|
//pkg/tcpip/stack:stack_x_test_nogo
//pkg/tcpip/transport/raw:raw_nogo
PiperOrigin-RevId: 338153265
|
|
|
|
The fix in commit 028e045da93b7c1c26417e80e4b4e388b86a713d was incorrect as
it can cause the right edge of the window to shrink when we announce
a zero window due to receive buffer being full as its done before the check
for seeing if the window is being shrunk because of the selected window.
Further the window was calculated purely on available space but in cases where
we are getting full sized segments it makes more sense to use the actual bytes
being held. This CL changes to use the lower of the total available space vs
the available space in the maximal window we could advertise minus the actual
payload bytes being held.
This change also cleans up the code so that the window selection logic is
not duplicated between getSendParams() and windowCrossedACKThresholdLocked.
PiperOrigin-RevId: 336404827
|
|
RACK detects packet reordering by checking if the sender received ACK for
the packet which has the sequence number less than the already acknowledged
packets.
PiperOrigin-RevId: 336397526
|
|
PiperOrigin-RevId: 336339194
|
|
PiperOrigin-RevId: 336304024
|
|
When a response needs to be sent to an incoming packet, the stack should
consult its neighbour table to determine the remote address's link
address.
When an entry does not exist in the stack's neighbor table, the stack
should queue the packet while link resolution completes. See comments.
PiperOrigin-RevId: 336185457
|
|
The IPv4 RFCs are specific (though obtuse) that an echo response
packet needs to contain all the options from the echo request,
much as if it been routed back to the sender, though apparently
with a new TTL. They suggest copying the incoming packet header
to achieve this so that is what this patch does.
PiperOrigin-RevId: 335559176
|
|
We can get the network endpoint directly from the NIC.
This is a preparatory CL for when a Route needs to hold a dedicated NIC
as its output interface. This is because when forwarding is enabled,
packets may be sent from a NIC different from the NIC a route's local
address is associated with.
PiperOrigin-RevId: 335484500
|
|
We are currently tracking the minimum RTT for RACK as smoothed RTT. As per RFC
minimum RTT can be a global minimum of all RTTs or filtered value of recent
RTT measurements. In this cl minimum RTT is updated to global minimum of all
RTTs for the connection.
PiperOrigin-RevId: 335061518
|
|
Adds support for the IPv6-compatible redirect target. Redirection is a limited
form of DNAT, where the destination is always the localhost.
Updates #3549.
PiperOrigin-RevId: 334698344
|
|
As per relevant IP RFCS (see code comments), broadcast (for IPv4) and
multicast addresses are not allowed. Currently checks for these are
done at the transport layer, but since it is explicitly forbidden at
the IP layers, check for them there.
This change also removes the UDP.InvalidSourceAddress stat since there
is no longer a need for it.
Test: ip_test.TestSourceAddressValidation
PiperOrigin-RevId: 334490971
|
|
Currently expired IP fragments are discarded only if another fragment for the
same IP datagram is received after timeout or the total size of the fragment
queue exceeded a predefined value.
Test: fragmentation.TestReassemblingTimeout
Fixes #3960
PiperOrigin-RevId: 334423710
|
|
* Remove Capabilities and NICID methods from NetworkEndpoint.
* Remove linkEP and stack parameters from NetworkProtocol.NewEndpoint.
The LinkEndpoint can be fetched from the NetworkInterface. The stack
is passed to the NetworkProtocol when it is created so the
NetworkEndpoint can get it from its protocol.
* Remove stack parameter from TransportProtocol.NewEndpoint.
Like the NetworkProtocol/Endpoint, the stack is passed to the
TransportProtocol when it is created.
PiperOrigin-RevId: 334332721
|
|
* Add network address to network endpoints.
Hold network-specific state in the NetworkEndpoint instead of the stack.
This results in the stack no longer needing to "know" about the network
endpoints and special case certain work for various endpoints
(e.g. IPv6 DAD).
* Provide NetworkEndpoints with an NetworkInterface interface.
Instead of just passing the NIC ID of a NIC, pass an interface so the
network endpoint may query other information about the NIC such as
whether or not it is a loopback device.
* Move NDP code and state to the IPv6 package.
NDP is IPv6 specific so there is no need for it to live in the stack.
* Control forwarding through NetworkProtocols instead of Stack
Forwarding should be controlled on a per-network protocol basis so
forwarding configurations are now controlled through network protocols.
* Remove stack.referencedNetworkEndpoint.
Now that addresses are exposed via AddressEndpoint and only one
NetworkEndpoint is created per interface, there is no need for a
referenced NetworkEndpoint.
* Assume network teardown methods are infallible.
Fixes #3871, #3916
PiperOrigin-RevId: 334319433
|
|
In TestReceiveBufferAutoTuning we now send a keep-alive packet to measure the
current window rather than a 1 byte segment as the returned window value in the
latter case is reduced due to the 1 byte segment now being held in the receive
buffer and can cause the test to flake if the segment overheads were to change.
In getSendParams in rcv.go we were advertising a non-zero window even if
available window space was zero after we received the previous segment. In such
a case newWnd and curWnd will be the same and we end up advertising a tiny but
non-zero window and this can cause the next segment to be dropped.
PiperOrigin-RevId: 334314070
|
|
When the socket is set with SO_LINGER and close()'d in the initial state, it
should not linger and return immediately.
PiperOrigin-RevId: 334263149
|
|
Network or transport protocols may want to reach the stack. Support this
by letting the stack create the protocol instances so it can pass a
reference to itself at protocol creation time.
Note, protocols do not yet use the stack in this CL but later CLs will
make use of the stack from protocols.
PiperOrigin-RevId: 334260210
|
|
PiperOrigin-RevId: 333591566
|
|
segment_queue today has its own standalone limit of MaxUnprocessedSegments but
this can be a problem in UnlockUser() we do not release the lock till there are
segments to be processed. What can happen is as handleSegments dequeues packets
more keep getting queued and we will never release the lock. This can keep
happening even if the receive buffer is full because nothing can read() till we
release the lock.
Further having a separate limit for pending segments makes it harder to track
memory usage etc. Unifying the limits makes it easier to reason about memory in
use and makes the overall buffer behaviour more consistent.
PiperOrigin-RevId: 333508122
|
|
Store transport protocol number on packet buffers for use in ICMP error
generation.
Updates #2211.
PiperOrigin-RevId: 333252762
|
|
TCP needs to enqueue any send requests arriving when the connection is in
SYN_SENT state. The data should be sent out soon after completion of the
connection handshake.
Fixes #3995
PiperOrigin-RevId: 332482041
|
|
Extract parsing utilities so they can be used by the sniffer.
Fixes #3930
PiperOrigin-RevId: 332401880
|
|
SO_LINGER is a socket level option and should be stored on all endpoints even
though it is used to linger only for TCP endpoints.
PiperOrigin-RevId: 332369252
|
|
PiperOrigin-RevId: 332097286
|
|
When a broadcast packet is received by the stack, the packet should be
delivered to each endpoint that may be interested in the packet. This
includes all any address and specified broadcast address listeners.
Test: integration_test.TestReuseAddrAndBroadcast
PiperOrigin-RevId: 332060652
|
|
The routing table (in its current) form should not be used to make
decisions about whether a remote address is a broadcast address or
not (for IPv4).
Note, a destination subnet does not always map to a network.
E.g. RouterA may have a route to 192.168.0.0/22 through RouterB,
but RouterB may be configured with 4x /24 subnets on 4 different
interfaces.
See https://github.com/google/gvisor/issues/3938.
PiperOrigin-RevId: 331819868
|
|
This is simpler and more performant.
PiperOrigin-RevId: 331639978
|
|
gVisor stack ignores RSTs when in TIME_WAIT which is not the default
Linux behavior. Add a packetimpact test to test the same.
Also update code comments to reflect the rationale for the current
gVisor behavior.
PiperOrigin-RevId: 331629879
|
|
e.ID can't be read without holding e.mu. GetSockOpt was reading e.ID
when looking up OriginalDst without holding e.mu.
PiperOrigin-RevId: 330562293
|
|
The existing implementation for TransportProtocol.{Set}Option take
arguments of an empty interface type which all types (implicitly)
implement; any type may be passed to the functions.
This change introduces marker interfaces for transport protocol options
that may be set or queried which transport protocol option types
implement to ensure that invalid types are caught at compile time.
Different interfaces are used to allow the compiler to enforce read-only
or set-only socket options.
RELNOTES: n/a
PiperOrigin-RevId: 330559811
|
|
Accept on gVisor will return an error if a socket in the accept queue was closed
before Accept() was called. Linux will return the new fd even if the returned
socket is already closed by the peer say due to a RST being sent by the peer.
This seems to be intentional in linux more details on the github issue.
Fixes #3780
PiperOrigin-RevId: 329828404
|
|
On receiving an ACK with unacceptable ACK number, in a closing state,
TCP, needs to reply back with an ACK with correct seq and ack numbers and
remain in same state. This change is as per RFC793 page 37, but with a
difference that it does not apply to ESTABLISHED state, just as in Linux.
Also add more tests to check for OTW sequence number and unacceptable
ack numbers in these states.
Fixes #3785
PiperOrigin-RevId: 329616283
|
|
PiperOrigin-RevId: 329526153
|
|
The existing implementation for {G,S}etSockOpt take arguments of an
empty interface type which all types (implicitly) implement; any
type may be passed to the functions.
This change introduces marker interfaces for socket options that may be
set or queried which socket option types implement to ensure that invalid
types are caught at compile time. Different interfaces are used to allow
the compiler to enforce read-only or set-only socket options.
Fixes #3714.
RELNOTES: n/a
PiperOrigin-RevId: 328832161
|
|
In an upcoming CL, socket option types are made to implement a marker
interface with pointer receivers. Since this results in calling methods
of an interface with a pointer, we incur an allocation when attempting
to get an Endpoint's last error with the current implementation.
When calling the method of an interface, the compiler is unable to
determine what the interface implementation does with the pointer
(since calling a method on an interface uses virtual dispatch at runtime
so the compiler does not know what the interface method will do) so it
allocates on the heap to be safe incase an implementation continues to
hold the pointer after the functioon returns (the reference escapes the
scope of the object).
In the example below, the compiler does not know what b.foo does with
the reference to a it allocates a on the heap as the reference to a may
escape the scope of a.
```
var a int
var b someInterface
b.foo(&a)
```
This change removes the opportunity for that allocation.
RELNOTES: n/a
PiperOrigin-RevId: 328796559
|
|
Test:
- TestV4UnknownDestination
- TestV6UnknownDestination
PiperOrigin-RevId: 328424137
|
|
This change adds an option to replace the current implementation of ARP through
linkAddrCache, with an implementation of NUD through neighborCache. Switching
to using NUD for both ARP and NDP is beneficial for the reasons described by
RFC 4861 Section 3.1:
"[Using NUD] significantly improves the robustness of packet delivery in the
presence of failing routers, partially failing or partitioned links, or nodes
that change their link-layer addresses. For instance, mobile nodes can move
off-link without losing any connectivity due to stale ARP caches."
"Unlike ARP, Neighbor Unreachability Detection detects half-link failures and
avoids sending traffic to neighbors with which two-way connectivity is
absent."
Along with these changes exposes the API for querying and operating the
neighbor cache. Operations include:
- Create a static entry
- List all entries
- Delete all entries
- Remove an entry by address
This also exposes the API to change the NUD protocol constants on a per-NIC
basis to allow Neighbor Discovery to operate over links with widely varying
performance characteristics. See [RFC 4861 Section 10][1] for the list of
constants.
Finally, an API for subscribing to NUD state changes is exposed through
NUDDispatcher. See [RFC 4861 Appendix C][3] for the list of edges.
Tests:
pkg/tcpip/network/arp:arp_test
+ TestDirectRequest
pkg/tcpip/network/ipv6:ipv6_test
+ TestLinkResolution
+ TestNDPValidation
+ TestNeighorAdvertisementWithTargetLinkLayerOption
+ TestNeighorSolicitationResponse
+ TestNeighorSolicitationWithSourceLinkLayerOption
+ TestRouterAdvertValidation
pkg/tcpip/stack:stack_test
+ TestCacheWaker
+ TestForwardingWithFakeResolver
+ TestForwardingWithFakeResolverManyPackets
+ TestForwardingWithFakeResolverManyResolutions
+ TestForwardingWithFakeResolverPartialTimeout
+ TestForwardingWithFakeResolverTwoPackets
+ TestIPv6SourceAddressSelectionScopeAndSameAddress
[1]: https://tools.ietf.org/html/rfc4861#section-10
[2]: https://tools.ietf.org/html/rfc4861#appendix-C
Fixes #1889
Fixes #1894
Fixes #1895
Fixes #1947
Fixes #1948
Fixes #1949
Fixes #1950
PiperOrigin-RevId: 328365034
|
|
When SO_LINGER option is enabled, the close will not return until all the
queued messages are sent and acknowledged for the socket or linger timeout is
reached. If the option is not set, close will return immediately. This option
is mainly supported for connection oriented protocols such as TCP.
PiperOrigin-RevId: 328350576
|
|
We still deviate a bit from linux in how long we will actually wait in
FIN-WAIT-2. Linux seems to cap it with TIME_WAIT_LEN and it's not completely
obvious as to why it's done that way. For now I think we can ignore that and
fix it if it really is an issue.
PiperOrigin-RevId: 328324922
|
|
PiperOrigin-RevId: 328259353
|
|
PiperOrigin-RevId: 327686558
|
|
RACK requires the segments to be in the order of their transmission
or retransmission times. This cl creates a new list and moves the
retransmitted segments to the end of the list.
PiperOrigin-RevId: 327325153
|