summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-04-18 11:40:34 -0700
committerShentubot <shentubot@google.com>2019-04-18 11:42:23 -0700
commit4524790ff668674149ad6ae6eec805369be0c6e3 (patch)
treefe2145a8e9c70d645614ad2d47ea8260af17cbbf /pkg/tcpip
parentb52cbd60280342f25411561702e97fe650fdaa9c (diff)
netstack: use a proper network protocol to set gso.L3HdrLen
It is possible to create a listening socket which will accept IPv4 and IPv6 connections. In this case, we set IPv6ProtocolNumber for all accepted endpoints, even if they handle IPv4 connections. This means that we can't use endpoint.netProto to set gso.L3HdrLen. PiperOrigin-RevId: 244227948 Change-Id: I5e1863596cb9f3d216febacdb7dc75651882eef1
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/link/channel/channel.go18
-rw-r--r--pkg/tcpip/link/fdbased/endpoint_test.go1
-rw-r--r--pkg/tcpip/transport/tcp/dual_stack_test.go12
-rw-r--r--pkg/tcpip/transport/tcp/endpoint.go2
-rw-r--r--pkg/tcpip/transport/tcp/testing/context/context.go9
5 files changed, 38 insertions, 4 deletions
diff --git a/pkg/tcpip/link/channel/channel.go b/pkg/tcpip/link/channel/channel.go
index 8c0d11288..f7501a1bc 100644
--- a/pkg/tcpip/link/channel/channel.go
+++ b/pkg/tcpip/link/channel/channel.go
@@ -28,6 +28,7 @@ type PacketInfo struct {
Header buffer.View
Payload buffer.View
Proto tcpip.NetworkProtocolNumber
+ GSO *stack.GSO
}
// Endpoint is link layer endpoint that stores outbound packets in a channel
@@ -36,6 +37,7 @@ type Endpoint struct {
dispatcher stack.NetworkDispatcher
mtu uint32
linkAddr tcpip.LinkAddress
+ GSO bool
// C is where outbound packets are queued.
C chan PacketInfo
@@ -93,8 +95,17 @@ func (e *Endpoint) MTU() uint32 {
}
// Capabilities implements stack.LinkEndpoint.Capabilities.
-func (*Endpoint) Capabilities() stack.LinkEndpointCapabilities {
- return 0
+func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
+ caps := stack.LinkEndpointCapabilities(0)
+ if e.GSO {
+ caps |= stack.CapabilityGSO
+ }
+ return caps
+}
+
+// GSOMaxSize returns the maximum GSO packet size.
+func (*Endpoint) GSOMaxSize() uint32 {
+ return 1 << 15
}
// MaxHeaderLength returns the maximum size of the link layer header. Given it
@@ -109,11 +120,12 @@ func (e *Endpoint) LinkAddress() tcpip.LinkAddress {
}
// WritePacket stores outbound packets into the channel.
-func (e *Endpoint) WritePacket(_ *stack.Route, _ *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error {
+func (e *Endpoint) WritePacket(_ *stack.Route, gso *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error {
p := PacketInfo{
Header: hdr.View(),
Proto: protocol,
Payload: payload.ToView(),
+ GSO: gso,
}
select {
diff --git a/pkg/tcpip/link/fdbased/endpoint_test.go b/pkg/tcpip/link/fdbased/endpoint_test.go
index 5a06c6387..c8b037d57 100644
--- a/pkg/tcpip/link/fdbased/endpoint_test.go
+++ b/pkg/tcpip/link/fdbased/endpoint_test.go
@@ -166,6 +166,7 @@ func testWritePacket(t *testing.T, plen int, eth bool, gsoMaxSize uint32) {
CsumOffset: csumOffset,
MSS: gsoMSS,
MaxSize: gsoMaxSize,
+ L3HdrLen: header.IPv4MaximumHeaderSize,
}
}
if err := c.ep.WritePacket(r, gso, hdr, payload.ToVectorisedView(), proto); err != nil {
diff --git a/pkg/tcpip/transport/tcp/dual_stack_test.go b/pkg/tcpip/transport/tcp/dual_stack_test.go
index 52f20bef1..2886cc707 100644
--- a/pkg/tcpip/transport/tcp/dual_stack_test.go
+++ b/pkg/tcpip/transport/tcp/dual_stack_test.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.googlesource.com/gvisor/pkg/tcpip"
+ "gvisor.googlesource.com/gvisor/pkg/tcpip/buffer"
"gvisor.googlesource.com/gvisor/pkg/tcpip/checker"
"gvisor.googlesource.com/gvisor/pkg/tcpip/header"
"gvisor.googlesource.com/gvisor/pkg/tcpip/network/ipv4"
@@ -330,6 +331,9 @@ func TestV6RefuseOnBoundToV4Mapped(t *testing.T) {
}
func testV4Accept(t *testing.T, c *context.Context) {
+ c.SetGSOEnabled(true)
+ defer c.SetGSOEnabled(false)
+
// Start listening.
if err := c.EP.Listen(10); err != nil {
t.Fatalf("Listen failed: %v", err)
@@ -406,6 +410,14 @@ func testV4Accept(t *testing.T, c *context.Context) {
if addr.Addr != context.TestAddr {
t.Fatalf("Unexpected remote address: got %v, want %v", addr.Addr, context.TestAddr)
}
+
+ data := "Don't panic"
+ nep.Write(tcpip.SlicePayload(buffer.NewViewFromBytes([]byte(data))), tcpip.WriteOptions{})
+ b = c.GetPacket()
+ tcp = header.TCP(header.IPv4(b).Payload())
+ if string(tcp.Payload()) != data {
+ t.Fatalf("Unexpected data: got %v, want %v", string(tcp.Payload()), data)
+ }
}
func TestV4AcceptOnV6(t *testing.T) {
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go
index b5d05af7d..c0b785431 100644
--- a/pkg/tcpip/transport/tcp/endpoint.go
+++ b/pkg/tcpip/transport/tcp/endpoint.go
@@ -1717,7 +1717,7 @@ func (e *endpoint) initGSO() {
}
gso := &stack.GSO{}
- switch e.netProto {
+ switch e.route.NetProto {
case header.IPv4ProtocolNumber:
gso.Type = stack.GSOTCPv4
gso.L3HdrLen = header.IPv4MinimumSize
diff --git a/pkg/tcpip/transport/tcp/testing/context/context.go b/pkg/tcpip/transport/tcp/testing/context/context.go
index 8ac411b1d..6e2fed880 100644
--- a/pkg/tcpip/transport/tcp/testing/context/context.go
+++ b/pkg/tcpip/transport/tcp/testing/context/context.go
@@ -234,6 +234,10 @@ func (c *Context) GetPacket() []byte {
copy(b, p.Header)
copy(b[len(p.Header):], p.Payload)
+ if p.GSO != nil && p.GSO.L3HdrLen != header.IPv4MinimumSize {
+ c.t.Errorf("L3HdrLen %v (expected %v)", p.GSO.L3HdrLen, header.IPv4MinimumSize)
+ }
+
checker.IPv4(c.t, b, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr))
return b
@@ -956,3 +960,8 @@ func (c *Context) SACKEnabled() bool {
}
return bool(v)
}
+
+// SetGSOEnabled enables or disables generic segmentation offload.
+func (c *Context) SetGSOEnabled(enable bool) {
+ c.linkEP.GSO = enable
+}