From d9cb55b00c896a198d6d9098a0ab3bdda74f874f Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Tue, 31 May 2022 18:26:31 -0700 Subject: [PATCH] Replace VectorisedView in transport endpoints. PiperOrigin-RevId: 452186398 --- pkg/tcpip/BUILD | 3 +- pkg/tcpip/header/BUILD | 1 + pkg/tcpip/header/checksum.go | 17 ++++++- pkg/tcpip/network/ipv6/icmp_test.go | 1 + pkg/tcpip/stack/packet_buffer.go | 5 ++ pkg/tcpip/transport/BUILD | 1 - pkg/tcpip/transport/datagram_test.go | 13 +++-- pkg/tcpip/transport/icmp/BUILD | 2 +- pkg/tcpip/transport/icmp/endpoint.go | 34 ++++++++------ pkg/tcpip/transport/icmp/endpoint_state.go | 17 ------- pkg/tcpip/transport/icmp/icmp_test.go | 41 ++++++++-------- pkg/tcpip/transport/icmp/protocol.go | 4 +- pkg/tcpip/transport/internal/network/BUILD | 4 +- .../transport/internal/network/endpoint.go | 6 +-- .../internal/network/endpoint_test.go | 12 ++--- pkg/tcpip/transport/packet/endpoint.go | 28 +++++------ pkg/tcpip/transport/packet/endpoint_state.go | 11 ----- pkg/tcpip/transport/raw/BUILD | 1 + pkg/tcpip/transport/raw/endpoint.go | 47 ++++++++++--------- pkg/tcpip/transport/raw/endpoint_state.go | 17 ------- pkg/tcpip/transport/tcp/BUILD | 2 +- pkg/tcpip/transport/tcp/segment.go | 3 +- pkg/tcpip/transport/tcp/segment_test.go | 5 +- pkg/tcpip/transport/tcp/test/e2e/BUILD | 1 + pkg/tcpip/transport/tcp/test/e2e/tcp_test.go | 17 +++---- pkg/tcpip/transport/tcp/testing/context/BUILD | 2 +- .../transport/tcp/testing/context/context.go | 38 +++++++-------- pkg/tcpip/transport/testing/context/BUILD | 2 +- .../transport/testing/context/context.go | 6 +-- pkg/tcpip/transport/testing/context/flow.go | 11 ++--- pkg/tcpip/transport/udp/BUILD | 1 - pkg/tcpip/transport/udp/endpoint.go | 6 +-- pkg/tcpip/transport/udp/udp_test.go | 19 ++++---- 33 files changed, 178 insertions(+), 200 deletions(-) diff --git a/pkg/tcpip/BUILD b/pkg/tcpip/BUILD index 29d31c5d7..0444000d2 100644 --- a/pkg/tcpip/BUILD +++ b/pkg/tcpip/BUILD @@ -48,8 +48,8 @@ deps_test( allowed = [ # gVisor deps. "//pkg/atomicbitops", - "//pkg/buffer", "//pkg/context", + "//pkg/buffer", "//pkg/cpuid", "//pkg/gohacks", "//pkg/goid", @@ -77,7 +77,6 @@ deps_test( targets = [ "//pkg/tcpip", "//pkg/tcpip/adapters/gonet", - "//pkg/tcpip/buffer", "//pkg/tcpip/link/channel", "//pkg/tcpip/header", "//pkg/tcpip/link/fdbased", diff --git a/pkg/tcpip/header/BUILD b/pkg/tcpip/header/BUILD index 1b2985459..f8adecac3 100644 --- a/pkg/tcpip/header/BUILD +++ b/pkg/tcpip/header/BUILD @@ -30,6 +30,7 @@ go_library( ], visibility = ["//visibility:public"], deps = [ + "//pkg/buffer", "//pkg/tcpip", "//pkg/tcpip/buffer", "//pkg/tcpip/seqnum", diff --git a/pkg/tcpip/header/checksum.go b/pkg/tcpip/header/checksum.go index 38e39242d..8ccb29944 100644 --- a/pkg/tcpip/header/checksum.go +++ b/pkg/tcpip/header/checksum.go @@ -20,8 +20,9 @@ import ( "encoding/binary" "fmt" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" + tcpipbuffer "gvisor.dev/gvisor/pkg/tcpip/buffer" ) // ChecksumSize is the size of a checksum. @@ -196,7 +197,7 @@ func Checksum(buf []byte, initial uint16) uint16 { // the given VectorizedView. // // The initial checksum must have been computed on an even number of bytes. -func ChecksumVV(vv buffer.VectorisedView, initial uint16) uint16 { +func ChecksumVV(vv tcpipbuffer.VectorisedView, initial uint16) uint16 { var c Checksumer for _, v := range vv.Views() { c.Add([]byte(v)) @@ -204,6 +205,18 @@ func ChecksumVV(vv buffer.VectorisedView, initial uint16) uint16 { return ChecksumCombine(initial, c.Checksum()) } +// ChecksumBuffer calculates the checksum (as defined in RFC 1071) of the +// bytes in the given Buffer. +// +// The initial checksum must have been computed on an even number of bytes. +func ChecksumBuffer(buf buffer.Buffer, initial uint16) uint16 { + var c Checksumer + buf.Apply(func(b []byte) { + c.Add(b) + }) + return ChecksumCombine(initial, c.Checksum()) +} + // Checksumer calculates checksum defined in RFC 1071. type Checksumer struct { sum uint16 diff --git a/pkg/tcpip/network/ipv6/icmp_test.go b/pkg/tcpip/network/ipv6/icmp_test.go index 43cad28ce..897b21ba0 100644 --- a/pkg/tcpip/network/ipv6/icmp_test.go +++ b/pkg/tcpip/network/ipv6/icmp_test.go @@ -591,6 +591,7 @@ func TestLinkResolution(t *testing.T) { // doesn't provoke NDP discovery. var wq waiter.Queue ep, err := c.s0.NewEndpoint(header.ICMPv6ProtocolNumber, ProtocolNumber, &wq) + defer ep.Close() if err != nil { t.Fatalf("NewEndpoint(_) = (_, %s), want = (_, nil)", err) } diff --git a/pkg/tcpip/stack/packet_buffer.go b/pkg/tcpip/stack/packet_buffer.go index ae56f90b4..dd7eff877 100644 --- a/pkg/tcpip/stack/packet_buffer.go +++ b/pkg/tcpip/stack/packet_buffer.go @@ -586,6 +586,11 @@ func (d PacketData) AppendView(v tcpipbuffer.View) { d.pk.buf.AppendOwned(v) } +// MergeBuffer merges b into d and clears b. +func (d PacketData) MergeBuffer(b buffer.Buffer) { + d.pk.buf.Merge(&b) +} + // MergeFragment appends the data portion of frag to dst. It modifies // frag and frag should not be used again. func MergeFragment(dst, frag *PacketBuffer) { diff --git a/pkg/tcpip/transport/BUILD b/pkg/tcpip/transport/BUILD index 624381abd..889317964 100644 --- a/pkg/tcpip/transport/BUILD +++ b/pkg/tcpip/transport/BUILD @@ -19,7 +19,6 @@ go_test( deps = [ ":transport", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/header", "//pkg/tcpip/link/loopback", "//pkg/tcpip/network/ipv4", diff --git a/pkg/tcpip/transport/datagram_test.go b/pkg/tcpip/transport/datagram_test.go index a1e5c1851..b80912102 100644 --- a/pkg/tcpip/transport/datagram_test.go +++ b/pkg/tcpip/transport/datagram_test.go @@ -23,7 +23,6 @@ import ( "github.com/google/go-cmp/cmp" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/loopback" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" @@ -184,7 +183,7 @@ func (e *mockEndpoint) pktsSize() int { func TestSndBuf(t *testing.T) { const nicID = 1 - buf := buffer.NewView(header.ICMPv4MinimumSize) + buf := make([]byte, header.ICMPv4MinimumSize) header.ICMPv4(buf).SetType(header.ICMPv4Echo) for _, test := range []struct { @@ -363,15 +362,15 @@ func TestDeviceReturnErrNoBufferSpace(t *testing.T) { netProto tcpip.NetworkProtocolNumber localAddr tcpip.Address remoteAddr tcpip.Address - buf buffer.View + buf []byte }{ { name: "IPv4", netProto: ipv4.ProtocolNumber, localAddr: testutil.MustParse4("1.2.3.4"), remoteAddr: testutil.MustParse4("1.0.0.1"), - buf: func() buffer.View { - buf := buffer.NewView(header.ICMPv4MinimumSize) + buf: func() []byte { + buf := make([]byte, header.ICMPv4MinimumSize) header.ICMPv4(buf).SetType(header.ICMPv4Echo) return buf }(), @@ -381,8 +380,8 @@ func TestDeviceReturnErrNoBufferSpace(t *testing.T) { netProto: ipv6.ProtocolNumber, localAddr: testutil.MustParse6("a::1"), remoteAddr: testutil.MustParse6("a::2"), - buf: func() buffer.View { - buf := buffer.NewView(header.ICMPv6MinimumSize) + buf: func() []byte { + buf := make([]byte, header.ICMPv6MinimumSize) header.ICMPv6(buf).SetType(header.ICMPv6EchoRequest) return buf }(), diff --git a/pkg/tcpip/transport/icmp/BUILD b/pkg/tcpip/transport/icmp/BUILD index 5affd5459..7f65952aa 100644 --- a/pkg/tcpip/transport/icmp/BUILD +++ b/pkg/tcpip/transport/icmp/BUILD @@ -26,6 +26,7 @@ go_library( imports = ["gvisor.dev/gvisor/pkg/tcpip/buffer"], visibility = ["//visibility:public"], deps = [ + "//pkg/buffer", "//pkg/log", "//pkg/sleep", "//pkg/sync", @@ -51,7 +52,6 @@ go_test( "//pkg/refs", "//pkg/refsvfs2", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/checker", "//pkg/tcpip/header", "//pkg/tcpip/link/channel", diff --git a/pkg/tcpip/transport/icmp/endpoint.go b/pkg/tcpip/transport/icmp/endpoint.go index a70a5c73d..f17ebcea8 100644 --- a/pkg/tcpip/transport/icmp/endpoint.go +++ b/pkg/tcpip/transport/icmp/endpoint.go @@ -19,10 +19,10 @@ import ( "io" "time" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/ports" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -36,8 +36,8 @@ type icmpPacket struct { icmpPacketEntry senderAddress tcpip.FullAddress packetInfo tcpip.IPPacketInfo - data buffer.VectorisedView `state:".(buffer.VectorisedView)"` - receivedAt time.Time `state:".(int64)"` + data *stack.PacketBuffer + receivedAt time.Time `state:".(int64)"` // tosOrTClass stores either the Type of Service for IPv4 or the Traffic Class // for IPv6. @@ -149,6 +149,7 @@ func (e *endpoint) Close() { for !e.rcvList.Empty() { p := e.rcvList.Front() e.rcvList.Remove(p) + p.data.DecRef() } return true @@ -184,7 +185,8 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult p := e.rcvList.Front() if !opts.Peek { e.rcvList.Remove(p) - e.rcvBufSize -= p.data.Size() + defer p.data.DecRef() + e.rcvBufSize -= p.data.Data().Size() } e.rcvMu.Unlock() @@ -232,14 +234,14 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult } res := tcpip.ReadResult{ - Total: p.data.Size(), + Total: p.data.Data().Size(), ControlMessages: cm, } if opts.NeedRemoteAddr { res.RemoteAddr = p.senderAddress } - n, err := p.data.ReadTo(dst, opts.Peek) + n, err := p.data.Data().ReadTo(dst, opts.Peek) if n == 0 && err != nil { return res, &tcpip.ErrBadBuffer{} } @@ -383,7 +385,7 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, tcpip.Error) { e.rcvMu.Lock() if !e.rcvList.Empty() { p := e.rcvList.Front() - v = p.data.Size() + v = p.data.Data().Size() } e.rcvMu.Unlock() return v, nil @@ -398,13 +400,13 @@ func (e *endpoint) GetSockOpt(opt tcpip.GettableSocketOption) tcpip.Error { return e.net.GetSockOpt(opt) } -func send4(s *stack.Stack, ctx *network.WriteContext, ident uint16, data buffer.View, maxHeaderLength uint16) tcpip.Error { +func send4(s *stack.Stack, ctx *network.WriteContext, ident uint16, data []byte, maxHeaderLength uint16) tcpip.Error { if len(data) < header.ICMPv4MinimumSize { log.Infof("len(data) is smaller than min size") return &tcpip.ErrInvalidEndpointState{} } - pkt := ctx.TryNewPacketBuffer(header.ICMPv4MinimumSize+int(maxHeaderLength), buffer.VectorisedView{}) + pkt := ctx.TryNewPacketBuffer(header.ICMPv4MinimumSize+int(maxHeaderLength), buffer.Buffer{}) if pkt == nil { return &tcpip.ErrWouldBlock{} } @@ -441,12 +443,12 @@ func send4(s *stack.Stack, ctx *network.WriteContext, ident uint16, data buffer. return nil } -func send6(s *stack.Stack, ctx *network.WriteContext, ident uint16, data buffer.View, src, dst tcpip.Address, maxHeaderLength uint16) tcpip.Error { +func send6(s *stack.Stack, ctx *network.WriteContext, ident uint16, data []byte, src, dst tcpip.Address, maxHeaderLength uint16) tcpip.Error { if len(data) < header.ICMPv6EchoMinimumSize { return &tcpip.ErrInvalidEndpointState{} } - pkt := ctx.TryNewPacketBuffer(header.ICMPv6MinimumSize+int(maxHeaderLength), buffer.VectorisedView{}) + pkt := ctx.TryNewPacketBuffer(header.ICMPv6MinimumSize+int(maxHeaderLength), buffer.Buffer{}) if pkt == nil { return &tcpip.ErrWouldBlock{} } @@ -757,12 +759,14 @@ func (e *endpoint) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketB packet.ttlOrHopLimit = header.IPv6(pkt.NetworkHeader().View()).HopLimit() } - // ICMP socket's data includes ICMP header. - packet.data = pkt.TransportHeader().View().ToVectorisedView() - packet.data.Append(pkt.Data().ExtractVV()) + // ICMP socket's data includes ICMP header but no others. Trim all other + // headers from the front of the packet. + pktBuf := pkt.Buffer() + pktBuf.TrimFront(int64(pkt.HeaderSize() - len(pkt.TransportHeader().View()))) + packet.data = stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: pktBuf}) e.rcvList.PushBack(packet) - e.rcvBufSize += packet.data.Size() + e.rcvBufSize += packet.data.Data().Size() packet.receivedAt = e.stack.Clock().Now() diff --git a/pkg/tcpip/transport/icmp/endpoint_state.go b/pkg/tcpip/transport/icmp/endpoint_state.go index dfe453ff9..54752dd26 100644 --- a/pkg/tcpip/transport/icmp/endpoint_state.go +++ b/pkg/tcpip/transport/icmp/endpoint_state.go @@ -19,7 +19,6 @@ import ( "time" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport" ) @@ -34,22 +33,6 @@ func (p *icmpPacket) loadReceivedAt(nsec int64) { p.receivedAt = time.Unix(0, nsec) } -// saveData saves icmpPacket.data field. -func (p *icmpPacket) saveData() buffer.VectorisedView { - // We cannot save p.data directly as p.data.views may alias to p.views, - // which is not allowed by state framework (in-struct pointer). - return p.data.Clone(nil) -} - -// loadData loads icmpPacket.data field. -func (p *icmpPacket) loadData(data buffer.VectorisedView) { - // NOTE: We cannot do the p.data = data.Clone(p.views[:]) optimization - // here because data.views is not guaranteed to be loaded by now. Plus, - // data.views will be allocated anyway so there really is little point - // of utilizing p.views for data.views. - p.data = data -} - // afterLoad is invoked by stateify. func (e *endpoint) afterLoad() { stack.StackFromEnv.RegisterRestoredEndpoint(e) diff --git a/pkg/tcpip/transport/icmp/icmp_test.go b/pkg/tcpip/transport/icmp/icmp_test.go index ba50e1632..870207a81 100644 --- a/pkg/tcpip/transport/icmp/icmp_test.go +++ b/pkg/tcpip/transport/icmp/icmp_test.go @@ -15,13 +15,13 @@ package icmp_test import ( + "bytes" "os" "testing" "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/refsvfs2" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/channel" @@ -111,8 +111,8 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { echoPayloadSize := defaultEP.MTU() - header.IPv4MinimumSize - header.ICMPv4MinimumSize - newICMPv4EchoRequest := func() buffer.View { - buf := buffer.NewView(header.ICMPv4MinimumSize + int(echoPayloadSize)) + newICMPv4EchoRequest := func() []byte { + buf := make([]byte, header.ICMPv4MinimumSize+int(echoPayloadSize)) writePayload(buf[header.ICMPv4MinimumSize:]) icmp := header.ICMPv4(buf) @@ -127,7 +127,8 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { // to be added is the default NIC to send packets when not explicitly bound. { buf := newICMPv4EchoRequest() - r := buf.Reader() + var r bytes.Reader + r.Reset(buf) n, err := socket.Write(&r, tcpip.WriteOptions{ To: &tcpip.FullAddress{Addr: remoteV4Addr}, }) @@ -144,9 +145,9 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { t.Fatalf("got defaultEP.Read(_) = _, false; want = _, true (packet wasn't written out)") } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) + pkbuf := p.Buffer() + b := pkbuf.Flatten() p.DecRef() - b := vv.ToView() checker.IPv4(t, b, []checker.NetworkChecker{ checker.SrcAddr(localV4Addr1), @@ -170,7 +171,8 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { socket.SocketOptions().SetBindToDevice(2) buf := newICMPv4EchoRequest() - r := buf.Reader() + var r bytes.Reader + r.Reset(buf) n, err := socket.Write(&r, tcpip.WriteOptions{ To: &tcpip.FullAddress{Addr: remoteV4Addr}, }) @@ -192,9 +194,9 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { t.Fatalf("got alternateEP.Read(_) = _, false; want = _, true (packet wasn't written out)") } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) + pkbuf := p.Buffer() + b := pkbuf.Flatten() p.DecRef() - b := vv.ToView() checker.IPv4(t, b, []checker.NetworkChecker{ checker.SrcAddr(localV4Addr2), @@ -213,7 +215,8 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { socket.SocketOptions().SetBindToDevice(0) buf := newICMPv4EchoRequest() - r := buf.Reader() + var r bytes.Reader + r.Reset(buf) n, err := socket.Write(&r, tcpip.WriteOptions{ To: &tcpip.FullAddress{Addr: remoteV4Addr}, }) @@ -230,9 +233,9 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { t.Fatalf("got defaultEP.Read(_) = _, false; want = _, true (packet wasn't written out)") } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) + pkbuf := p.Buffer() + b := pkbuf.Flatten() p.DecRef() - b := vv.ToView() checker.IPv4(t, b, []checker.NetworkChecker{ checker.SrcAddr(localV4Addr1), @@ -250,9 +253,9 @@ func TestWriteUnboundWithBindToDevice(t *testing.T) { } } -func buildV4EchoReplyPacket(payload []byte, h context.Header4Tuple) (buffer.View, buffer.View) { +func buildV4EchoReplyPacket(payload []byte, h context.Header4Tuple) ([]byte, []byte) { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.IPv4MinimumSize + header.ICMPv4MinimumSize + len(payload)) + buf := make([]byte, header.IPv4MinimumSize+header.ICMPv4MinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) @@ -275,12 +278,12 @@ func buildV4EchoReplyPacket(payload []byte, h context.Header4Tuple) (buffer.View icmp.SetIdent(h.Dst.Port) icmp.SetChecksum(^header.Checksum(icmp, 0)) - return buf, buffer.View(icmp) + return buf, icmp } -func buildV6EchoReplyPacket(payload []byte, h context.Header4Tuple) (buffer.View, buffer.View) { +func buildV6EchoReplyPacket(payload []byte, h context.Header4Tuple) ([]byte, []byte) { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.IPv6MinimumSize + header.ICMPv6EchoMinimumSize + len(payload)) + buf := make([]byte, header.IPv6MinimumSize+header.ICMPv6EchoMinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) @@ -308,12 +311,12 @@ func buildV6EchoReplyPacket(payload []byte, h context.Header4Tuple) (buffer.View PayloadLen: len(payload), })) - return buf, buffer.View(icmpv6) + return buf, icmpv6 } // buildEchoReplyPacket builds an ICMPv4 or ICMPv6 echo reply packet, and // returns the full packet and the ICMP portion of the packet. -func buildEchoReplyPacket(payload []byte, flow context.TestFlow) (buffer.View, buffer.View) { +func buildEchoReplyPacket(payload []byte, flow context.TestFlow) ([]byte, []byte) { h := flow.MakeHeader4Tuple(context.Incoming) if flow.IsV4() { return buildV4EchoReplyPacket(payload, h) diff --git a/pkg/tcpip/transport/icmp/protocol.go b/pkg/tcpip/transport/icmp/protocol.go index 5d4bbb10c..d5b2c39cf 100644 --- a/pkg/tcpip/transport/icmp/protocol.go +++ b/pkg/tcpip/transport/icmp/protocol.go @@ -20,7 +20,7 @@ import ( "fmt" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" + tcpipbuffer "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport/raw" @@ -87,7 +87,7 @@ func (p *protocol) MinimumPacketSize() int { } // ParsePorts in case of ICMP sets src to 0, dst to ICMP ID, and err to nil. -func (p *protocol) ParsePorts(v buffer.View) (src, dst uint16, err tcpip.Error) { +func (p *protocol) ParsePorts(v tcpipbuffer.View) (src, dst uint16, err tcpip.Error) { switch p.number { case ProtocolNumber4: hdr := header.ICMPv4(v) diff --git a/pkg/tcpip/transport/internal/network/BUILD b/pkg/tcpip/transport/internal/network/BUILD index 16b68570e..540c98091 100644 --- a/pkg/tcpip/transport/internal/network/BUILD +++ b/pkg/tcpip/transport/internal/network/BUILD @@ -15,9 +15,9 @@ go_library( ], deps = [ "//pkg/atomicbitops", + "//pkg/buffer", "//pkg/sync", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/header", "//pkg/tcpip/stack", "//pkg/tcpip/transport", @@ -31,10 +31,10 @@ go_test( srcs = ["endpoint_test.go"], deps = [ ":network", + "//pkg/buffer", "//pkg/refs", "//pkg/refsvfs2", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/checker", "//pkg/tcpip/faketime", "//pkg/tcpip/header", diff --git a/pkg/tcpip/transport/internal/network/endpoint.go b/pkg/tcpip/transport/internal/network/endpoint.go index 72d5c6105..27ae08634 100644 --- a/pkg/tcpip/transport/internal/network/endpoint.go +++ b/pkg/tcpip/transport/internal/network/endpoint.go @@ -20,9 +20,9 @@ import ( "fmt" "gvisor.dev/gvisor/pkg/atomicbitops" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport" @@ -265,7 +265,7 @@ func (c *WriteContext) PacketInfo() WritePacketInfo { // // If this method returns nil, the caller should wait for the endpoint to become // writable. -func (c *WriteContext) TryNewPacketBuffer(reserveHdrBytes int, data buffer.VectorisedView) *stack.PacketBuffer { +func (c *WriteContext) TryNewPacketBuffer(reserveHdrBytes int, data buffer.Buffer) *stack.PacketBuffer { e := c.e e.sendBufferSizeInUseMu.Lock() @@ -288,7 +288,7 @@ func (c *WriteContext) TryNewPacketBuffer(reserveHdrBytes int, data buffer.Vecto return stack.NewPacketBuffer(stack.PacketBufferOptions{ ReserveHeaderBytes: reserveHdrBytes, - Data: data, + Payload: data, OnRelease: func() { e.sendBufferSizeInUseMu.Lock() if got := e.sendBufferSizeInUse; got < pktSize { diff --git a/pkg/tcpip/transport/internal/network/endpoint_test.go b/pkg/tcpip/transport/internal/network/endpoint_test.go index 913b38816..2bf9340c2 100644 --- a/pkg/tcpip/transport/internal/network/endpoint_test.go +++ b/pkg/tcpip/transport/internal/network/endpoint_test.go @@ -20,10 +20,10 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/refsvfs2" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/faketime" "gvisor.dev/gvisor/pkg/tcpip/header" @@ -49,8 +49,8 @@ var ( func TestEndpointStateTransitions(t *testing.T) { const nicID = 1 - data := buffer.View([]byte{1, 2, 4, 5}) - v4Checker := func(t *testing.T, b buffer.View) { + data := []byte{1, 2, 4, 5} + v4Checker := func(t *testing.T, b []byte) { checker.IPv4(t, b, checker.SrcAddr(ipv4NICAddr), checker.DstAddr(ipv4RemoteAddr), @@ -58,7 +58,7 @@ func TestEndpointStateTransitions(t *testing.T) { ) } - v6Checker := func(t *testing.T, b buffer.View) { + v6Checker := func(t *testing.T, b []byte) { checker.IPv6(t, b, checker.SrcAddr(ipv6NICAddr), checker.DstAddr(ipv6RemoteAddr), @@ -76,7 +76,7 @@ func TestEndpointStateTransitions(t *testing.T) { expectedBoundAddr tcpip.Address remoteAddr tcpip.Address expectedRemoteAddr tcpip.Address - checker func(*testing.T, buffer.View) + checker func(*testing.T, []byte) }{ { name: "IPv4", @@ -205,7 +205,7 @@ func TestEndpointStateTransitions(t *testing.T) { } injectPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ ReserveHeaderBytes: int(info.MaxHeaderLength), - Data: data.ToVectorisedView(), + Payload: buffer.NewWithData(data), }) defer injectPkt.DecRef() if err := ctx.WritePacket(injectPkt, false /* headerIncluded */); err != nil { diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go index 14b0b0767..74d807824 100644 --- a/pkg/tcpip/transport/packet/endpoint.go +++ b/pkg/tcpip/transport/packet/endpoint.go @@ -39,10 +39,9 @@ import ( // +stateify savable type packet struct { packetEntry - // data holds the actual packet data, including any headers and - // payload. - data buffer.VectorisedView `state:".(buffer.VectorisedView)"` - receivedAt time.Time `state:".(int64)"` + // data holds the actual packet data, including any headers and payload. + data *stack.PacketBuffer + receivedAt time.Time `state:".(int64)"` // senderAddr is the network address of the sender. senderAddr tcpip.FullAddress // packetInfo holds additional information like the protocol @@ -145,7 +144,9 @@ func (ep *endpoint) Close() { ep.rcvClosed = true ep.rcvBufSize = 0 for !ep.rcvList.Empty() { - ep.rcvList.Remove(ep.rcvList.Front()) + p := ep.rcvList.Front() + ep.rcvList.Remove(p) + p.data.DecRef() } ep.closed = true @@ -174,6 +175,7 @@ func (ep *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResul packet := ep.rcvList.Front() if !opts.Peek { ep.rcvList.Remove(packet) + defer packet.data.DecRef() ep.rcvBufSize -= packet.data.Size() } @@ -193,7 +195,7 @@ func (ep *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResul res.LinkPacketInfo = packet.packetInfo } - n, err := packet.data.ReadTo(dst, opts.Peek) + n, err := packet.data.Data().ReadTo(dst, opts.Peek) if n == 0 && err != nil { return res, &tcpip.ErrBadBuffer{} } @@ -447,20 +449,14 @@ func (ep *endpoint) HandlePacket(nicID tcpip.NICID, netProto tcpip.NetworkProtoc rcvdPkt.senderAddr.Addr = tcpip.Address(hdr.SourceAddress()) } + // Raw packet endpoints include link-headers in received packets. + pktBuf := pkt.Buffer() if ep.cooked { // Cooked packet endpoints don't include the link-headers in received // packets. - if v := pkt.NetworkHeader().View(); !v.IsEmpty() { - rcvdPkt.data.AppendView(v) - } - if v := pkt.TransportHeader().View(); !v.IsEmpty() { - rcvdPkt.data.AppendView(v) - } - rcvdPkt.data.Append(pkt.Data().ExtractVV()) - } else { - // Raw packet endpoints include link-headers in received packets. - rcvdPkt.data = buffer.NewVectorisedView(pkt.Size(), pkt.Views()) + pktBuf.TrimFront(int64(len(pkt.LinkHeader().View()) + len(pkt.VirtioNetHeader().View()))) } + rcvdPkt.data = stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: pktBuf}) ep.rcvList.PushBack(&rcvdPkt) ep.rcvBufSize += rcvdPkt.data.Size() diff --git a/pkg/tcpip/transport/packet/endpoint_state.go b/pkg/tcpip/transport/packet/endpoint_state.go index 88cd80ad3..74203fa83 100644 --- a/pkg/tcpip/transport/packet/endpoint_state.go +++ b/pkg/tcpip/transport/packet/endpoint_state.go @@ -19,7 +19,6 @@ import ( "time" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/stack" ) @@ -33,16 +32,6 @@ func (p *packet) loadReceivedAt(nsec int64) { p.receivedAt = time.Unix(0, nsec) } -// saveData saves packet.data field. -func (p *packet) saveData() buffer.VectorisedView { - return p.data.Clone(nil) -} - -// loadData loads packet.data field. -func (p *packet) loadData(data buffer.VectorisedView) { - p.data = data -} - // beforeSave is invoked by stateify. func (ep *endpoint) beforeSave() { ep.rcvMu.Lock() diff --git a/pkg/tcpip/transport/raw/BUILD b/pkg/tcpip/transport/raw/BUILD index 9185926f3..3c1d329f9 100644 --- a/pkg/tcpip/transport/raw/BUILD +++ b/pkg/tcpip/transport/raw/BUILD @@ -26,6 +26,7 @@ go_library( imports = ["gvisor.dev/gvisor/pkg/tcpip/buffer"], visibility = ["//visibility:public"], deps = [ + "//pkg/buffer", "//pkg/log", "//pkg/sleep", "//pkg/sync", diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go index 496e972c7..bdf274caf 100644 --- a/pkg/tcpip/transport/raw/endpoint.go +++ b/pkg/tcpip/transport/raw/endpoint.go @@ -30,9 +30,9 @@ import ( "io" "time" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport" @@ -45,8 +45,8 @@ type rawPacket struct { rawPacketEntry // data holds the actual packet data, including any headers and // payload. - data buffer.VectorisedView `state:".(buffer.VectorisedView)"` - receivedAt time.Time `state:".(int64)"` + data *stack.PacketBuffer + receivedAt time.Time `state:".(int64)"` // senderAddr is the network address of the sender. senderAddr tcpip.FullAddress packetInfo tcpip.IPPacketInfo @@ -203,7 +203,9 @@ func (e *endpoint) Close() { e.rcvClosed = true e.rcvBufSize = 0 for !e.rcvList.Empty() { - e.rcvList.Remove(e.rcvList.Front()) + p := e.rcvList.Front() + e.rcvList.Remove(p) + p.data.DecRef() } e.waiterQueue.Notify(waiter.EventHUp | waiter.EventErr | waiter.ReadableEvents | waiter.WritableEvents) @@ -235,7 +237,8 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult pkt := e.rcvList.Front() if !opts.Peek { e.rcvList.Remove(pkt) - e.rcvBufSize -= pkt.data.Size() + defer pkt.data.DecRef() + e.rcvBufSize -= pkt.data.Data().Size() } e.rcvMu.Unlock() @@ -283,14 +286,14 @@ func (e *endpoint) Read(dst io.Writer, opts tcpip.ReadOptions) (tcpip.ReadResult } res := tcpip.ReadResult{ - Total: pkt.data.Size(), + Total: pkt.data.Data().Size(), ControlMessages: cm, } if opts.NeedRemoteAddr { res.RemoteAddr = pkt.senderAddr } - n, err := pkt.data.ReadTo(dst, opts.Peek) + n, err := pkt.data.Data().ReadTo(dst, opts.Peek) if n == 0 && err != nil { return res, &tcpip.ErrBadBuffer{} } @@ -360,7 +363,7 @@ func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp header.PutChecksum(payloadBytes[ipv6ChecksumOffset:], ^xsum) } - pkt := ctx.TryNewPacketBuffer(int(ctx.PacketInfo().MaxHeaderLength), buffer.View(payloadBytes).ToVectorisedView()) + pkt := ctx.TryNewPacketBuffer(int(ctx.PacketInfo().MaxHeaderLength), buffer.NewWithData(payloadBytes)) if pkt == nil { return 0, &tcpip.ErrWouldBlock{} } @@ -550,7 +553,7 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, tcpip.Error) { e.rcvMu.Lock() if !e.rcvList.Empty() { p := e.rcvList.Front() - v = p.data.Size() + v = p.data.Data().Size() } e.rcvMu.Unlock() return v, nil @@ -664,15 +667,16 @@ func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) { // TODO(https://gvisor.dev/issue/6517): Avoid the copy once S/R supports // overlapping slices. transportHeader := pkt.TransportHeader().View() - var combinedVV buffer.VectorisedView + var combinedBuf buffer.Buffer switch info.NetProto { case header.IPv4ProtocolNumber: networkHeader := pkt.NetworkHeader().View() - headers := make(buffer.View, 0, len(networkHeader)+len(transportHeader)) + headers := make([]byte, 0, len(networkHeader)+len(transportHeader)) headers = append(headers, networkHeader...) headers = append(headers, transportHeader...) - combinedVV = headers.ToVectorisedView() - combinedVV.Append(pkt.Data().ExtractVV()) + combinedBuf = buffer.NewWithData(headers) + pktBuf := pkt.Data().AsBuffer() + combinedBuf.Merge(&pktBuf) case header.IPv6ProtocolNumber: if e.transProto == header.ICMPv6ProtocolNumber { if len(transportHeader) < header.ICMPv6MinimumSize { @@ -684,18 +688,19 @@ func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) { } } - combinedVV = append(buffer.View(nil), transportHeader...).ToVectorisedView() - combinedVV.Append(pkt.Data().ExtractVV()) + combinedBuf = buffer.NewWithData(transportHeader) + pktBuf := pkt.Data().AsBuffer() + combinedBuf.Merge(&pktBuf) if checksumOffset := e.ipv6ChecksumOffset; checksumOffset >= 0 { - vvSize := combinedVV.Size() - if vvSize < checksumOffset+header.ChecksumSize { + bufSize := int(combinedBuf.Size()) + if bufSize < checksumOffset+header.ChecksumSize { // Message too small to fit checksum. return false } - xsum := header.PseudoHeaderChecksum(e.transProto, srcAddr, dstAddr, uint16(vvSize)) - xsum = header.ChecksumVV(combinedVV, xsum) + xsum := header.PseudoHeaderChecksum(e.transProto, srcAddr, dstAddr, uint16(bufSize)) + xsum = header.ChecksumBuffer(combinedBuf, xsum) if xsum != 0xFFFF { // Invalid checksum. return false @@ -705,11 +710,11 @@ func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) { panic(fmt.Sprintf("unrecognized protocol number = %d", info.NetProto)) } - packet.data = combinedVV + packet.data = stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: combinedBuf}) packet.receivedAt = e.stack.Clock().Now() e.rcvList.PushBack(packet) - e.rcvBufSize += packet.data.Size() + e.rcvBufSize += packet.data.Data().Size() e.stats.PacketsReceived.Increment() // Notify waiters that there is data to be read now. diff --git a/pkg/tcpip/transport/raw/endpoint_state.go b/pkg/tcpip/transport/raw/endpoint_state.go index 615488f78..1bda0b8b2 100644 --- a/pkg/tcpip/transport/raw/endpoint_state.go +++ b/pkg/tcpip/transport/raw/endpoint_state.go @@ -19,7 +19,6 @@ import ( "time" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/stack" ) @@ -33,22 +32,6 @@ func (p *rawPacket) loadReceivedAt(nsec int64) { p.receivedAt = time.Unix(0, nsec) } -// saveData saves rawPacket.data field. -func (p *rawPacket) saveData() buffer.VectorisedView { - // We cannot save p.data directly as p.data.views may alias to p.views, - // which is not allowed by state framework (in-struct pointer). - return p.data.Clone(nil) -} - -// loadData loads rawPacket.data field. -func (p *rawPacket) loadData(data buffer.VectorisedView) { - // NOTE: We cannot do the p.data = data.Clone(p.views[:]) optimization - // here because data.views is not guaranteed to be loaded by now. Plus, - // data.views will be allocated anyway so there really is little point - // of utilizing p.views for data.views. - p.data = data -} - // afterLoad is invoked by stateify. func (e *endpoint) afterLoad() { stack.StackFromEnv.RegisterRestoredEndpoint(e) diff --git a/pkg/tcpip/transport/tcp/BUILD b/pkg/tcpip/transport/tcp/BUILD index 7e176d31f..d1f544661 100644 --- a/pkg/tcpip/transport/tcp/BUILD +++ b/pkg/tcpip/transport/tcp/BUILD @@ -72,6 +72,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/atomicbitops", + "//pkg/buffer", "//pkg/log", "//pkg/rand", "//pkg/refsvfs2", @@ -105,7 +106,6 @@ go_test( "//pkg/refs", "//pkg/refsvfs2", "//pkg/sleep", - "//pkg/tcpip/buffer", "//pkg/tcpip/faketime", "//pkg/tcpip/stack", "@com_github_google_go_cmp//cmp:go_default_library", diff --git a/pkg/tcpip/transport/tcp/segment.go b/pkg/tcpip/transport/tcp/segment.go index a0e81d843..be77c3e99 100644 --- a/pkg/tcpip/transport/tcp/segment.go +++ b/pkg/tcpip/transport/tcp/segment.go @@ -19,7 +19,6 @@ import ( "io" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/seqnum" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -127,7 +126,7 @@ func newIncomingSegment(id stack.TransportEndpointID, clock tcpip.Clock, pkt *st return s, nil } -func newOutgoingSegment(id stack.TransportEndpointID, clock tcpip.Clock, v buffer.View) *segment { +func newOutgoingSegment(id stack.TransportEndpointID, clock tcpip.Clock, v []byte) *segment { s := &segment{ id: id, } diff --git a/pkg/tcpip/transport/tcp/segment_test.go b/pkg/tcpip/transport/tcp/segment_test.go index 0bf8757ba..76d1773a0 100644 --- a/pkg/tcpip/transport/tcp/segment_test.go +++ b/pkg/tcpip/transport/tcp/segment_test.go @@ -18,7 +18,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/faketime" "gvisor.dev/gvisor/pkg/tcpip/stack" ) @@ -44,9 +43,9 @@ func checkSegmentSize(t *testing.T, name string, seg *segment, want segmentSizeW func TestSegmentMerge(t *testing.T) { var clock faketime.NullClock id := stack.TransportEndpointID{} - seg1 := newOutgoingSegment(id, &clock, buffer.NewView(10)) + seg1 := newOutgoingSegment(id, &clock, make([]byte, 10)) defer seg1.DecRef() - seg2 := newOutgoingSegment(id, &clock, buffer.NewView(20)) + seg2 := newOutgoingSegment(id, &clock, make([]byte, 20)) defer seg2.DecRef() checkSegmentSize(t, "seg1", seg1, segmentSizeWants{ diff --git a/pkg/tcpip/transport/tcp/test/e2e/BUILD b/pkg/tcpip/transport/tcp/test/e2e/BUILD index f20f186d7..0e9a09138 100644 --- a/pkg/tcpip/transport/tcp/test/e2e/BUILD +++ b/pkg/tcpip/transport/tcp/test/e2e/BUILD @@ -9,6 +9,7 @@ go_test( shard_count = more_shards, deps = [ ":e2e", + "//pkg/buffer", "//pkg/rand", "//pkg/refs", "//pkg/refsvfs2", diff --git a/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go index 7c45af9b9..f2a31f1a6 100644 --- a/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go +++ b/pkg/tcpip/transport/tcp/test/e2e/tcp_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/rand" "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/refsvfs2" @@ -4688,7 +4689,7 @@ func TestReceivedInvalidSegmentCountIncrement(t *testing.T) { stats := c.Stack().Stats() want := stats.TCP.InvalidSegmentsReceived.Value() + 1 iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) - vv := c.BuildSegment(nil, &context.Headers{ + buf := c.BuildSegment(nil, &context.Headers{ SrcPort: context.TestPort, DstPort: c.Port, Flags: header.TCPFlagAck, @@ -4696,10 +4697,10 @@ func TestReceivedInvalidSegmentCountIncrement(t *testing.T) { AckNum: c.IRS.Add(1), RcvWnd: 30000, }) - tcpbuf := vv.ToView()[header.IPv4MinimumSize:] - tcpbuf[header.TCPDataOffset] = ((header.TCPMinimumSize - 1) / 4) << 4 + tcpbuf := buf.Flatten() + tcpbuf[header.IPv4MinimumSize+header.TCPDataOffset] = ((header.TCPMinimumSize - 1) / 4) << 4 - c.SendSegment(vv) + c.SendSegment(buffer.NewWithData(tcpbuf)) if got := stats.TCP.InvalidSegmentsReceived.Value(); got != want { t.Errorf("got stats.TCP.InvalidSegmentsReceived.Value() = %d, want = %d", got, want) @@ -4716,7 +4717,7 @@ func TestReceivedIncorrectChecksumIncrement(t *testing.T) { stats := c.Stack().Stats() want := stats.TCP.ChecksumErrors.Value() + 1 iss := seqnum.Value(context.TestInitialSequenceNumber).Add(1) - vv := c.BuildSegment([]byte{0x1, 0x2, 0x3}, &context.Headers{ + buf := c.BuildSegment([]byte{0x1, 0x2, 0x3}, &context.Headers{ SrcPort: context.TestPort, DstPort: c.Port, Flags: header.TCPFlagAck, @@ -4724,12 +4725,12 @@ func TestReceivedIncorrectChecksumIncrement(t *testing.T) { AckNum: c.IRS.Add(1), RcvWnd: 30000, }) - tcpbuf := vv.ToView()[header.IPv4MinimumSize:] + tcpbuf := buf.Flatten() // Overwrite a byte in the payload which should cause checksum // verification to fail. - tcpbuf[(tcpbuf[header.TCPDataOffset]>>4)*4] = 0x4 + tcpbuf[header.IPv4MinimumSize+((tcpbuf[header.IPv4MinimumSize+header.TCPDataOffset]>>4)*4)] = 0x4 - c.SendSegment(vv) + c.SendSegment(buffer.NewWithData(tcpbuf)) if got := stats.TCP.ChecksumErrors.Value(); got != want { t.Errorf("got stats.TCP.ChecksumErrors.Value() = %d, want = %d", got, want) diff --git a/pkg/tcpip/transport/tcp/testing/context/BUILD b/pkg/tcpip/transport/tcp/testing/context/BUILD index ce6a2c31d..6ed2a6ff3 100644 --- a/pkg/tcpip/transport/tcp/testing/context/BUILD +++ b/pkg/tcpip/transport/tcp/testing/context/BUILD @@ -10,8 +10,8 @@ go_library( "//visibility:public", ], deps = [ + "//pkg/buffer", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/checker", "//pkg/tcpip/header", "//pkg/tcpip/link/channel", diff --git a/pkg/tcpip/transport/tcp/testing/context/context.go b/pkg/tcpip/transport/tcp/testing/context/context.go index e58d8b40d..19c8b5a95 100644 --- a/pkg/tcpip/transport/tcp/testing/context/context.go +++ b/pkg/tcpip/transport/tcp/testing/context/context.go @@ -22,8 +22,8 @@ import ( "testing" "time" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/channel" @@ -343,8 +343,8 @@ func (c *Context) GetPacketWithTimeout(timeout time.Duration) []byte { c.t.Fatalf("got pkt.TransportProtocolNumber = %d, want = %d", got, want) } - vv := buffer.NewVectorisedView(pkt.Size(), pkt.Views()) - b := vv.ToView() + buf := pkt.Buffer() + b := buf.Flatten() if pkt.GSOOptions.Type != stack.GSONone && pkt.GSOOptions.L3HdrLen != header.IPv4MinimumSize { c.t.Errorf("got L3HdrLen = %d, want = %d", pkt.GSOOptions.L3HdrLen, header.IPv4MinimumSize) @@ -394,8 +394,8 @@ func (c *Context) GetPacketNonBlocking() []byte { c.t.Fatalf("got pkt.TransportProtocolNumber = %d, want = %d", got, want) } - vv := buffer.NewVectorisedView(pkt.Size(), pkt.Views()) - b := vv.ToView() + buf := pkt.Buffer() + b := buf.Flatten() checker.IPv4(c.t, b, checker.SrcAddr(StackAddr), checker.DstAddr(TestAddr)) return b @@ -404,7 +404,7 @@ func (c *Context) GetPacketNonBlocking() []byte { // SendICMPPacket builds and sends an ICMPv4 packet via the link layer endpoint. func (c *Context) SendICMPPacket(typ header.ICMPv4Type, code header.ICMPv4Code, p1, p2 []byte, maxTotalSize int) { // Allocate a buffer data and headers. - buf := buffer.NewView(header.IPv4MinimumSize + header.ICMPv4PayloadOffset + len(p2)) + buf := make([]byte, header.IPv4MinimumSize+header.ICMPv4PayloadOffset+len(p2)) if len(buf) > maxTotalSize { buf = buf[:maxTotalSize] } @@ -431,22 +431,22 @@ func (c *Context) SendICMPPacket(typ header.ICMPv4Type, code header.ICMPv4Code, // Inject packet. pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: buf.ToVectorisedView(), + Payload: buffer.NewWithData(buf), }) defer pkt.DecRef() c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) } // BuildSegment builds a TCP segment based on the given Headers and payload. -func (c *Context) BuildSegment(payload []byte, h *Headers) buffer.VectorisedView { +func (c *Context) BuildSegment(payload []byte, h *Headers) buffer.Buffer { return c.BuildSegmentWithAddrs(payload, h, TestAddr, StackAddr) } // BuildSegmentWithAddrs builds a TCP segment based on the given Headers, // payload and source and destination IPv4 addresses. -func (c *Context) BuildSegmentWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) buffer.VectorisedView { +func (c *Context) BuildSegmentWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) buffer.Buffer { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.TCPMinimumSize + header.IPv4MinimumSize + len(h.TCPOpts) + len(payload)) + buf := make([]byte, header.TCPMinimumSize+header.IPv4MinimumSize+len(h.TCPOpts)+len(payload)) copy(buf[len(buf)-len(payload):], payload) copy(buf[len(buf)-len(payload)-len(h.TCPOpts):], h.TCPOpts) @@ -481,14 +481,14 @@ func (c *Context) BuildSegmentWithAddrs(payload []byte, h *Headers, src, dst tcp t.SetChecksum(^t.CalculateChecksum(xsum)) // Inject packet. - return buf.ToVectorisedView() + return buffer.NewWithData(buf) } // SendSegment sends a TCP segment that has already been built and written to a // buffer.VectorisedView. -func (c *Context) SendSegment(s buffer.VectorisedView) { +func (c *Context) SendSegment(s buffer.Buffer) { pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: s, + Payload: s, }) defer pkt.DecRef() c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) @@ -498,7 +498,7 @@ func (c *Context) SendSegment(s buffer.VectorisedView) { // headers) in an IPv4 packet via the link layer endpoint. func (c *Context) SendPacket(payload []byte, h *Headers) { pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: c.BuildSegment(payload, h), + Payload: c.BuildSegment(payload, h), }) defer pkt.DecRef() c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) @@ -509,7 +509,7 @@ func (c *Context) SendPacket(payload []byte, h *Headers) { // provided source and destination IPv4 addresses. func (c *Context) SendPacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) { pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: c.BuildSegmentWithAddrs(payload, h, src, dst), + Payload: c.BuildSegmentWithAddrs(payload, h, src, dst), }) defer pkt.DecRef() c.linkEP.InjectInbound(ipv4.ProtocolNumber, pkt) @@ -632,8 +632,8 @@ func (c *Context) GetV6Packet() []byte { if got, want := pkt.NetworkProtocolNumber, ipv6.ProtocolNumber; got != want { c.t.Fatalf("got pkt.NetworkProtocolNumber = %d, want = %d", got, want) } - vv := buffer.NewVectorisedView(pkt.Size(), pkt.Views()) - b := vv.ToView() + buf := pkt.Buffer() + b := buf.Flatten() checker.IPv6(c.t, b, checker.SrcAddr(StackV6Addr), checker.DstAddr(TestV6Addr)) return b @@ -650,7 +650,7 @@ func (c *Context) SendV6Packet(payload []byte, h *Headers) { // addresses. func (c *Context) SendV6PacketWithAddrs(payload []byte, h *Headers, src, dst tcpip.Address) { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.TCPMinimumSize + header.IPv6MinimumSize + len(h.TCPOpts) + len(payload)) + buf := make([]byte, header.TCPMinimumSize+header.IPv6MinimumSize+len(payload)+len(h.TCPOpts)) copy(buf[len(buf)-len(payload):], payload) copy(buf[len(buf)-len(payload)-len(h.TCPOpts):], h.TCPOpts) @@ -685,7 +685,7 @@ func (c *Context) SendV6PacketWithAddrs(payload []byte, h *Headers, src, dst tcp // Inject packet. pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: buf.ToVectorisedView(), + Payload: buffer.NewWithData(buf), }) defer pkt.DecRef() c.linkEP.InjectInbound(ipv6.ProtocolNumber, pkt) diff --git a/pkg/tcpip/transport/testing/context/BUILD b/pkg/tcpip/transport/testing/context/BUILD index f398ff67c..5544e547c 100644 --- a/pkg/tcpip/transport/testing/context/BUILD +++ b/pkg/tcpip/transport/testing/context/BUILD @@ -13,9 +13,9 @@ go_library( "//visibility:public", ], deps = [ + "//pkg/buffer", "//pkg/refsvfs2", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/checker", "//pkg/tcpip/faketime", "//pkg/tcpip/header", diff --git a/pkg/tcpip/transport/testing/context/context.go b/pkg/tcpip/transport/testing/context/context.go index 64eec1591..1fe473e78 100644 --- a/pkg/tcpip/transport/testing/context/context.go +++ b/pkg/tcpip/transport/testing/context/context.go @@ -23,9 +23,9 @@ import ( "github.com/google/go-cmp/cmp" "golang.org/x/time/rate" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/refsvfs2" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/faketime" "gvisor.dev/gvisor/pkg/tcpip/header" @@ -251,9 +251,9 @@ func (c *Context) CheckEndpointReadStats(incr uint64, want *tcpip.TransportEndpo } // InjectPacket injects a packet into the context's link endpoint. -func (c *Context) InjectPacket(netProto tcpip.NetworkProtocolNumber, buf buffer.View) { +func (c *Context) InjectPacket(netProto tcpip.NetworkProtocolNumber, buf []byte) { pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: buf.ToVectorisedView(), + Payload: buffer.NewWithData(buf), }) defer pkt.DecRef() c.LinkEP.InjectInbound(netProto, pkt) diff --git a/pkg/tcpip/transport/testing/context/flow.go b/pkg/tcpip/transport/testing/context/flow.go index 96fd10e0f..9512b18f8 100644 --- a/pkg/tcpip/transport/testing/context/flow.go +++ b/pkg/tcpip/transport/testing/context/flow.go @@ -19,7 +19,6 @@ import ( "testing" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" @@ -342,9 +341,9 @@ func (flow TestFlow) isReverseMulticast() bool { } // BuildV4UDPPacket builds an IPv4 UDP packet. -func BuildV4UDPPacket(payload []byte, h Header4Tuple, tos, ttl uint8, badChecksum bool) buffer.View { +func BuildV4UDPPacket(payload []byte, h Header4Tuple, tos, ttl uint8, badChecksum bool) []byte { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.UDPMinimumSize + header.IPv4MinimumSize + len(payload)) + buf := make([]byte, header.UDPMinimumSize+header.IPv4MinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) @@ -390,9 +389,9 @@ func BuildV4UDPPacket(payload []byte, h Header4Tuple, tos, ttl uint8, badChecksu } // BuildV6UDPPacket builds an IPv6 UDP packet. -func BuildV6UDPPacket(payload []byte, h Header4Tuple, tclass, hoplimit uint8, badChecksum bool) buffer.View { +func BuildV6UDPPacket(payload []byte, h Header4Tuple, tclass, hoplimit uint8, badChecksum bool) []byte { // Allocate a buffer for data and headers. - buf := buffer.NewView(header.UDPMinimumSize + header.IPv6MinimumSize + len(payload)) + buf := make([]byte, header.UDPMinimumSize+header.IPv6MinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) @@ -434,7 +433,7 @@ func BuildV6UDPPacket(payload []byte, h Header4Tuple, tclass, hoplimit uint8, ba // BuildUDPPacket builds an IPv4 or IPv6 UDP packet, depending on the specified // TestFlow. -func BuildUDPPacket(payload []byte, flow TestFlow, direction PacketDirection, tosOrTclass, ttlOrHopLimit uint8, badChecksum bool) buffer.View { +func BuildUDPPacket(payload []byte, flow TestFlow, direction PacketDirection, tosOrTclass, ttlOrHopLimit uint8, badChecksum bool) []byte { h := flow.MakeHeader4Tuple(direction) if flow.IsV4() { return BuildV4UDPPacket(payload, h, tosOrTclass, ttlOrHopLimit, badChecksum) diff --git a/pkg/tcpip/transport/udp/BUILD b/pkg/tcpip/transport/udp/BUILD index c4804482c..57b08a425 100644 --- a/pkg/tcpip/transport/udp/BUILD +++ b/pkg/tcpip/transport/udp/BUILD @@ -52,7 +52,6 @@ go_test( "//pkg/refs", "//pkg/refsvfs2", "//pkg/tcpip", - "//pkg/tcpip/buffer", "//pkg/tcpip/checker", "//pkg/tcpip/faketime", "//pkg/tcpip/header", diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 694326fe2..89bc9c622 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -20,9 +20,9 @@ import ( "math" "time" + "gvisor.dev/gvisor/pkg/buffer" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/ports" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -458,7 +458,7 @@ func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp defer udpInfo.ctx.Release() pktInfo := udpInfo.ctx.PacketInfo() - pkt := udpInfo.ctx.TryNewPacketBuffer(header.UDPMinimumSize+int(pktInfo.MaxHeaderLength), udpInfo.data.ToVectorisedView()) + pkt := udpInfo.ctx.TryNewPacketBuffer(header.UDPMinimumSize+int(pktInfo.MaxHeaderLength), buffer.NewWithData(udpInfo.data)) if pkt == nil { return 0, &tcpip.ErrWouldBlock{} } @@ -576,7 +576,7 @@ func (e *endpoint) GetSockOpt(opt tcpip.GettableSocketOption) tcpip.Error { // udpPacketInfo holds information needed to send a UDP packet. type udpPacketInfo struct { ctx network.WriteContext - data buffer.View + data []byte localPort uint16 remotePort uint16 } diff --git a/pkg/tcpip/transport/udp/udp_test.go b/pkg/tcpip/transport/udp/udp_test.go index aee793c31..7c1e755f5 100644 --- a/pkg/tcpip/transport/udp/udp_test.go +++ b/pkg/tcpip/transport/udp/udp_test.go @@ -27,7 +27,6 @@ import ( "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/refsvfs2" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/checker" "gvisor.dev/gvisor/pkg/tcpip/faketime" "gvisor.dev/gvisor/pkg/tcpip/header" @@ -466,7 +465,7 @@ func testWriteWithoutDestination(c *context.Context, flow context.TestFlow, chec // TODO(https://gvisor.dev/issue/5623): Extract the test write methods in the // testing context. -func testWriteNoVerify(c *context.Context, flow context.TestFlow, setDest bool) buffer.View { +func testWriteNoVerify(c *context.Context, flow context.TestFlow, setDest bool) []byte { c.T.Helper() // Take a snapshot of the stats to validate them at the end of the test. var epstats tcpip.TransportEndpointStats @@ -515,8 +514,8 @@ func testWriteAndVerifyInternal(c *context.Context, flow context.TestFlow, setDe c.T.Errorf("got p.TransportProtocolNumber = %d, want = %d", got, want) } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) - b := vv.ToView() + buf := p.Buffer() + b := buf.Flatten() h := flow.MakeHeader4Tuple(context.Outgoing) checkers = append( @@ -1376,9 +1375,9 @@ func TestV4UnknownDestination(t *testing.T) { t.Fatalf("packet wasn't written out") } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) + buf := p.Buffer() p.DecRef() - pkt := vv.ToView() + pkt := buf.Flatten() if got, want := len(pkt), header.IPv4MinimumProcessableDatagramSize; got > want { t.Fatalf("got an ICMP packet of size: %d, want: sz <= %d", got, want) } @@ -1471,9 +1470,9 @@ func TestV6UnknownDestination(t *testing.T) { t.Fatalf("packet wasn't written out") } - vv := buffer.NewVectorisedView(p.Size(), p.Views()) + buf := p.Buffer() p.DecRef() - pkt := vv.ToView() + pkt := buf.Flatten() if got, want := len(pkt), header.IPv6MinimumMTU; got > want { t.Fatalf("got an ICMP packet of size: %d, want: sz <= %d", got, want) } @@ -1550,7 +1549,7 @@ func TestShortHeader(t *testing.T) { // Allocate a buffer for an IPv6 and too-short UDP header. const udpSize = header.UDPMinimumSize - 1 - buf := buffer.NewView(header.IPv6MinimumSize + udpSize) + buf := make([]byte, header.IPv6MinimumSize+udpSize) // Initialize the IP header. ip := header.IPv6(buf) ip.Encode(&header.IPv6Fields{ @@ -1563,7 +1562,7 @@ func TestShortHeader(t *testing.T) { }) // Initialize the UDP header. - udpHdr := header.UDP(buffer.NewView(header.UDPMinimumSize)) + udpHdr := header.UDP(make([]byte, header.UDPMinimumSize)) udpHdr.Encode(&header.UDPFields{ SrcPort: h.Src.Port, DstPort: h.Dst.Port,