mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Always pass buffer.VectorisedView by value
PiperOrigin-RevId: 212757571 Change-Id: I04200df9e45c21eb64951cd2802532fa84afcb1a
This commit is contained in:
committed by
Shentubot
parent
5adb3468d4
commit
d689f8422f
@@ -42,11 +42,7 @@ func createStack(t *testing.T) *stack.Stack {
|
||||
|
||||
go func() {
|
||||
for pkt := range linkEP.C {
|
||||
v := make(buffer.View, len(pkt.Header)+len(pkt.Payload))
|
||||
copy(v, pkt.Header)
|
||||
copy(v[len(pkt.Header):], pkt.Payload)
|
||||
vv := v.ToVectorisedView([1]buffer.View{})
|
||||
linkEP.Inject(pkt.Proto, &vv)
|
||||
linkEP.Inject(pkt.Proto, buffer.NewVectorisedView(len(pkt.Header)+len(pkt.Payload), []buffer.View{pkt.Header, pkt.Payload}))
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -350,8 +350,7 @@ func (c *Conn) Write(b []byte) (int, error) {
|
||||
default:
|
||||
}
|
||||
|
||||
v := buffer.NewView(len(b))
|
||||
copy(v, b)
|
||||
v := buffer.NewViewFromBytes(b)
|
||||
|
||||
// We must handle two soft failure conditions simultaneously:
|
||||
// 1. Write may write nothing and return tcpip.ErrWouldBlock.
|
||||
|
||||
@@ -45,11 +45,9 @@ func (v *View) CapLength(length int) {
|
||||
*v = (*v)[:length:length]
|
||||
}
|
||||
|
||||
// ToVectorisedView transforms a View in a VectorisedView from an
|
||||
// already-allocated slice of View.
|
||||
func (v *View) ToVectorisedView(views [1]View) VectorisedView {
|
||||
views[0] = *v
|
||||
return NewVectorisedView(len(*v), views[:])
|
||||
// ToVectorisedView returns a VectorisedView containing the receiver.
|
||||
func (v View) ToVectorisedView() VectorisedView {
|
||||
return NewVectorisedView(len(v), []View{v})
|
||||
}
|
||||
|
||||
// VectorisedView is a vectorised version of View using non contigous memory.
|
||||
@@ -107,21 +105,12 @@ func (vv *VectorisedView) CapLength(length int) {
|
||||
// Clone returns a clone of this VectorisedView.
|
||||
// If the buffer argument is large enough to contain all the Views of this VectorisedView,
|
||||
// the method will avoid allocations and use the buffer to store the Views of the clone.
|
||||
func (vv *VectorisedView) Clone(buffer []View) VectorisedView {
|
||||
var views []View
|
||||
if len(buffer) >= len(vv.views) {
|
||||
views = buffer[:len(vv.views)]
|
||||
} else {
|
||||
views = make([]View, len(vv.views))
|
||||
}
|
||||
for i, v := range vv.views {
|
||||
views[i] = v
|
||||
}
|
||||
return VectorisedView{views: views, size: vv.size}
|
||||
func (vv VectorisedView) Clone(buffer []View) VectorisedView {
|
||||
return VectorisedView{views: append(buffer[:0], vv.views...), size: vv.size}
|
||||
}
|
||||
|
||||
// First returns the first view of the vectorised view.
|
||||
func (vv *VectorisedView) First() View {
|
||||
func (vv VectorisedView) First() View {
|
||||
if len(vv.views) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -137,23 +126,13 @@ func (vv *VectorisedView) RemoveFirst() {
|
||||
vv.views = vv.views[1:]
|
||||
}
|
||||
|
||||
// SetSize unsafely sets the size of the VectorisedView.
|
||||
func (vv *VectorisedView) SetSize(size int) {
|
||||
vv.size = size
|
||||
}
|
||||
|
||||
// SetViews unsafely sets the views of the VectorisedView.
|
||||
func (vv *VectorisedView) SetViews(views []View) {
|
||||
vv.views = views
|
||||
}
|
||||
|
||||
// Size returns the size in bytes of the entire content stored in the vectorised view.
|
||||
func (vv *VectorisedView) Size() int {
|
||||
func (vv VectorisedView) Size() int {
|
||||
return vv.size
|
||||
}
|
||||
|
||||
// ToView returns a single view containing the content of the vectorised view.
|
||||
func (vv *VectorisedView) ToView() View {
|
||||
func (vv VectorisedView) ToView() View {
|
||||
u := make([]byte, 0, vv.size)
|
||||
for _, v := range vv.views {
|
||||
u = append(u, v...)
|
||||
@@ -162,29 +141,6 @@ func (vv *VectorisedView) ToView() View {
|
||||
}
|
||||
|
||||
// Views returns the slice containing the all views.
|
||||
func (vv *VectorisedView) Views() []View {
|
||||
func (vv VectorisedView) Views() []View {
|
||||
return vv.views
|
||||
}
|
||||
|
||||
// ByteSlice returns a slice containing the all views as a []byte.
|
||||
func (vv *VectorisedView) ByteSlice() [][]byte {
|
||||
s := make([][]byte, len(vv.views))
|
||||
for i := range vv.views {
|
||||
s[i] = []byte(vv.views[i])
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// copy returns a deep-copy of the vectorised view.
|
||||
// It is an expensive method that should be used only in tests.
|
||||
func (vv *VectorisedView) copy() *VectorisedView {
|
||||
uu := &VectorisedView{
|
||||
views: make([]View, len(vv.views)),
|
||||
size: vv.size,
|
||||
}
|
||||
for i, v := range vv.views {
|
||||
uu.views[i] = make(View, len(v))
|
||||
copy(uu.views[i], v)
|
||||
}
|
||||
return uu
|
||||
}
|
||||
|
||||
@@ -20,22 +20,33 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// copy returns a deep-copy of the vectorised view.
|
||||
func (vv VectorisedView) copy() VectorisedView {
|
||||
uu := VectorisedView{
|
||||
views: make([]View, 0, len(vv.views)),
|
||||
size: vv.size,
|
||||
}
|
||||
for _, v := range vv.views {
|
||||
uu.views = append(uu.views, append(View(nil), v...))
|
||||
}
|
||||
return uu
|
||||
}
|
||||
|
||||
// vv is an helper to build VectorisedView from different strings.
|
||||
func vv(size int, pieces ...string) *VectorisedView {
|
||||
func vv(size int, pieces ...string) VectorisedView {
|
||||
views := make([]View, len(pieces))
|
||||
for i, p := range pieces {
|
||||
views[i] = []byte(p)
|
||||
}
|
||||
|
||||
vv := NewVectorisedView(size, views)
|
||||
return &vv
|
||||
return NewVectorisedView(size, views)
|
||||
}
|
||||
|
||||
var capLengthTestCases = []struct {
|
||||
comment string
|
||||
in *VectorisedView
|
||||
in VectorisedView
|
||||
length int
|
||||
want *VectorisedView
|
||||
want VectorisedView
|
||||
}{
|
||||
{
|
||||
comment: "Simple case",
|
||||
@@ -88,9 +99,9 @@ func TestCapLength(t *testing.T) {
|
||||
|
||||
var trimFrontTestCases = []struct {
|
||||
comment string
|
||||
in *VectorisedView
|
||||
in VectorisedView
|
||||
count int
|
||||
want *VectorisedView
|
||||
want VectorisedView
|
||||
}{
|
||||
{
|
||||
comment: "Simple case",
|
||||
@@ -149,7 +160,7 @@ func TestTrimFront(t *testing.T) {
|
||||
|
||||
var toViewCases = []struct {
|
||||
comment string
|
||||
in *VectorisedView
|
||||
in VectorisedView
|
||||
want View
|
||||
}{
|
||||
{
|
||||
@@ -181,7 +192,7 @@ func TestToView(t *testing.T) {
|
||||
|
||||
var toCloneCases = []struct {
|
||||
comment string
|
||||
inView *VectorisedView
|
||||
inView VectorisedView
|
||||
inBuffer []View
|
||||
}{
|
||||
{
|
||||
@@ -213,10 +224,12 @@ var toCloneCases = []struct {
|
||||
|
||||
func TestToClone(t *testing.T) {
|
||||
for _, c := range toCloneCases {
|
||||
got := c.inView.Clone(c.inBuffer)
|
||||
if !reflect.DeepEqual(&got, c.inView) {
|
||||
t.Errorf("Test \"%s\" failed when calling Clone(%v) on %v. Got %v. Want %v",
|
||||
c.comment, c.inBuffer, c.inView, got, c.inView)
|
||||
}
|
||||
t.Run(c.comment, func(t *testing.T) {
|
||||
got := c.inView.Clone(c.inBuffer)
|
||||
if !reflect.DeepEqual(got, c.inView) {
|
||||
t.Fatalf("got (%+v).Clone(%+v) = %+v, want = %+v",
|
||||
c.inView, c.inBuffer, got, c.inView)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,40 +39,52 @@ type TransportChecker func(*testing.T, header.Transport)
|
||||
//
|
||||
// checker.IPv4(t, b, checker.SrcAddr(x), checker.DstAddr(y))
|
||||
func IPv4(t *testing.T, b []byte, checkers ...NetworkChecker) {
|
||||
t.Helper()
|
||||
|
||||
ipv4 := header.IPv4(b)
|
||||
|
||||
if !ipv4.IsValid(len(b)) {
|
||||
t.Fatalf("Not a valid IPv4 packet")
|
||||
t.Error("Not a valid IPv4 packet")
|
||||
}
|
||||
|
||||
xsum := ipv4.CalculateChecksum()
|
||||
if xsum != 0 && xsum != 0xffff {
|
||||
t.Fatalf("Bad checksum: 0x%x, checksum in packet: 0x%x", xsum, ipv4.Checksum())
|
||||
t.Errorf("Bad checksum: 0x%x, checksum in packet: 0x%x", xsum, ipv4.Checksum())
|
||||
}
|
||||
|
||||
for _, f := range checkers {
|
||||
f(t, []header.Network{ipv4})
|
||||
}
|
||||
if t.Failed() {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// IPv6 checks the validity and properties of the given IPv6 packet. The usage
|
||||
// is similar to IPv4.
|
||||
func IPv6(t *testing.T, b []byte, checkers ...NetworkChecker) {
|
||||
t.Helper()
|
||||
|
||||
ipv6 := header.IPv6(b)
|
||||
if !ipv6.IsValid(len(b)) {
|
||||
t.Fatalf("Not a valid IPv6 packet")
|
||||
t.Error("Not a valid IPv6 packet")
|
||||
}
|
||||
|
||||
for _, f := range checkers {
|
||||
f(t, []header.Network{ipv6})
|
||||
}
|
||||
if t.Failed() {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// SrcAddr creates a checker that checks the source address.
|
||||
func SrcAddr(addr tcpip.Address) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if a := h[0].SourceAddress(); a != addr {
|
||||
t.Fatalf("Bad source address, got %v, want %v", a, addr)
|
||||
t.Errorf("Bad source address, got %v, want %v", a, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,8 +92,10 @@ func SrcAddr(addr tcpip.Address) NetworkChecker {
|
||||
// DstAddr creates a checker that checks the destination address.
|
||||
func DstAddr(addr tcpip.Address) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if a := h[0].DestinationAddress(); a != addr {
|
||||
t.Fatalf("Bad destination address, got %v, want %v", a, addr)
|
||||
t.Errorf("Bad destination address, got %v, want %v", a, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,8 +119,10 @@ func TTL(ttl uint8) NetworkChecker {
|
||||
// PayloadLen creates a checker that checks the payload length.
|
||||
func PayloadLen(plen int) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if l := len(h[0].Payload()); l != plen {
|
||||
t.Fatalf("Bad payload length, got %v, want %v", l, plen)
|
||||
t.Errorf("Bad payload length, got %v, want %v", l, plen)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,11 +130,13 @@ func PayloadLen(plen int) NetworkChecker {
|
||||
// FragmentOffset creates a checker that checks the FragmentOffset field.
|
||||
func FragmentOffset(offset uint16) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
// We only do this of IPv4 for now.
|
||||
switch ip := h[0].(type) {
|
||||
case header.IPv4:
|
||||
if v := ip.FragmentOffset(); v != offset {
|
||||
t.Fatalf("Bad fragment offset, got %v, want %v", v, offset)
|
||||
t.Errorf("Bad fragment offset, got %v, want %v", v, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,11 +145,13 @@ func FragmentOffset(offset uint16) NetworkChecker {
|
||||
// FragmentFlags creates a checker that checks the fragment flags field.
|
||||
func FragmentFlags(flags uint8) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
// We only do this of IPv4 for now.
|
||||
switch ip := h[0].(type) {
|
||||
case header.IPv4:
|
||||
if v := ip.Flags(); v != flags {
|
||||
t.Fatalf("Bad fragment offset, got %v, want %v", v, flags)
|
||||
t.Errorf("Bad fragment offset, got %v, want %v", v, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,8 +160,10 @@ func FragmentFlags(flags uint8) NetworkChecker {
|
||||
// TOS creates a checker that checks the TOS field.
|
||||
func TOS(tos uint8, label uint32) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if v, l := h[0].TOS(); v != tos || l != label {
|
||||
t.Fatalf("Bad TOS, got (%v, %v), want (%v,%v)", v, l, tos, label)
|
||||
t.Errorf("Bad TOS, got (%v, %v), want (%v,%v)", v, l, tos, label)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,8 +175,10 @@ func TOS(tos uint8, label uint32) NetworkChecker {
|
||||
// the bytes added by the IPv6 fragmentation.
|
||||
func Raw(want []byte) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if got := h[len(h)-1].Payload(); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("Wrong payload, got %v, want %v", got, want)
|
||||
t.Errorf("Wrong payload, got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,18 +186,23 @@ func Raw(want []byte) NetworkChecker {
|
||||
// IPv6Fragment creates a checker that validates an IPv6 fragment.
|
||||
func IPv6Fragment(checkers ...NetworkChecker) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
if p := h[0].TransportProtocol(); p != header.IPv6FragmentHeader {
|
||||
t.Fatalf("Bad protocol, got %v, want %v", p, header.UDPProtocolNumber)
|
||||
t.Errorf("Bad protocol, got %v, want %v", p, header.UDPProtocolNumber)
|
||||
}
|
||||
|
||||
ipv6Frag := header.IPv6Fragment(h[0].Payload())
|
||||
if !ipv6Frag.IsValid() {
|
||||
t.Fatalf("Not a valid IPv6 fragment")
|
||||
t.Error("Not a valid IPv6 fragment")
|
||||
}
|
||||
|
||||
for _, f := range checkers {
|
||||
f(t, []header.Network{h[0], ipv6Frag})
|
||||
}
|
||||
if t.Failed() {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,11 +210,13 @@ func IPv6Fragment(checkers ...NetworkChecker) NetworkChecker {
|
||||
// potentially additional transport header fields.
|
||||
func TCP(checkers ...TransportChecker) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
first := h[0]
|
||||
last := h[len(h)-1]
|
||||
|
||||
if p := last.TransportProtocol(); p != header.TCPProtocolNumber {
|
||||
t.Fatalf("Bad protocol, got %v, want %v", p, header.TCPProtocolNumber)
|
||||
t.Errorf("Bad protocol, got %v, want %v", p, header.TCPProtocolNumber)
|
||||
}
|
||||
|
||||
// Verify the checksum.
|
||||
@@ -199,13 +230,16 @@ func TCP(checkers ...TransportChecker) NetworkChecker {
|
||||
xsum = header.Checksum(tcp, xsum)
|
||||
|
||||
if xsum != 0 && xsum != 0xffff {
|
||||
t.Fatalf("Bad checksum: 0x%x, checksum in segment: 0x%x", xsum, tcp.Checksum())
|
||||
t.Errorf("Bad checksum: 0x%x, checksum in segment: 0x%x", xsum, tcp.Checksum())
|
||||
}
|
||||
|
||||
// Run the transport checkers.
|
||||
for _, f := range checkers {
|
||||
f(t, tcp)
|
||||
}
|
||||
if t.Failed() {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,24 +247,31 @@ func TCP(checkers ...TransportChecker) NetworkChecker {
|
||||
// potentially additional transport header fields.
|
||||
func UDP(checkers ...TransportChecker) NetworkChecker {
|
||||
return func(t *testing.T, h []header.Network) {
|
||||
t.Helper()
|
||||
|
||||
last := h[len(h)-1]
|
||||
|
||||
if p := last.TransportProtocol(); p != header.UDPProtocolNumber {
|
||||
t.Fatalf("Bad protocol, got %v, want %v", p, header.UDPProtocolNumber)
|
||||
t.Errorf("Bad protocol, got %v, want %v", p, header.UDPProtocolNumber)
|
||||
}
|
||||
|
||||
udp := header.UDP(last.Payload())
|
||||
for _, f := range checkers {
|
||||
f(t, udp)
|
||||
}
|
||||
if t.Failed() {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SrcPort creates a checker that checks the source port.
|
||||
func SrcPort(port uint16) TransportChecker {
|
||||
return func(t *testing.T, h header.Transport) {
|
||||
t.Helper()
|
||||
|
||||
if p := h.SourcePort(); p != port {
|
||||
t.Fatalf("Bad source port, got %v, want %v", p, port)
|
||||
t.Errorf("Bad source port, got %v, want %v", p, port)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +280,7 @@ func SrcPort(port uint16) TransportChecker {
|
||||
func DstPort(port uint16) TransportChecker {
|
||||
return func(t *testing.T, h header.Transport) {
|
||||
if p := h.DestinationPort(); p != port {
|
||||
t.Fatalf("Bad destination port, got %v, want %v", p, port)
|
||||
t.Errorf("Bad destination port, got %v, want %v", p, port)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,13 +288,15 @@ func DstPort(port uint16) TransportChecker {
|
||||
// SeqNum creates a checker that checks the sequence number.
|
||||
func SeqNum(seq uint32) TransportChecker {
|
||||
return func(t *testing.T, h header.Transport) {
|
||||
t.Helper()
|
||||
|
||||
tcp, ok := h.(header.TCP)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if s := tcp.SequenceNumber(); s != seq {
|
||||
t.Fatalf("Bad sequence number, got %v, want %v", s, seq)
|
||||
t.Errorf("Bad sequence number, got %v, want %v", s, seq)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,7 +311,7 @@ func AckNum(seq uint32) TransportChecker {
|
||||
}
|
||||
|
||||
if s := tcp.AckNumber(); s != seq {
|
||||
t.Fatalf("Bad ack number, got %v, want %v", s, seq)
|
||||
t.Errorf("Bad ack number, got %v, want %v", s, seq)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +325,7 @@ func Window(window uint16) TransportChecker {
|
||||
}
|
||||
|
||||
if w := tcp.WindowSize(); w != window {
|
||||
t.Fatalf("Bad window, got 0x%x, want 0x%x", w, window)
|
||||
t.Errorf("Bad window, got 0x%x, want 0x%x", w, window)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,13 +333,15 @@ func Window(window uint16) TransportChecker {
|
||||
// TCPFlags creates a checker that checks the tcp flags.
|
||||
func TCPFlags(flags uint8) TransportChecker {
|
||||
return func(t *testing.T, h header.Transport) {
|
||||
t.Helper()
|
||||
|
||||
tcp, ok := h.(header.TCP)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if f := tcp.Flags(); f != flags {
|
||||
t.Fatalf("Bad flags, got 0x%x, want 0x%x", f, flags)
|
||||
t.Errorf("Bad flags, got 0x%x, want 0x%x", f, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,7 +356,7 @@ func TCPFlagsMatch(flags, mask uint8) TransportChecker {
|
||||
}
|
||||
|
||||
if f := tcp.Flags(); (f & mask) != (flags & mask) {
|
||||
t.Fatalf("Bad masked flags, got 0x%x, want 0x%x, mask 0x%x", f, flags, mask)
|
||||
t.Errorf("Bad masked flags, got 0x%x, want 0x%x, mask 0x%x", f, flags, mask)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,26 +388,26 @@ func TCPSynOptions(wantOpts header.TCPSynOptions) TransportChecker {
|
||||
case header.TCPOptionMSS:
|
||||
v := uint16(opts[i+2])<<8 | uint16(opts[i+3])
|
||||
if wantOpts.MSS != v {
|
||||
t.Fatalf("Bad MSS: got %v, want %v", v, wantOpts.MSS)
|
||||
t.Errorf("Bad MSS: got %v, want %v", v, wantOpts.MSS)
|
||||
}
|
||||
foundMSS = true
|
||||
i += 4
|
||||
case header.TCPOptionWS:
|
||||
if wantOpts.WS < 0 {
|
||||
t.Fatalf("WS present when it shouldn't be")
|
||||
t.Error("WS present when it shouldn't be")
|
||||
}
|
||||
v := int(opts[i+2])
|
||||
if v != wantOpts.WS {
|
||||
t.Fatalf("Bad WS: got %v, want %v", v, wantOpts.WS)
|
||||
t.Errorf("Bad WS: got %v, want %v", v, wantOpts.WS)
|
||||
}
|
||||
foundWS = true
|
||||
i += 3
|
||||
case header.TCPOptionTS:
|
||||
if i+9 >= limit {
|
||||
t.Fatalf("TS Option truncated , option is only: %d bytes, want 10", limit-i)
|
||||
t.Errorf("TS Option truncated , option is only: %d bytes, want 10", limit-i)
|
||||
}
|
||||
if opts[i+1] != 10 {
|
||||
t.Fatalf("Bad length %d for TS option, limit: %d", opts[i+1], limit)
|
||||
t.Errorf("Bad length %d for TS option, limit: %d", opts[i+1], limit)
|
||||
}
|
||||
tsVal = binary.BigEndian.Uint32(opts[i+2:])
|
||||
tsEcr = uint32(0)
|
||||
@@ -375,10 +420,10 @@ func TCPSynOptions(wantOpts header.TCPSynOptions) TransportChecker {
|
||||
i += 10
|
||||
case header.TCPOptionSACKPermitted:
|
||||
if i+1 >= limit {
|
||||
t.Fatalf("SACKPermitted option truncated, option is only : %d bytes, want 2", limit-i)
|
||||
t.Errorf("SACKPermitted option truncated, option is only : %d bytes, want 2", limit-i)
|
||||
}
|
||||
if opts[i+1] != 2 {
|
||||
t.Fatalf("Bad length %d for SACKPermitted option, limit: %d", opts[i+1], limit)
|
||||
t.Errorf("Bad length %d for SACKPermitted option, limit: %d", opts[i+1], limit)
|
||||
}
|
||||
foundSACKPermitted = true
|
||||
i += 2
|
||||
@@ -389,23 +434,23 @@ func TCPSynOptions(wantOpts header.TCPSynOptions) TransportChecker {
|
||||
}
|
||||
|
||||
if !foundMSS {
|
||||
t.Fatalf("MSS option not found. Options: %x", opts)
|
||||
t.Errorf("MSS option not found. Options: %x", opts)
|
||||
}
|
||||
|
||||
if !foundWS && wantOpts.WS >= 0 {
|
||||
t.Fatalf("WS option not found. Options: %x", opts)
|
||||
t.Errorf("WS option not found. Options: %x", opts)
|
||||
}
|
||||
if wantOpts.TS && !foundTS {
|
||||
t.Fatalf("TS option not found. Options: %x", opts)
|
||||
t.Errorf("TS option not found. Options: %x", opts)
|
||||
}
|
||||
if foundTS && tsVal == 0 {
|
||||
t.Fatalf("TS option specified but the timestamp value is zero")
|
||||
t.Error("TS option specified but the timestamp value is zero")
|
||||
}
|
||||
if foundTS && tsEcr == 0 && wantOpts.TSEcr != 0 {
|
||||
t.Fatalf("TS option specified but TSEcr is incorrect: got %d, want: %d", tsEcr, wantOpts.TSEcr)
|
||||
t.Errorf("TS option specified but TSEcr is incorrect: got %d, want: %d", tsEcr, wantOpts.TSEcr)
|
||||
}
|
||||
if wantOpts.SACKPermitted && !foundSACKPermitted {
|
||||
t.Fatalf("SACKPermitted option not found. Options: %x", opts)
|
||||
t.Errorf("SACKPermitted option not found. Options: %x", opts)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,10 +480,10 @@ func TCPTimestampChecker(wantTS bool, wantTSVal uint32, wantTSEcr uint32) Transp
|
||||
i++
|
||||
case header.TCPOptionTS:
|
||||
if i+9 >= limit {
|
||||
t.Fatalf("TS option found, but option is truncated, option length: %d, want 10 bytes", limit-i)
|
||||
t.Errorf("TS option found, but option is truncated, option length: %d, want 10 bytes", limit-i)
|
||||
}
|
||||
if opts[i+1] != 10 {
|
||||
t.Fatalf("TS option found, but bad length specified: %d, want: 10", opts[i+1])
|
||||
t.Errorf("TS option found, but bad length specified: %d, want: 10", opts[i+1])
|
||||
}
|
||||
tsVal = binary.BigEndian.Uint32(opts[i+2:])
|
||||
tsEcr = binary.BigEndian.Uint32(opts[i+6:])
|
||||
@@ -458,13 +503,13 @@ func TCPTimestampChecker(wantTS bool, wantTSVal uint32, wantTSEcr uint32) Transp
|
||||
}
|
||||
|
||||
if wantTS != foundTS {
|
||||
t.Fatalf("TS Option mismatch: got TS= %v, want TS= %v", foundTS, wantTS)
|
||||
t.Errorf("TS Option mismatch: got TS= %v, want TS= %v", foundTS, wantTS)
|
||||
}
|
||||
if wantTS && wantTSVal != 0 && wantTSVal != tsVal {
|
||||
t.Fatalf("Timestamp value is incorrect: got: %d, want: %d", tsVal, wantTSVal)
|
||||
t.Errorf("Timestamp value is incorrect: got: %d, want: %d", tsVal, wantTSVal)
|
||||
}
|
||||
if wantTS && wantTSEcr != 0 && tsEcr != wantTSEcr {
|
||||
t.Fatalf("Timestamp Echo Reply is incorrect: got: %d, want: %d", tsEcr, wantTSEcr)
|
||||
t.Errorf("Timestamp Echo Reply is incorrect: got: %d, want: %d", tsEcr, wantTSEcr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,12 +542,12 @@ func TCPSACKBlockChecker(sackBlocks []header.SACKBlock) TransportChecker {
|
||||
case header.TCPOptionSACK:
|
||||
if i+2 > limit {
|
||||
// Malformed SACK block.
|
||||
t.Fatalf("malformed SACK option in options: %v", opts)
|
||||
t.Errorf("malformed SACK option in options: %v", opts)
|
||||
}
|
||||
sackOptionLen := int(opts[i+1])
|
||||
if i+sackOptionLen > limit || (sackOptionLen-2)%8 != 0 {
|
||||
// Malformed SACK block.
|
||||
t.Fatalf("malformed SACK option length in options: %v", opts)
|
||||
t.Errorf("malformed SACK option length in options: %v", opts)
|
||||
}
|
||||
numBlocks := sackOptionLen / 8
|
||||
for j := 0; j < numBlocks; j++ {
|
||||
@@ -528,7 +573,7 @@ func TCPSACKBlockChecker(sackBlocks []header.SACKBlock) TransportChecker {
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotSACKBlocks, sackBlocks) {
|
||||
t.Fatalf("SACKBlocks are not equal, got: %v, want: %v", gotSACKBlocks, sackBlocks)
|
||||
t.Errorf("SACKBlocks are not equal, got: %v, want: %v", gotSACKBlocks, sackBlocks)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -537,7 +582,7 @@ func TCPSACKBlockChecker(sackBlocks []header.SACKBlock) TransportChecker {
|
||||
func Payload(want []byte) TransportChecker {
|
||||
return func(t *testing.T, h header.Transport) {
|
||||
if got := h.Payload(); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("Wrong payload, got %v, want %v", got, want)
|
||||
t.Errorf("Wrong payload, got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,15 +66,13 @@ func (e *Endpoint) Drain() int {
|
||||
}
|
||||
|
||||
// Inject injects an inbound packet.
|
||||
func (e *Endpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
uu := vv.Clone(nil)
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, &uu)
|
||||
func (e *Endpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
e.InjectLinkAddr(protocol, "", vv)
|
||||
}
|
||||
|
||||
// InjectLinkAddr injects an inbound packet with a remote link address.
|
||||
func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remoteLinkAddr tcpip.LinkAddress, vv *buffer.VectorisedView) {
|
||||
uu := vv.Clone(nil)
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, protocol, &uu)
|
||||
func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remoteLinkAddr tcpip.LinkAddress, vv buffer.VectorisedView) {
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, protocol, vv.Clone(nil))
|
||||
}
|
||||
|
||||
// Attach saves the stack network-layer dispatcher for use later when packets
|
||||
|
||||
@@ -57,7 +57,6 @@ type endpoint struct {
|
||||
// its end of the communication pipe.
|
||||
closed func(*tcpip.Error)
|
||||
|
||||
vv *buffer.VectorisedView
|
||||
iovecs []syscall.Iovec
|
||||
views []buffer.View
|
||||
dispatcher stack.NetworkDispatcher
|
||||
@@ -118,8 +117,6 @@ func New(opts *Options) tcpip.LinkEndpointID {
|
||||
iovecs: make([]syscall.Iovec, len(BufConfig)),
|
||||
handleLocal: opts.HandleLocal,
|
||||
}
|
||||
vv := buffer.NewVectorisedView(0, e.views)
|
||||
e.vv = &vv
|
||||
return stack.RegisterLinkEndpoint(e)
|
||||
}
|
||||
|
||||
@@ -167,7 +164,7 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload
|
||||
views[0] = hdr.View()
|
||||
views = append(views, payload.Views()...)
|
||||
vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
|
||||
e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, protocol, &vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, protocol, vv)
|
||||
return nil
|
||||
}
|
||||
if e.hdrSize > 0 {
|
||||
@@ -246,11 +243,10 @@ func (e *endpoint) dispatch(largeV buffer.View) (bool, *tcpip.Error) {
|
||||
}
|
||||
|
||||
used := e.capViews(n, BufConfig)
|
||||
e.vv.SetViews(e.views[:used])
|
||||
e.vv.SetSize(n)
|
||||
e.vv.TrimFront(e.hdrSize)
|
||||
vv := buffer.NewVectorisedView(n, e.views[:used])
|
||||
vv.TrimFront(e.hdrSize)
|
||||
|
||||
e.dispatcher.DeliverNetworkPacket(e, addr, p, e.vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, addr, p, vv)
|
||||
|
||||
// Prepare e.views for another packet: release used views.
|
||||
for i := 0; i < used; i++ {
|
||||
@@ -290,7 +286,7 @@ func (e *InjectableEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
|
||||
}
|
||||
|
||||
// Inject injects an inbound packet.
|
||||
func (e *InjectableEndpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (e *InjectableEndpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, vv)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func (c *context) cleanup() {
|
||||
syscall.Close(c.fds[1])
|
||||
}
|
||||
|
||||
func (c *context) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (c *context) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
c.ch <- packetInfo{remoteLinkAddr, protocol, vv.ToView()}
|
||||
}
|
||||
|
||||
@@ -158,8 +158,7 @@ func TestWritePacket(t *testing.T) {
|
||||
payload[i] = uint8(rand.Intn(256))
|
||||
}
|
||||
want := append(hdr.UsedBytes(), payload...)
|
||||
vv := buffer.NewVectorisedView(len(payload), []buffer.View{payload})
|
||||
if err := c.ep.WritePacket(r, &hdr, vv, proto); err != nil {
|
||||
if err := c.ep.WritePacket(r, &hdr, payload.ToVectorisedView(), proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func (e *endpoint) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload
|
||||
views[0] = hdr.View()
|
||||
views = append(views, payload.Views()...)
|
||||
vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, &vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, vv)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -227,8 +227,6 @@ func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) {
|
||||
|
||||
// Read in a loop until a stop is requested.
|
||||
var rxb []queue.RxBuffer
|
||||
views := []buffer.View{nil}
|
||||
vv := buffer.NewVectorisedView(0, views)
|
||||
for atomic.LoadUint32(&e.stopRequested) == 0 {
|
||||
var n uint32
|
||||
rxb, n = e.rx.postAndReceive(rxb, &e.stopRequested)
|
||||
@@ -250,9 +248,7 @@ func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) {
|
||||
|
||||
// Send packet up the stack.
|
||||
eth := header.Ethernet(b)
|
||||
views[0] = b[header.EthernetMinimumSize:]
|
||||
vv.SetSize(int(n) - header.EthernetMinimumSize)
|
||||
d.DeliverNetworkPacket(e, eth.SourceAddress(), eth.Type(), &vv)
|
||||
d.DeliverNetworkPacket(e, eth.SourceAddress(), eth.Type(), buffer.View(b[header.EthernetMinimumSize:]).ToVectorisedView())
|
||||
}
|
||||
|
||||
// Clean state.
|
||||
|
||||
@@ -129,7 +129,7 @@ func newTestContext(t *testing.T, mtu, bufferSize uint32, addr tcpip.LinkAddress
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *testContext) DeliverNetworkPacket(_ stack.LinkEndpoint, remoteAddr tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (c *testContext) DeliverNetworkPacket(_ stack.LinkEndpoint, remoteAddr tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
c.mu.Lock()
|
||||
c.packets = append(c.packets, packetInfo{
|
||||
addr: remoteAddr,
|
||||
@@ -270,8 +270,7 @@ func TestSimpleSend(t *testing.T) {
|
||||
randomFill(buf)
|
||||
|
||||
proto := tcpip.NetworkProtocolNumber(rand.Intn(0x10000))
|
||||
vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf})
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, proto); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -330,7 +329,6 @@ func TestFillTxQueue(t *testing.T) {
|
||||
}
|
||||
|
||||
buf := buffer.NewView(100)
|
||||
vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf})
|
||||
|
||||
// Each packet is uses no more than 40 bytes, so write that many packets
|
||||
// until the tx queue if full.
|
||||
@@ -338,7 +336,7 @@ func TestFillTxQueue(t *testing.T) {
|
||||
for i := queuePipeSize / 40; i > 0; i-- {
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
|
||||
@@ -353,7 +351,7 @@ func TestFillTxQueue(t *testing.T) {
|
||||
|
||||
// Next attempt to write must fail.
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != want {
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != want {
|
||||
t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -374,12 +372,11 @@ func TestFillTxQueueAfterBadCompletion(t *testing.T) {
|
||||
}
|
||||
|
||||
buf := buffer.NewView(100)
|
||||
vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf})
|
||||
|
||||
// Send two packets so that the id slice has at least two slots.
|
||||
for i := 2; i > 0; i-- {
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -399,7 +396,7 @@ func TestFillTxQueueAfterBadCompletion(t *testing.T) {
|
||||
ids := make(map[uint64]struct{})
|
||||
for i := queuePipeSize / 40; i > 0; i-- {
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
|
||||
@@ -414,7 +411,7 @@ func TestFillTxQueueAfterBadCompletion(t *testing.T) {
|
||||
|
||||
// Next attempt to write must fail.
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != want {
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != want {
|
||||
t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -431,14 +428,13 @@ func TestFillTxMemory(t *testing.T) {
|
||||
}
|
||||
|
||||
buf := buffer.NewView(100)
|
||||
vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf})
|
||||
|
||||
// Each packet is uses up one buffer, so write as many as possible until
|
||||
// we fill the memory.
|
||||
ids := make(map[uint64]struct{})
|
||||
for i := queueDataSize / bufferSize; i > 0; i-- {
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
|
||||
@@ -454,7 +450,7 @@ func TestFillTxMemory(t *testing.T) {
|
||||
|
||||
// Next attempt to write must fail.
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber)
|
||||
err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber)
|
||||
if want := tcpip.ErrWouldBlock; err != want {
|
||||
t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want)
|
||||
}
|
||||
@@ -474,13 +470,12 @@ func TestFillTxMemoryWithMultiBuffer(t *testing.T) {
|
||||
}
|
||||
|
||||
buf := buffer.NewView(100)
|
||||
vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf})
|
||||
|
||||
// Each packet is uses up one buffer, so write as many as possible
|
||||
// until there is only one buffer left.
|
||||
for i := queueDataSize/bufferSize - 1; i > 0; i-- {
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
|
||||
@@ -490,20 +485,26 @@ func TestFillTxMemoryWithMultiBuffer(t *testing.T) {
|
||||
}
|
||||
|
||||
// Attempt to write a two-buffer packet. It must fail.
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
uu := buffer.NewVectorisedView(bufferSize, []buffer.View{buffer.NewView(bufferSize)})
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, uu, header.IPv4ProtocolNumber); err != want {
|
||||
t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want)
|
||||
{
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
uu := buffer.NewView(bufferSize).ToVectorisedView()
|
||||
if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, uu, header.IPv4ProtocolNumber); err != want {
|
||||
t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to write the one-buffer packet again. It must succeed.
|
||||
hdr = buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
{
|
||||
hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength()))
|
||||
if err := c.ep.WritePacket(&r, &hdr, buf.ToVectorisedView(), header.IPv4ProtocolNumber); err != nil {
|
||||
t.Fatalf("WritePacket failed unexpectedly: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pollPull(t *testing.T, p *pipe.Rx, to <-chan time.Time, errStr string) []byte {
|
||||
t.Helper()
|
||||
|
||||
for {
|
||||
b := p.Pull()
|
||||
if b != nil {
|
||||
@@ -513,7 +514,7 @@ func pollPull(t *testing.T, p *pipe.Rx, to <-chan time.Time, errStr string) []by
|
||||
select {
|
||||
case <-time.After(10 * time.Millisecond):
|
||||
case <-to:
|
||||
t.Fatalf(errStr)
|
||||
t.Fatal(errStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func NewWithFile(lower tcpip.LinkEndpointID, file *os.File, snapLen uint32) (tcp
|
||||
// DeliverNetworkPacket implements the stack.NetworkDispatcher interface. It is
|
||||
// called by the link-layer endpoint being wrapped when a packet arrives, and
|
||||
// logs the packet before forwarding to the actual dispatcher.
|
||||
func (e *endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (e *endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
if atomic.LoadUint32(&LogPackets) == 1 && e.file == nil {
|
||||
logPacket("recv", protocol, vv.First())
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func New(lower tcpip.LinkEndpointID) (tcpip.LinkEndpointID, *Endpoint) {
|
||||
// It is called by the link-layer endpoint being wrapped when a packet arrives,
|
||||
// and only forwards to the actual dispatcher if Wait or WaitDispatch haven't
|
||||
// been called.
|
||||
func (e *Endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (e *Endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
if !e.dispatchGate.Enter() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ type countedEndpoint struct {
|
||||
dispatcher stack.NetworkDispatcher
|
||||
}
|
||||
|
||||
func (e *countedEndpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||
func (e *countedEndpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
e.dispatchCount++
|
||||
}
|
||||
|
||||
@@ -106,21 +106,21 @@ func TestWaitDispatch(t *testing.T) {
|
||||
}
|
||||
|
||||
// Dispatch and check that it goes through.
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, nil)
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
if want := 1; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
// Wait on writes, then try to dispatch. It must go through.
|
||||
wep.WaitWrite()
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, nil)
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
if want := 2; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
// Wait on dispatches, then try to dispatch. It must not go through.
|
||||
wep.WaitDispatch()
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, nil)
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
if want := 2; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload
|
||||
return tcpip.ErrNotSupported
|
||||
}
|
||||
|
||||
func (e *endpoint) HandlePacket(r *stack.Route, vv *buffer.VectorisedView) {
|
||||
func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
|
||||
v := vv.First()
|
||||
h := header.ARP(v)
|
||||
if !h.IsValid() {
|
||||
|
||||
@@ -96,54 +96,54 @@ func TestDirectRequest(t *testing.T) {
|
||||
copy(h.HardwareAddressSender(), senderMAC)
|
||||
copy(h.ProtocolAddressSender(), senderIPv4)
|
||||
|
||||
// stackAddr1
|
||||
copy(h.ProtocolAddressTarget(), stackAddr1)
|
||||
vv := v.ToVectorisedView([1]buffer.View{})
|
||||
c.linkEP.Inject(arp.ProtocolNumber, &vv)
|
||||
pkt := <-c.linkEP.C
|
||||
if pkt.Proto != arp.ProtocolNumber {
|
||||
t.Fatalf("stackAddr1: expected ARP response, got network protocol number %v", pkt.Proto)
|
||||
}
|
||||
rep := header.ARP(pkt.Header)
|
||||
if !rep.IsValid() {
|
||||
t.Fatalf("stackAddr1: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
|
||||
}
|
||||
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr1 {
|
||||
t.Errorf("stackAddr1: expected sender to be set")
|
||||
}
|
||||
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
|
||||
t.Errorf("stackAddr1: expected sender to be stackLinkAddr, got %q", got)
|
||||
inject := func(addr tcpip.Address) {
|
||||
copy(h.ProtocolAddressTarget(), addr)
|
||||
c.linkEP.Inject(arp.ProtocolNumber, v.ToVectorisedView())
|
||||
}
|
||||
|
||||
// stackAddr2
|
||||
copy(h.ProtocolAddressTarget(), stackAddr2)
|
||||
vv = v.ToVectorisedView([1]buffer.View{})
|
||||
c.linkEP.Inject(arp.ProtocolNumber, &vv)
|
||||
pkt = <-c.linkEP.C
|
||||
if pkt.Proto != arp.ProtocolNumber {
|
||||
t.Fatalf("stackAddr2: expected ARP response, got network protocol number %v", pkt.Proto)
|
||||
}
|
||||
rep = header.ARP(pkt.Header)
|
||||
if !rep.IsValid() {
|
||||
t.Fatalf("stackAddr2: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
|
||||
}
|
||||
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr2 {
|
||||
t.Errorf("stackAddr2: expected sender to be set")
|
||||
}
|
||||
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
|
||||
t.Errorf("stackAddr2: expected sender to be stackLinkAddr, got %q", got)
|
||||
inject(stackAddr1)
|
||||
{
|
||||
pkt := <-c.linkEP.C
|
||||
if pkt.Proto != arp.ProtocolNumber {
|
||||
t.Fatalf("stackAddr1: expected ARP response, got network protocol number %v", pkt.Proto)
|
||||
}
|
||||
rep := header.ARP(pkt.Header)
|
||||
if !rep.IsValid() {
|
||||
t.Fatalf("stackAddr1: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
|
||||
}
|
||||
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr1 {
|
||||
t.Errorf("stackAddr1: expected sender to be set")
|
||||
}
|
||||
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
|
||||
t.Errorf("stackAddr1: expected sender to be stackLinkAddr, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
// stackAddrBad
|
||||
copy(h.ProtocolAddressTarget(), stackAddrBad)
|
||||
vv = v.ToVectorisedView([1]buffer.View{})
|
||||
c.linkEP.Inject(arp.ProtocolNumber, &vv)
|
||||
inject(stackAddr2)
|
||||
{
|
||||
pkt := <-c.linkEP.C
|
||||
if pkt.Proto != arp.ProtocolNumber {
|
||||
t.Fatalf("stackAddr2: expected ARP response, got network protocol number %v", pkt.Proto)
|
||||
}
|
||||
rep := header.ARP(pkt.Header)
|
||||
if !rep.IsValid() {
|
||||
t.Fatalf("stackAddr2: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
|
||||
}
|
||||
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr2 {
|
||||
t.Errorf("stackAddr2: expected sender to be set")
|
||||
}
|
||||
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
|
||||
t.Errorf("stackAddr2: expected sender to be stackLinkAddr, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
inject(stackAddrBad)
|
||||
select {
|
||||
case pkt := <-c.linkEP.C:
|
||||
t.Errorf("stackAddrBad: unexpected packet sent, Proto=%v", pkt.Proto)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
// Sleep tests are gross, but this will only
|
||||
// potentially fail flakily if there's a bugj
|
||||
// If there is no bug this will reliably succeed.
|
||||
// Sleep tests are gross, but this will only potentially flake
|
||||
// if there's a bug. If there is no bug this will reliably
|
||||
// succeed.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
type fragment struct {
|
||||
offset uint16
|
||||
vv *buffer.VectorisedView
|
||||
vv buffer.VectorisedView
|
||||
}
|
||||
|
||||
type fragHeap []fragment
|
||||
@@ -60,7 +60,7 @@ func (h *fragHeap) reassemble() (buffer.VectorisedView, error) {
|
||||
size := curr.vv.Size()
|
||||
|
||||
if curr.offset != 0 {
|
||||
return buffer.NewVectorisedView(0, nil), fmt.Errorf("offset of the first packet is != 0 (%d)", curr.offset)
|
||||
return buffer.VectorisedView{}, fmt.Errorf("offset of the first packet is != 0 (%d)", curr.offset)
|
||||
}
|
||||
|
||||
for h.Len() > 0 {
|
||||
@@ -68,7 +68,7 @@ func (h *fragHeap) reassemble() (buffer.VectorisedView, error) {
|
||||
if int(curr.offset) < size {
|
||||
curr.vv.TrimFront(size - int(curr.offset))
|
||||
} else if int(curr.offset) > size {
|
||||
return buffer.NewVectorisedView(0, nil), fmt.Errorf("packet has a hole, expected offset %d, got %d", size, curr.offset)
|
||||
return buffer.VectorisedView{}, fmt.Errorf("packet has a hole, expected offset %d, got %d", size, curr.offset)
|
||||
}
|
||||
size += curr.vv.Size()
|
||||
views = append(views, curr.vv.Views()...)
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
var reassambleTestCases = []struct {
|
||||
comment string
|
||||
in []fragment
|
||||
want *buffer.VectorisedView
|
||||
want buffer.VectorisedView
|
||||
}{
|
||||
{
|
||||
comment: "Non-overlapping in-order",
|
||||
@@ -87,21 +87,25 @@ var reassambleTestCases = []struct {
|
||||
|
||||
func TestReassamble(t *testing.T) {
|
||||
for _, c := range reassambleTestCases {
|
||||
h := (fragHeap)(make([]fragment, 0, 8))
|
||||
heap.Init(&h)
|
||||
for _, f := range c.in {
|
||||
heap.Push(&h, f)
|
||||
}
|
||||
got, _ := h.reassemble()
|
||||
|
||||
if !reflect.DeepEqual(got, *c.want) {
|
||||
t.Errorf("Test \"%s\" reassembling failed. Got %v. Want %v", c.comment, got, *c.want)
|
||||
}
|
||||
t.Run(c.comment, func(t *testing.T) {
|
||||
h := make(fragHeap, 0, 8)
|
||||
heap.Init(&h)
|
||||
for _, f := range c.in {
|
||||
heap.Push(&h, f)
|
||||
}
|
||||
got, err := h.reassemble()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, c.want) {
|
||||
t.Errorf("got reassemble(%+v) = %v, want = %v", c.in, got, c.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReassambleFailsForNonZeroOffset(t *testing.T) {
|
||||
h := (fragHeap)(make([]fragment, 0, 8))
|
||||
h := make(fragHeap, 0, 8)
|
||||
heap.Init(&h)
|
||||
heap.Push(&h, fragment{offset: 1, vv: vv(1, "0")})
|
||||
_, err := h.reassemble()
|
||||
@@ -111,7 +115,7 @@ func TestReassambleFailsForNonZeroOffset(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReassambleFailsForHoles(t *testing.T) {
|
||||
h := (fragHeap)(make([]fragment, 0, 8))
|
||||
h := make(fragHeap, 0, 8)
|
||||
heap.Init(&h)
|
||||
heap.Push(&h, fragment{offset: 0, vv: vv(1, "0")})
|
||||
heap.Push(&h, fragment{offset: 2, vv: vv(1, "1")})
|
||||
|
||||
@@ -82,7 +82,7 @@ func NewFragmentation(highMemoryLimit, lowMemoryLimit int, reassemblingTimeout t
|
||||
|
||||
// Process processes an incoming fragment beloning to an ID
|
||||
// and returns a complete packet when all the packets belonging to that ID have been received.
|
||||
func (f *Fragmentation) Process(id uint32, first, last uint16, more bool, vv *buffer.VectorisedView) (buffer.VectorisedView, bool) {
|
||||
func (f *Fragmentation) Process(id uint32, first, last uint16, more bool, vv buffer.VectorisedView) (buffer.VectorisedView, bool) {
|
||||
f.mu.Lock()
|
||||
r, ok := f.reassemblers[id]
|
||||
if ok && r.tooOld(f.timeout) {
|
||||
|
||||
@@ -23,19 +23,13 @@ import (
|
||||
)
|
||||
|
||||
// vv is a helper to build VectorisedView from different strings.
|
||||
func vv(size int, pieces ...string) *buffer.VectorisedView {
|
||||
func vv(size int, pieces ...string) buffer.VectorisedView {
|
||||
views := make([]buffer.View, len(pieces))
|
||||
for i, p := range pieces {
|
||||
views[i] = []byte(p)
|
||||
}
|
||||
|
||||
vv := buffer.NewVectorisedView(size, views)
|
||||
return &vv
|
||||
}
|
||||
|
||||
func emptyVv() *buffer.VectorisedView {
|
||||
vv := buffer.NewVectorisedView(0, nil)
|
||||
return &vv
|
||||
return buffer.NewVectorisedView(size, views)
|
||||
}
|
||||
|
||||
type processInput struct {
|
||||
@@ -43,11 +37,11 @@ type processInput struct {
|
||||
first uint16
|
||||
last uint16
|
||||
more bool
|
||||
vv *buffer.VectorisedView
|
||||
vv buffer.VectorisedView
|
||||
}
|
||||
|
||||
type processOutput struct {
|
||||
vv *buffer.VectorisedView
|
||||
vv buffer.VectorisedView
|
||||
done bool
|
||||
}
|
||||
|
||||
@@ -63,7 +57,7 @@ var processTestCases = []struct {
|
||||
{id: 0, first: 2, last: 3, more: false, vv: vv(2, "23")},
|
||||
},
|
||||
out: []processOutput{
|
||||
{vv: emptyVv(), done: false},
|
||||
{vv: buffer.VectorisedView{}, done: false},
|
||||
{vv: vv(4, "01", "23"), done: true},
|
||||
},
|
||||
},
|
||||
@@ -76,8 +70,8 @@ var processTestCases = []struct {
|
||||
{id: 0, first: 2, last: 3, more: false, vv: vv(2, "23")},
|
||||
},
|
||||
out: []processOutput{
|
||||
{vv: emptyVv(), done: false},
|
||||
{vv: emptyVv(), done: false},
|
||||
{vv: buffer.VectorisedView{}, done: false},
|
||||
{vv: buffer.VectorisedView{}, done: false},
|
||||
{vv: vv(4, "ab", "cd"), done: true},
|
||||
{vv: vv(4, "01", "23"), done: true},
|
||||
},
|
||||
@@ -86,26 +80,28 @@ var processTestCases = []struct {
|
||||
|
||||
func TestFragmentationProcess(t *testing.T) {
|
||||
for _, c := range processTestCases {
|
||||
f := NewFragmentation(1024, 512, DefaultReassembleTimeout)
|
||||
for i, in := range c.in {
|
||||
vv, done := f.Process(in.id, in.first, in.last, in.more, in.vv)
|
||||
if !reflect.DeepEqual(vv, *(c.out[i].vv)) {
|
||||
t.Errorf("Test \"%s\" Process() returned a wrong vv. Got %v. Want %v", c.comment, vv, *(c.out[i].vv))
|
||||
}
|
||||
if done != c.out[i].done {
|
||||
t.Errorf("Test \"%s\" Process() returned a wrong done. Got %t. Want %t", c.comment, done, c.out[i].done)
|
||||
}
|
||||
if c.out[i].done {
|
||||
if _, ok := f.reassemblers[in.id]; ok {
|
||||
t.Errorf("Test \"%s\" Process() didn't remove buffer from reassemblers.", c.comment)
|
||||
t.Run(c.comment, func(t *testing.T) {
|
||||
f := NewFragmentation(1024, 512, DefaultReassembleTimeout)
|
||||
for i, in := range c.in {
|
||||
vv, done := f.Process(in.id, in.first, in.last, in.more, in.vv)
|
||||
if !reflect.DeepEqual(vv, c.out[i].vv) {
|
||||
t.Errorf("got Process(%d) = %+v, want = %+v", i, vv, c.out[i].vv)
|
||||
}
|
||||
for n := f.rList.Front(); n != nil; n = n.Next() {
|
||||
if n.id == in.id {
|
||||
t.Errorf("Test \"%s\" Process() didn't remove buffer from rList.", c.comment)
|
||||
if done != c.out[i].done {
|
||||
t.Errorf("got Process(%d) = %+v, want = %+v", i, done, c.out[i].done)
|
||||
}
|
||||
if c.out[i].done {
|
||||
if _, ok := f.reassemblers[in.id]; ok {
|
||||
t.Errorf("Process(%d) did not remove buffer from reassemblers", i)
|
||||
}
|
||||
for n := f.rList.Front(); n != nil; n = n.Next() {
|
||||
if n.id == in.id {
|
||||
t.Errorf("Process(%d) did not remove buffer from rList", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,16 +157,3 @@ func TestMemoryLimitsIgnoresDuplicates(t *testing.T) {
|
||||
t.Errorf("Wrong size, duplicates are not handled correctly: got=%d, want=%d.", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFragmentationViewsDoNotEscape(t *testing.T) {
|
||||
f := NewFragmentation(1024, 512, DefaultReassembleTimeout)
|
||||
in := vv(2, "0", "1")
|
||||
f.Process(0, 0, 1, true, in)
|
||||
// Modify input view.
|
||||
in.RemoveFirst()
|
||||
got, _ := f.Process(0, 2, 2, false, vv(1, "2"))
|
||||
want := vv(3, "0", "1", "2")
|
||||
if !reflect.DeepEqual(got, *want) {
|
||||
t.Errorf("Process() returned a wrong vv. Got %v. Want %v", got, *want)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user