blob: 55568e0d28af47b90b577bd61703a3d246b90383 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package packetbuffer
import (
"fmt"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
// OutboundToInbound coverts a PacketBuffer that conforms to the
// contract of WritePacket to one that conforms to the contract of
// DeliverNetworkPacket/InjectInbound/etc.
//
// The contract of WritePacket differs from that of DeliverNetworkPacket.
// WritePacket treats Header and Data as disjoint buffers; DeliverNetworkPacket
// expects Data to contain the full packet, including any Header bytes if they
// are present.
func OutboundToInbound(pkt *stack.PacketBuffer) *stack.PacketBuffer {
views := make([]buffer.View, 1, 1+len(pkt.Data.Views()))
views[0] = pkt.Header.View()
views = append(views, pkt.Data.Views()...)
return &stack.PacketBuffer{
Data: buffer.NewVectorisedView(len(views[0])+pkt.Data.Size(), views),
}
}
// EnsurePopulatedHeader smashes pkt.Data into pkt.Header, leaving
// maxLinkHeaderLen space in reserve.
func EnsurePopulatedHeader(pkt *stack.PacketBuffer, maxLinkHeaderLen uint16) {
if pkt.Data.Size() == 0 {
return
}
hdr := pkt.Header
pkt.Header = buffer.NewPrependable(hdr.UsedLength() + pkt.Data.Size() + int(maxLinkHeaderLen))
for i := len(pkt.Data.Views()); i != 0; i-- {
view := pkt.Data.Views()[i-1]
if n := copy(pkt.Header.Prepend(len(view)), view); n != len(view) {
panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, len(view)))
}
}
if n := copy(pkt.Header.Prepend(hdr.UsedLength()), hdr.View()); n != hdr.UsedLength() {
panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, hdr.UsedLength()))
}
pkt.Data = buffer.VectorisedView{}
}