mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
committed by
Shentubot
parent
fe8ca76c22
commit
5685d6b5ad
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user