Update {LinkEndpoint,NetworkEndpoint}#WritePacket to take a VectorisedView

Makes it possible to avoid copying or allocating in cases where DeliverNetworkPacket (rx)
needs to turn around and call WritePacket (tx) with its VectorisedView.

Also removes the restriction on having VectorisedViews with multiple views in the write path.

PiperOrigin-RevId: 211728717
Change-Id: Ie03a65ecb4e28bd15ebdb9c69f05eced18fdfcff
This commit is contained in:
Bert Muthalaly
2018-09-05 17:34:25 -07:00
committed by Shentubot
parent fe8ca76c22
commit 5685d6b5ad
26 changed files with 137 additions and 143 deletions
+1 -1
View File
@@ -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
+4 -8
View File
@@ -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 {
+7 -5
View File
@@ -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 {
+4 -3
View File
@@ -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)
}
+6 -12
View File
@@ -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
}
+3 -2
View File
@@ -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 {
+19 -16
View File
@@ -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)
}
}
+18 -12
View File
@@ -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")
+1 -1
View File
@@ -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
}
+4 -4
View File
@@ -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)
}
+3 -3
View File
@@ -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.
+9 -9
View File
@@ -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)
}
}
+2 -1
View File
@@ -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)
}
+2 -2
View File
@@ -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
+12 -10
View File
@@ -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]
+1 -1
View File
@@ -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
+2 -5
View File
@@ -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,
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -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()
+2 -3
View File
@@ -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
}

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