Replace VectorisedView in transport endpoints.

PiperOrigin-RevId: 452186398
This commit is contained in:
Lucas Manning
2022-05-31 18:29:02 -07:00
committed by gVisor bot
parent ad3f841aad
commit d9cb55b00c
33 changed files with 178 additions and 200 deletions
+1 -2
View File
@@ -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",
+1
View File
@@ -30,6 +30,7 @@ go_library(
],
visibility = ["//visibility:public"],
deps = [
"//pkg/buffer",
"//pkg/tcpip",
"//pkg/tcpip/buffer",
"//pkg/tcpip/seqnum",
+15 -2
View File
@@ -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
+1
View File
@@ -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)
}
+5
View File
@@ -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) {
-1
View File
@@ -19,7 +19,6 @@ go_test(
deps = [
":transport",
"//pkg/tcpip",
"//pkg/tcpip/buffer",
"//pkg/tcpip/header",
"//pkg/tcpip/link/loopback",
"//pkg/tcpip/network/ipv4",
+6 -7
View File
@@ -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
}(),
+1 -1
View File
@@ -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",
+19 -15
View File
@@ -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()
@@ -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)
+22 -19
View File
@@ -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)
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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",
@@ -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 {
@@ -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 {
+12 -16
View File
@@ -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()
@@ -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()
+1
View File
@@ -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",
+26 -21
View File
@@ -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.
-17
View File
@@ -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)

Some files were not shown because too many files have changed in this diff Show More