diff options
Diffstat (limited to 'pkg/tcpip')
26 files changed, 137 insertions, 143 deletions
diff --git a/pkg/tcpip/buffer/view.go b/pkg/tcpip/buffer/view.go index 85ae38ac8..d151b8cf0 100644 --- a/pkg/tcpip/buffer/view.go +++ b/pkg/tcpip/buffer/view.go @@ -152,7 +152,7 @@ func (vv *VectorisedView) Size() int { return vv.size } -// ToView returns the a single view containing the content of the vectorised view. +// ToView returns a single view containing the content of the vectorised view. func (vv *VectorisedView) ToView() View { v := make([]byte, vv.size) u := v diff --git a/pkg/tcpip/link/channel/channel.go b/pkg/tcpip/link/channel/channel.go index dd3fe7c87..6983fae3f 100644 --- a/pkg/tcpip/link/channel/channel.go +++ b/pkg/tcpip/link/channel/channel.go @@ -111,15 +111,11 @@ func (e *Endpoint) LinkAddress() tcpip.LinkAddress { } // WritePacket stores outbound packets into the channel. -func (e *Endpoint) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *Endpoint) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { p := PacketInfo{ - Header: hdr.View(), - Proto: protocol, - } - - if payload != nil { - p.Payload = make(buffer.View, len(payload)) - copy(p.Payload, payload) + Header: hdr.View(), + Proto: protocol, + Payload: payload.ToView(), } select { diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go index 449acdfdd..12c249c0d 100644 --- a/pkg/tcpip/link/fdbased/endpoint.go +++ b/pkg/tcpip/link/fdbased/endpoint.go @@ -161,10 +161,12 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket writes outbound packets to the file descriptor. If it is not // currently writable, the packet is dropped. -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { if e.handleLocal && r.LocalAddress != "" && r.LocalAddress == r.RemoteAddress { - hdrView := hdr.View() - vv := buffer.NewVectorisedView(len(hdrView)+len(payload), []buffer.View{hdrView, payload}) + views := make([]buffer.View, 1, 1+len(payload.Views())) + 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) return nil } @@ -178,11 +180,11 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload }) } - if len(payload) == 0 { + if payload.Size() == 0 { return rawfile.NonBlockingWrite(e.fd, hdr.UsedBytes()) } - return rawfile.NonBlockingWrite2(e.fd, hdr.UsedBytes(), payload) + return rawfile.NonBlockingWrite2(e.fd, hdr.UsedBytes(), payload.ToView()) } func (e *endpoint) capViews(n int, buffers []int) int { diff --git a/pkg/tcpip/link/fdbased/endpoint_test.go b/pkg/tcpip/link/fdbased/endpoint_test.go index 89e791543..408169bbe 100644 --- a/pkg/tcpip/link/fdbased/endpoint_test.go +++ b/pkg/tcpip/link/fdbased/endpoint_test.go @@ -152,13 +152,14 @@ func TestWritePacket(t *testing.T) { b[i] = uint8(rand.Intn(256)) } - // Buiild payload and write. - payload := make([]byte, plen) + // Build payload and write. + payload := make(buffer.View, plen) for i := range payload { payload[i] = uint8(rand.Intn(256)) } want := append(hdr.UsedBytes(), payload...) - if err := c.ep.WritePacket(r, &hdr, payload, proto); err != nil { + vv := buffer.NewVectorisedView(len(payload), []buffer.View{payload}) + if err := c.ep.WritePacket(r, &hdr, vv, proto); err != nil { t.Fatalf("WritePacket failed: %v", err) } diff --git a/pkg/tcpip/link/loopback/loopback.go b/pkg/tcpip/link/loopback/loopback.go index 015275721..4a750fa12 100644 --- a/pkg/tcpip/link/loopback/loopback.go +++ b/pkg/tcpip/link/loopback/loopback.go @@ -72,18 +72,12 @@ func (*endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket implements stack.LinkEndpoint.WritePacket. It delivers outbound // packets to the network-layer dispatcher. -func (e *endpoint) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { - if len(payload) == 0 { - // We don't have a payload, so just use the buffer from the - // header as the full packet. - v := hdr.View() - vv := v.ToVectorisedView([1]buffer.View{}) - e.dispatcher.DeliverNetworkPacket(e, "", protocol, &vv) - } else { - views := []buffer.View{hdr.View(), payload} - vv := buffer.NewVectorisedView(len(views[0])+len(views[1]), views) - e.dispatcher.DeliverNetworkPacket(e, "", protocol, &vv) - } +func (e *endpoint) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { + views := make([]buffer.View, 1, 1+len(payload.Views())) + views[0] = hdr.View() + views = append(views, payload.Views()...) + vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views) + e.dispatcher.DeliverNetworkPacket(e, "", protocol, &vv) return nil } diff --git a/pkg/tcpip/link/sharedmem/sharedmem.go b/pkg/tcpip/link/sharedmem/sharedmem.go index 824cab093..6bd5441f6 100644 --- a/pkg/tcpip/link/sharedmem/sharedmem.go +++ b/pkg/tcpip/link/sharedmem/sharedmem.go @@ -184,7 +184,7 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket writes outbound packets to the file descriptor. If it is not // currently writable, the packet is dropped. -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { // Add the ethernet header here. eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize)) eth.Encode(&header.EthernetFields{ @@ -193,9 +193,10 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload Type: protocol, }) + v := payload.ToView() // Transmit the packet. e.mu.Lock() - ok := e.tx.transmit(hdr.UsedBytes(), payload) + ok := e.tx.transmit(hdr.UsedBytes(), v) e.mu.Unlock() if !ok { diff --git a/pkg/tcpip/link/sharedmem/sharedmem_test.go b/pkg/tcpip/link/sharedmem/sharedmem_test.go index 1e229279a..69d4ef29f 100644 --- a/pkg/tcpip/link/sharedmem/sharedmem_test.go +++ b/pkg/tcpip/link/sharedmem/sharedmem_test.go @@ -270,8 +270,8 @@ func TestSimpleSend(t *testing.T) { randomFill(buf) proto := tcpip.NetworkProtocolNumber(rand.Intn(0x10000)) - err := c.ep.WritePacket(&r, &hdr, buf, proto) - if err != nil { + vv := buffer.NewVectorisedView(len(buf), []buffer.View{buf}) + if err := c.ep.WritePacket(&r, &hdr, vv, proto); err != nil { t.Fatalf("WritePacket failed: %v", err) } @@ -330,13 +330,15 @@ 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. 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, buf, header.IPv4ProtocolNumber); err != nil { + + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } @@ -351,8 +353,7 @@ func TestFillTxQueue(t *testing.T) { // Next attempt to write must fail. hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength())) - err := c.ep.WritePacket(&r, &hdr, buf, header.IPv4ProtocolNumber) - if want := tcpip.ErrWouldBlock; err != want { + if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != want { t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want) } } @@ -373,11 +374,12 @@ 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, buf, header.IPv4ProtocolNumber); err != nil { + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } } @@ -397,7 +399,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, buf, header.IPv4ProtocolNumber); err != nil { + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } @@ -412,8 +414,7 @@ func TestFillTxQueueAfterBadCompletion(t *testing.T) { // Next attempt to write must fail. hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength())) - err := c.ep.WritePacket(&r, &hdr, buf, header.IPv4ProtocolNumber) - if want := tcpip.ErrWouldBlock; err != want { + if want, err := tcpip.ErrWouldBlock, c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != want { t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want) } } @@ -430,13 +431,14 @@ 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, buf, header.IPv4ProtocolNumber); err != nil { + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } @@ -452,7 +454,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, buf, header.IPv4ProtocolNumber) + err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber) if want := tcpip.ErrWouldBlock; err != want { t.Fatalf("WritePacket return unexpected result: got %v, want %v", err, want) } @@ -472,12 +474,13 @@ 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, buf, header.IPv4ProtocolNumber); err != nil { + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } @@ -488,14 +491,14 @@ func TestFillTxMemoryWithMultiBuffer(t *testing.T) { // Attempt to write a two-buffer packet. It must fail. hdr := buffer.NewPrependable(int(c.ep.MaxHeaderLength())) - err := c.ep.WritePacket(&r, &hdr, buffer.NewView(bufferSize), header.IPv4ProtocolNumber) - if want := tcpip.ErrWouldBlock; err != want { + 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) } - // Attempt to write a one-buffer packet. It must succeed. + // 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, buf, header.IPv4ProtocolNumber); err != nil { + if err := c.ep.WritePacket(&r, &hdr, vv, header.IPv4ProtocolNumber); err != nil { t.Fatalf("WritePacket failed unexpectedly: %v", err) } } diff --git a/pkg/tcpip/link/sniffer/sniffer.go b/pkg/tcpip/link/sniffer/sniffer.go index 1e302f557..3bdc85210 100644 --- a/pkg/tcpip/link/sniffer/sniffer.go +++ b/pkg/tcpip/link/sniffer/sniffer.go @@ -118,7 +118,7 @@ func NewWithFile(lower tcpip.LinkEndpointID, file *os.File, snapLen uint32) (tcp // 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) { if atomic.LoadUint32(&LogPackets) == 1 && e.file == nil { - logPacket("recv", protocol, vv.First(), nil) + logPacket("recv", protocol, vv.First()) } if e.file != nil && atomic.LoadUint32(&LogPacketsToFile) == 1 { vs := vv.Views() @@ -188,19 +188,19 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket implements the stack.LinkEndpoint interface. It is called by // higher-level protocols to write packets; it just logs the packet and forwards // the request to the lower endpoint. -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { if atomic.LoadUint32(&LogPackets) == 1 && e.file == nil { - logPacket("send", protocol, hdr.UsedBytes(), payload) + logPacket("send", protocol, hdr.UsedBytes()) } if e.file != nil && atomic.LoadUint32(&LogPacketsToFile) == 1 { hdrBuf := hdr.UsedBytes() - length := len(hdrBuf) + len(payload) + length := len(hdrBuf) + payload.Size() if length > int(e.maxPCAPLen) { length = int(e.maxPCAPLen) } buf := bytes.NewBuffer(make([]byte, 0, pcapPacketHeaderLen+length)) - if err := binary.Write(buf, binary.BigEndian, newPCAPPacketHeader(uint32(length), uint32(hdr.UsedLength()+len(payload)))); err != nil { + if err := binary.Write(buf, binary.BigEndian, newPCAPPacketHeader(uint32(length), uint32(len(hdrBuf)+payload.Size()))); err != nil { panic(err) } if len(hdrBuf) > length { @@ -211,12 +211,18 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload } length -= len(hdrBuf) if length > 0 { - p := payload - if len(p) > length { - p = p[:length] - } - if _, err := buf.Write(p); err != nil { - panic(err) + for _, v := range payload.Views() { + if len(v) > length { + v = v[:length] + } + n, err := buf.Write(v) + if err != nil { + panic(err) + } + length -= n + if length == 0 { + break + } } } if _, err := e.file.Write(buf.Bytes()); err != nil { @@ -226,7 +232,7 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload return e.lower.WritePacket(r, hdr, payload, protocol) } -func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b, plb []byte) { +func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b buffer.View) { // Figure out the network layer info. var transProto uint8 src := tcpip.Address("unknown") diff --git a/pkg/tcpip/link/waitable/waitable.go b/pkg/tcpip/link/waitable/waitable.go index 08b8d66e7..1c19a4509 100644 --- a/pkg/tcpip/link/waitable/waitable.go +++ b/pkg/tcpip/link/waitable/waitable.go @@ -100,7 +100,7 @@ func (e *Endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket implements stack.LinkEndpoint.WritePacket. It is called by // higher-level protocols to write packets. It only forwards packets to the // lower endpoint if Wait or WaitWrite haven't been called. -func (e *Endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *Endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { if !e.writeGate.Enter() { return nil } diff --git a/pkg/tcpip/link/waitable/waitable_test.go b/pkg/tcpip/link/waitable/waitable_test.go index 37efa60d6..0719a95a9 100644 --- a/pkg/tcpip/link/waitable/waitable_test.go +++ b/pkg/tcpip/link/waitable/waitable_test.go @@ -65,7 +65,7 @@ func (e *countedEndpoint) LinkAddress() tcpip.LinkAddress { return e.linkAddr } -func (e *countedEndpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (e *countedEndpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { e.writeCount++ return nil } @@ -75,21 +75,21 @@ func TestWaitWrite(t *testing.T) { _, wep := New(stack.RegisterLinkEndpoint(ep)) // Write and check that it goes through. - wep.WritePacket(nil, nil, nil, 0) + wep.WritePacket(nil, nil, buffer.VectorisedView{}, 0) if want := 1; ep.writeCount != want { t.Fatalf("Unexpected writeCount: got=%v, want=%v", ep.writeCount, want) } // Wait on dispatches, then try to write. It must go through. wep.WaitDispatch() - wep.WritePacket(nil, nil, nil, 0) + wep.WritePacket(nil, nil, buffer.VectorisedView{}, 0) if want := 2; ep.writeCount != want { t.Fatalf("Unexpected writeCount: got=%v, want=%v", ep.writeCount, want) } // Wait on writes, then try to write. It must not go through. wep.WaitWrite() - wep.WritePacket(nil, nil, nil, 0) + wep.WritePacket(nil, nil, buffer.VectorisedView{}, 0) if want := 2; ep.writeCount != want { t.Fatalf("Unexpected writeCount: got=%v, want=%v", ep.writeCount, want) } diff --git a/pkg/tcpip/network/arp/arp.go b/pkg/tcpip/network/arp/arp.go index e7dfc6444..6bf4be868 100644 --- a/pkg/tcpip/network/arp/arp.go +++ b/pkg/tcpip/network/arp/arp.go @@ -74,7 +74,7 @@ func (e *endpoint) MaxHeaderLength() uint16 { func (e *endpoint) Close() {} -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error { +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error { return tcpip.ErrNotSupported } @@ -98,7 +98,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, vv *buffer.VectorisedView) { copy(pkt.HardwareAddressSender(), r.LocalLinkAddress[:]) copy(pkt.ProtocolAddressSender(), h.ProtocolAddressTarget()) copy(pkt.ProtocolAddressTarget(), h.ProtocolAddressSender()) - e.linkEP.WritePacket(r, &hdr, nil, ProtocolNumber) + e.linkEP.WritePacket(r, &hdr, buffer.VectorisedView{}, ProtocolNumber) fallthrough // also fill the cache from requests case header.ARPReply: addr := tcpip.Address(h.ProtocolAddressSender()) @@ -150,7 +150,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack. copy(h.ProtocolAddressSender(), localAddr) copy(h.ProtocolAddressTarget(), addr) - return linkEP.WritePacket(r, &hdr, nil, ProtocolNumber) + return linkEP.WritePacket(r, &hdr, buffer.VectorisedView{}, ProtocolNumber) } // ResolveStaticAddress implements stack.LinkAddressResolver. diff --git a/pkg/tcpip/network/ip_test.go b/pkg/tcpip/network/ip_test.go index 4475a75cf..1e92b7ae9 100644 --- a/pkg/tcpip/network/ip_test.go +++ b/pkg/tcpip/network/ip_test.go @@ -66,7 +66,7 @@ type testObject struct { // checkValues verifies that the transport protocol, data contents, src & dst // addresses of a packet match what's expected. If any field doesn't match, the // test fails. -func (t *testObject) checkValues(protocol tcpip.TransportProtocolNumber, vv *buffer.VectorisedView, srcAddr, dstAddr tcpip.Address) { +func (t *testObject) checkValues(protocol tcpip.TransportProtocolNumber, vv buffer.VectorisedView, srcAddr, dstAddr tcpip.Address) { v := vv.ToView() if protocol != t.protocol { t.t.Errorf("protocol = %v, want %v", protocol, t.protocol) @@ -95,7 +95,7 @@ func (t *testObject) checkValues(protocol tcpip.TransportProtocolNumber, vv *buf // packets. This is used by the test object to verify that the results of the // parsing are expected. func (t *testObject) DeliverTransportPacket(r *stack.Route, protocol tcpip.TransportProtocolNumber, vv *buffer.VectorisedView) { - t.checkValues(protocol, vv, r.RemoteAddress, r.LocalAddress) + t.checkValues(protocol, *vv, r.RemoteAddress, r.LocalAddress) t.dataCalls++ } @@ -103,7 +103,7 @@ func (t *testObject) DeliverTransportPacket(r *stack.Route, protocol tcpip.Trans // incoming control (ICMP) packets. This is used by the test object to verify // that the results of the parsing are expected. func (t *testObject) DeliverTransportControlPacket(local, remote tcpip.Address, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, typ stack.ControlType, extra uint32, vv *buffer.VectorisedView) { - t.checkValues(trans, vv, remote, local) + t.checkValues(trans, *vv, remote, local) if typ != t.typ { t.t.Errorf("typ = %v, want %v", typ, t.typ) } @@ -145,7 +145,7 @@ func (*testObject) LinkAddress() tcpip.LinkAddress { // WritePacket is called by network endpoints after producing a packet and // writing it to the link endpoint. This is used by the test object to verify // that the produced packet is as expected. -func (t *testObject) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { +func (t *testObject) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { var prot tcpip.TransportProtocolNumber var srcAddr tcpip.Address var dstAddr tcpip.Address @@ -162,9 +162,7 @@ func (t *testObject) WritePacket(_ *stack.Route, hdr *buffer.Prependable, payloa srcAddr = h.SourceAddress() dstAddr = h.DestinationAddress() } - var views [1]buffer.View - vv := payload.ToVectorisedView(views) - t.checkValues(prot, &vv, srcAddr, dstAddr) + t.checkValues(prot, payload, srcAddr, dstAddr) return nil } @@ -223,7 +221,8 @@ func TestIPv4Send(t *testing.T) { if err != nil { t.Fatalf("could not find route: %v", err) } - if err := ep.WritePacket(&r, &hdr, payload, 123); err != nil { + vv := buffer.NewVectorisedView(len(payload), []buffer.View{payload}) + if err := ep.WritePacket(&r, &hdr, vv, 123); err != nil { t.Fatalf("WritePacket failed: %v", err) } } @@ -461,7 +460,8 @@ func TestIPv6Send(t *testing.T) { if err != nil { t.Fatalf("could not find route: %v", err) } - if err := ep.WritePacket(&r, &hdr, payload, 123); err != nil { + vv := buffer.NewVectorisedView(len(payload), []buffer.View{payload}) + if err := ep.WritePacket(&r, &hdr, vv, 123); err != nil { t.Fatalf("WritePacket failed: %v", err) } } diff --git a/pkg/tcpip/network/ipv4/icmp.go b/pkg/tcpip/network/ipv4/icmp.go index d11938d6e..de21e623e 100644 --- a/pkg/tcpip/network/ipv4/icmp.go +++ b/pkg/tcpip/network/ipv4/icmp.go @@ -120,5 +120,6 @@ func sendPing4(r *stack.Route, code byte, data buffer.View) *tcpip.Error { data = data[header.ICMPv4EchoMinimumSize-header.ICMPv4MinimumSize:] icmpv4.SetChecksum(^header.Checksum(icmpv4, header.Checksum(data, 0))) - return r.WritePacket(&hdr, data, header.ICMPv4ProtocolNumber) + vv := buffer.NewVectorisedView(len(data), []buffer.View{data}) + return r.WritePacket(&hdr, vv, header.ICMPv4ProtocolNumber) } diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go index 143d8e73e..478957827 100644 --- a/pkg/tcpip/network/ipv4/ipv4.go +++ b/pkg/tcpip/network/ipv4/ipv4.go @@ -106,9 +106,9 @@ func (e *endpoint) MaxHeaderLength() uint16 { } // WritePacket writes a packet to the given destination address and protocol. -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error { +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error { ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) - length := uint16(hdr.UsedLength() + len(payload)) + length := uint16(hdr.UsedLength() + payload.Size()) id := uint32(0) if length > header.IPv4MaximumHeaderSize+8 { // Packets of 68 bytes or less are required by RFC 791 to not be diff --git a/pkg/tcpip/network/ipv6/icmp.go b/pkg/tcpip/network/ipv6/icmp.go index e3ef89d26..b18b78830 100644 --- a/pkg/tcpip/network/ipv6/icmp.go +++ b/pkg/tcpip/network/ipv6/icmp.go @@ -62,6 +62,7 @@ func (e *endpoint) handleControl(typ stack.ControlType, extra uint32, vv *buffer e.dispatcher.DeliverTransportControlPacket(e.id.LocalAddress, h.DestinationAddress(), ProtocolNumber, p, typ, extra, vv) } +// TODO: take buffer.VectorisedView by value. func (e *endpoint) handleICMP(r *stack.Route, vv *buffer.VectorisedView) { v := vv.First() if len(v) < header.ICMPv6MinimumSize { @@ -105,8 +106,8 @@ func (e *endpoint) handleICMP(r *stack.Route, vv *buffer.VectorisedView) { pkt[icmpV6OptOffset] = ndpOptDstLinkAddr pkt[icmpV6LengthOffset] = 1 copy(pkt[icmpV6LengthOffset+1:], r.LocalLinkAddress[:]) - pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, nil)) - r.WritePacket(&hdr, nil, header.ICMPv6ProtocolNumber) + pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{})) + r.WritePacket(&hdr, buffer.VectorisedView{}, header.ICMPv6ProtocolNumber) e.linkAddrCache.AddLinkAddress(e.nicid, r.RemoteAddress, r.RemoteLinkAddress) @@ -125,13 +126,12 @@ func (e *endpoint) handleICMP(r *stack.Route, vv *buffer.VectorisedView) { return } vv.TrimFront(header.ICMPv6EchoMinimumSize) - data := vv.ToView() hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.IPv6MinimumSize + header.ICMPv6EchoMinimumSize) pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6EchoMinimumSize)) copy(pkt, h) pkt.SetType(header.ICMPv6EchoReply) - pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, data)) - r.WritePacket(&hdr, data, header.ICMPv6ProtocolNumber) + pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, *vv)) + r.WritePacket(&hdr, *vv, header.ICMPv6ProtocolNumber) case header.ICMPv6EchoReply: if len(v) < header.ICMPv6EchoMinimumSize { @@ -185,7 +185,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack. pkt[icmpV6OptOffset] = ndpOptSrcLinkAddr pkt[icmpV6LengthOffset] = 1 copy(pkt[icmpV6LengthOffset+1:], linkEP.LinkAddress()) - pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, nil)) + pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{})) length := uint16(hdr.UsedLength()) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) @@ -197,7 +197,7 @@ func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack. DstAddr: r.RemoteAddress, }) - return linkEP.WritePacket(r, &hdr, nil, ProtocolNumber) + return linkEP.WritePacket(r, &hdr, buffer.VectorisedView{}, ProtocolNumber) } // ResolveStaticAddress implements stack.LinkAddressResolver. @@ -205,15 +205,17 @@ func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bo return "", false } -func icmpChecksum(h header.ICMPv6, src, dst tcpip.Address, data []byte) uint16 { +func icmpChecksum(h header.ICMPv6, src, dst tcpip.Address, vv buffer.VectorisedView) uint16 { // Calculate the IPv6 pseudo-header upper-layer checksum. xsum := header.Checksum([]byte(src), 0) xsum = header.Checksum([]byte(dst), xsum) var upperLayerLength [4]byte - binary.BigEndian.PutUint32(upperLayerLength[:], uint32(len(h)+len(data))) + binary.BigEndian.PutUint32(upperLayerLength[:], uint32(len(h)+vv.Size())) xsum = header.Checksum(upperLayerLength[:], xsum) xsum = header.Checksum([]byte{0, 0, 0, uint8(header.ICMPv6ProtocolNumber)}, xsum) - xsum = header.Checksum(data, xsum) + for _, v := range vv.Views() { + xsum = header.Checksum(v, xsum) + } // h[2:4] is the checksum itself, set it aside to avoid checksumming the checksum. h2, h3 := h[2], h[3] diff --git a/pkg/tcpip/network/ipv6/icmp_test.go b/pkg/tcpip/network/ipv6/icmp_test.go index 582bbb40e..e9f400fe4 100644 --- a/pkg/tcpip/network/ipv6/icmp_test.go +++ b/pkg/tcpip/network/ipv6/icmp_test.go @@ -186,7 +186,7 @@ func TestLinkResolution(t *testing.T) { hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.IPv6MinimumSize + header.ICMPv6EchoMinimumSize) pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6EchoMinimumSize)) pkt.SetType(header.ICMPv6EchoRequest) - pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, nil)) + pkt.SetChecksum(icmpChecksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{})) payload := tcpip.SlicePayload(hdr.UsedBytes()) // We can't send our payload directly over the route because that diff --git a/pkg/tcpip/network/ipv6/ipv6.go b/pkg/tcpip/network/ipv6/ipv6.go index cdb8284a2..19dc1b49e 100644 --- a/pkg/tcpip/network/ipv6/ipv6.go +++ b/pkg/tcpip/network/ipv6/ipv6.go @@ -82,11 +82,8 @@ func (e *endpoint) MaxHeaderLength() uint16 { } // WritePacket writes a packet to the given destination address and protocol. -func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error { - length := uint16(hdr.UsedLength()) - if payload != nil { - length += uint16(len(payload)) - } +func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error { + length := uint16(hdr.UsedLength() + payload.Size()) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ PayloadLength: length, diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go index bbe887144..b9e2cc045 100644 --- a/pkg/tcpip/stack/registration.go +++ b/pkg/tcpip/stack/registration.go @@ -141,7 +141,7 @@ type NetworkEndpoint interface { // WritePacket writes a packet to the given destination address and // protocol. - WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error + WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error // ID returns the network protocol endpoint ID. ID() *NetworkEndpointID @@ -234,7 +234,7 @@ type LinkEndpoint interface { // WritePacket writes a packet with the given protocol through the given // route. - WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error + WritePacket(r *Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error // Attach attaches the data link layer endpoint to the network-layer // dispatcher of the stack. diff --git a/pkg/tcpip/stack/route.go b/pkg/tcpip/stack/route.go index 63a20e031..533a0b560 100644 --- a/pkg/tcpip/stack/route.go +++ b/pkg/tcpip/stack/route.go @@ -129,7 +129,7 @@ func (r *Route) IsResolutionRequired() bool { } // WritePacket writes the packet through the given route. -func (r *Route) WritePacket(hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error { +func (r *Route) WritePacket(hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error { err := r.ref.ep.WritePacket(r, hdr, payload, protocol) if err == tcpip.ErrNoRoute { r.Stats().IP.OutgoingPacketErrors.Increment() diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go index c46e91241..02f02dfa2 100644 --- a/pkg/tcpip/stack/stack_test.go +++ b/pkg/tcpip/stack/stack_test.go @@ -105,7 +105,7 @@ func (f *fakeNetworkEndpoint) Capabilities() stack.LinkEndpointCapabilities { return f.linkEP.Capabilities() } -func (f *fakeNetworkEndpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.TransportProtocolNumber) *tcpip.Error { +func (f *fakeNetworkEndpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber) *tcpip.Error { // Increment the sent packet count in the protocol descriptor. f.proto.sendPacketCount[int(r.RemoteAddress[0])%len(f.proto.sendPacketCount)]++ @@ -269,8 +269,7 @@ func sendTo(t *testing.T, s *stack.Stack, addr tcpip.Address) { defer r.Release() hdr := buffer.NewPrependable(int(r.MaxHeaderLength())) - err = r.WritePacket(&hdr, nil, fakeTransNumber) - if err != nil { + if err := r.WritePacket(&hdr, buffer.VectorisedView{}, fakeTransNumber); err != nil { t.Errorf("WritePacket failed: %v", err) return } diff --git a/pkg/tcpip/stack/transport_test.go b/pkg/tcpip/stack/transport_test.go index 98d2f9d99..5ab485c98 100644 --- a/pkg/tcpip/stack/transport_test.go +++ b/pkg/tcpip/stack/transport_test.go @@ -70,7 +70,8 @@ func (f *fakeTransportEndpoint) Write(p tcpip.Payload, opts tcpip.WriteOptions) if err != nil { return 0, err } - if err := f.route.WritePacket(&hdr, v, fakeTransNumber); err != nil { + vv := buffer.NewVectorisedView(len(v), []buffer.View{v}) + if err := f.route.WritePacket(&hdr, vv, fakeTransNumber); err != nil { return 0, err } diff --git a/pkg/tcpip/transport/ping/endpoint.go b/pkg/tcpip/transport/ping/endpoint.go index 7e10c0aae..fc98c41eb 100644 --- a/pkg/tcpip/transport/ping/endpoint.go +++ b/pkg/tcpip/transport/ping/endpoint.go @@ -384,7 +384,8 @@ func sendPing4(r *stack.Route, ident uint16, data buffer.View) *tcpip.Error { icmpv4.SetChecksum(0) icmpv4.SetChecksum(^header.Checksum(icmpv4, header.Checksum(data, 0))) - return r.WritePacket(&hdr, data, header.ICMPv4ProtocolNumber) + vv := buffer.NewVectorisedView(len(data), []buffer.View{data}) + return r.WritePacket(&hdr, vv, header.ICMPv4ProtocolNumber) } func sendPing6(r *stack.Route, ident uint16, data buffer.View) *tcpip.Error { @@ -407,8 +408,8 @@ func sendPing6(r *stack.Route, ident uint16, data buffer.View) *tcpip.Error { icmpv6.SetChecksum(0) icmpv6.SetChecksum(^header.Checksum(icmpv6, header.Checksum(data, 0))) - - return r.WritePacket(&hdr, data, header.ICMPv6ProtocolNumber) + vv := buffer.NewVectorisedView(len(data), []buffer.View{data}) + return r.WritePacket(&hdr, vv, header.ICMPv6ProtocolNumber) } func (e *endpoint) checkV4Mapped(addr *tcpip.FullAddress, allowMismatch bool) (tcpip.NetworkProtocolNumber, *tcpip.Error) { diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 558dbc50a..de5f963cf 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -166,7 +166,7 @@ func (h *handshake) checkAck(s *segment) bool { // incoming segment acknowledges something not yet sent. The // connection remains in the same state. ack := s.sequenceNumber.Add(s.logicalLen()) - h.ep.sendRaw(nil, flagRst|flagAck, s.ackNumber, ack, 0) + h.ep.sendRaw(buffer.VectorisedView{}, flagRst|flagAck, s.ackNumber, ack, 0) return false } @@ -214,7 +214,7 @@ func (h *handshake) synSentState(s *segment) *tcpip.Error { // and the handshake is completed. if s.flagIsSet(flagAck) { h.state = handshakeCompleted - h.ep.sendRaw(nil, flagAck, h.iss+1, h.ackNum, h.rcvWnd>>h.effectiveRcvWndScale()) + h.ep.sendRaw(buffer.VectorisedView{}, flagAck, h.iss+1, h.ackNum, h.rcvWnd>>h.effectiveRcvWndScale()) return nil } @@ -263,7 +263,7 @@ func (h *handshake) synRcvdState(s *segment) *tcpip.Error { if s.flagIsSet(flagAck) { seq = s.ackNumber } - h.ep.sendRaw(nil, flagRst|flagAck, seq, ack, 0) + h.ep.sendRaw(buffer.VectorisedView{}, flagRst|flagAck, seq, ack, 0) if !h.active { return tcpip.ErrInvalidEndpointState @@ -563,14 +563,14 @@ func sendSynTCP(r *stack.Route, id stack.TransportEndpointID, flags byte, seq, a } options := makeSynOptions(opts) - err := sendTCPWithOptions(r, id, nil, flags, seq, ack, rcvWnd, options) + err := sendTCPWithOptions(r, id, buffer.VectorisedView{}, flags, seq, ack, rcvWnd, options) putOptions(options) return err } // sendTCPWithOptions sends a TCP segment with the provided options via the // provided network endpoint and under the provided identity. -func sendTCPWithOptions(r *stack.Route, id stack.TransportEndpointID, data buffer.View, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size, opts []byte) *tcpip.Error { +func sendTCPWithOptions(r *stack.Route, id stack.TransportEndpointID, data buffer.VectorisedView, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size, opts []byte) *tcpip.Error { optLen := len(opts) // Allocate a buffer for the TCP header. hdr := buffer.NewPrependable(header.TCPMinimumSize + int(r.MaxHeaderLength()) + optLen) @@ -594,11 +594,10 @@ func sendTCPWithOptions(r *stack.Route, id stack.TransportEndpointID, data buffe // Only calculate the checksum if offloading isn't supported. if r.Capabilities()&stack.CapabilityChecksumOffload == 0 { - length := uint16(hdr.UsedLength()) + length := uint16(hdr.UsedLength() + data.Size()) xsum := r.PseudoHeaderChecksum(ProtocolNumber) - if data != nil { - length += uint16(len(data)) - xsum = header.Checksum(data, xsum) + for _, v := range data.Views() { + xsum = header.Checksum(v, xsum) } tcp.SetChecksum(^tcp.CalculateChecksum(xsum, length)) @@ -614,7 +613,7 @@ func sendTCPWithOptions(r *stack.Route, id stack.TransportEndpointID, data buffe // sendTCP sends a TCP segment via the provided network endpoint and under the // provided identity. -func sendTCP(r *stack.Route, id stack.TransportEndpointID, data buffer.View, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size) *tcpip.Error { +func sendTCP(r *stack.Route, id stack.TransportEndpointID, payload buffer.VectorisedView, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size) *tcpip.Error { // Allocate a buffer for the TCP header. hdr := buffer.NewPrependable(header.TCPMinimumSize + int(r.MaxHeaderLength())) @@ -636,11 +635,10 @@ func sendTCP(r *stack.Route, id stack.TransportEndpointID, data buffer.View, fla // Only calculate the checksum if offloading isn't supported. if r.Capabilities()&stack.CapabilityChecksumOffload == 0 { - length := uint16(hdr.UsedLength()) + length := uint16(hdr.UsedLength() + payload.Size()) xsum := r.PseudoHeaderChecksum(ProtocolNumber) - if data != nil { - length += uint16(len(data)) - xsum = header.Checksum(data, xsum) + for _, v := range payload.Views() { + xsum = header.Checksum(v, xsum) } tcp.SetChecksum(^tcp.CalculateChecksum(xsum, length)) @@ -651,7 +649,7 @@ func sendTCP(r *stack.Route, id stack.TransportEndpointID, data buffer.View, fla r.Stats().TCP.ResetsSent.Increment() } - return r.WritePacket(&hdr, data, ProtocolNumber) + return r.WritePacket(&hdr, payload, ProtocolNumber) } // makeOptions makes an options slice. @@ -694,7 +692,7 @@ func (e *endpoint) makeOptions(sackBlocks []header.SACKBlock) []byte { } // sendRaw sends a TCP segment to the endpoint's peer. -func (e *endpoint) sendRaw(data buffer.View, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size) *tcpip.Error { +func (e *endpoint) sendRaw(data buffer.VectorisedView, flags byte, seq, ack seqnum.Value, rcvWnd seqnum.Size) *tcpip.Error { var sackBlocks []header.SACKBlock if e.state == stateConnected && e.rcv.pendingBufSize > 0 && (flags&flagAck != 0) { sackBlocks = e.sack.Blocks[:e.sack.NumBlocks] @@ -751,7 +749,7 @@ func (e *endpoint) handleClose() *tcpip.Error { // state with the given error code. This method must only be called from the // protocol goroutine. func (e *endpoint) resetConnectionLocked(err *tcpip.Error) { - e.sendRaw(nil, flagAck|flagRst, e.snd.sndUna, e.rcv.rcvNxt, 0) + e.sendRaw(buffer.VectorisedView{}, flagAck|flagRst, e.snd.sndUna, e.rcv.rcvNxt, 0) e.state = stateError e.hardError = err @@ -851,7 +849,7 @@ func (e *endpoint) keepaliveTimerExpired() *tcpip.Error { // seg.seq = snd.nxt-1. e.keepalive.unacked++ e.keepalive.Unlock() - e.snd.sendSegment(nil, flagAck, e.snd.sndNxt-1) + e.snd.sendSegment(buffer.VectorisedView{}, flagAck, e.snd.sndNxt-1) e.resetKeepaliveTimer(false) return nil } diff --git a/pkg/tcpip/transport/tcp/protocol.go b/pkg/tcpip/transport/tcp/protocol.go index 194d3f41d..006b2f074 100644 --- a/pkg/tcpip/transport/tcp/protocol.go +++ b/pkg/tcpip/transport/tcp/protocol.go @@ -147,7 +147,7 @@ func replyWithReset(s *segment) { ack := s.sequenceNumber.Add(s.logicalLen()) - sendTCP(&s.route, s.id, nil, flagRst|flagAck, seq, ack, 0) + sendTCP(&s.route, s.id, buffer.VectorisedView{}, flagRst|flagAck, seq, ack, 0) } // SetOption implements TransportProtocol.SetOption. diff --git a/pkg/tcpip/transport/tcp/snd.go b/pkg/tcpip/transport/tcp/snd.go index e4fa89912..284e720c6 100644 --- a/pkg/tcpip/transport/tcp/snd.go +++ b/pkg/tcpip/transport/tcp/snd.go @@ -270,7 +270,7 @@ func (s *sender) updateMaxPayloadSize(mtu, count int) { // sendAck sends an ACK segment. func (s *sender) sendAck() { - s.sendSegment(nil, flagAck, s.sndNxt) + s.sendSegment(buffer.VectorisedView{}, flagAck, s.sndNxt) } // updateRTO updates the retransmit timeout when a new roud-trip time is @@ -305,7 +305,7 @@ func (s *sender) resendSegment() { // Resend the segment. if seg := s.writeList.Front(); seg != nil { - s.sendSegment(&seg.data, seg.flags, seg.sequenceNumber) + s.sendSegment(seg.data, seg.flags, seg.sequenceNumber) } } @@ -419,7 +419,7 @@ func (s *sender) sendData() { segEnd = seg.sequenceNumber.Add(seqnum.Size(seg.data.Size())) } - s.sendSegment(&seg.data, seg.flags, seg.sequenceNumber) + s.sendSegment(seg.data, seg.flags, seg.sequenceNumber) // Update sndNxt if we actually sent new data (as opposed to // retransmitting some previously sent data). @@ -642,7 +642,7 @@ func (s *sender) handleRcvdSegment(seg *segment) { // sendSegment sends a new segment containing the given payload, flags and // sequence number. -func (s *sender) sendSegment(data *buffer.VectorisedView, flags byte, seq seqnum.Value) *tcpip.Error { +func (s *sender) sendSegment(data buffer.VectorisedView, flags byte, seq seqnum.Value) *tcpip.Error { s.lastSendTime = time.Now() if seq == s.rttMeasureSeqNum { s.rttMeasureTime = s.lastSendTime @@ -653,13 +653,5 @@ func (s *sender) sendSegment(data *buffer.VectorisedView, flags byte, seq seqnum // Remember the max sent ack. s.maxSentAck = rcvNxt - if data == nil { - return s.ep.sendRaw(nil, flags, seq, rcvNxt, rcvWnd) - } - - if len(data.Views()) > 1 { - panic("send path does not support views with multiple buffers") - } - - return s.ep.sendRaw(data.First(), flags, seq, rcvNxt, rcvWnd) + return s.ep.sendRaw(data, flags, seq, rcvNxt, rcvWnd) } diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 6a12c2f08..283379a28 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -328,7 +328,8 @@ func (e *endpoint) Write(p tcpip.Payload, opts tcpip.WriteOptions) (uintptr, *tc return 0, err } - if err := sendUDP(route, v, e.id.LocalPort, dstPort); err != nil { + vv := buffer.NewVectorisedView(len(v), []buffer.View{v}) + if err := sendUDP(route, vv, e.id.LocalPort, dstPort); err != nil { return 0, err } return uintptr(len(v)), nil @@ -426,14 +427,14 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error { // sendUDP sends a UDP segment via the provided network endpoint and under the // provided identity. -func sendUDP(r *stack.Route, data buffer.View, localPort, remotePort uint16) *tcpip.Error { +func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16) *tcpip.Error { // Allocate a buffer for the UDP header. hdr := buffer.NewPrependable(header.UDPMinimumSize + int(r.MaxHeaderLength())) // Initialize the header. udp := header.UDP(hdr.Prepend(header.UDPMinimumSize)) - length := uint16(hdr.UsedLength()) + uint16(len(data)) + length := uint16(hdr.UsedLength() + data.Size()) udp.Encode(&header.UDPFields{ SrcPort: localPort, DstPort: remotePort, @@ -443,10 +444,9 @@ func sendUDP(r *stack.Route, data buffer.View, localPort, remotePort uint16) *tc // Only calculate the checksum if offloading isn't supported. if r.Capabilities()&stack.CapabilityChecksumOffload == 0 { xsum := r.PseudoHeaderChecksum(ProtocolNumber) - if data != nil { - xsum = header.Checksum(data, xsum) + for _, v := range data.Views() { + xsum = header.Checksum(v, xsum) } - udp.SetChecksum(^udp.CalculateChecksum(xsum, length)) } |