summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-03-04 00:10:22 +0000
committergVisor bot <gvisor-bot@google.com>2021-03-04 00:10:22 +0000
commit441d4acfe5b5ea527084930a60e90656a254c881 (patch)
treeb76347fabadc1397e9867bde5ec4e4a80709a07e /pkg/tcpip/network
parentbaa0ab982f66510088d66778cf063ff72e6f9022 (diff)
parent1cd76d958a9b3eb29f6b55a8bea71fbe464e67d3 (diff)
Merge release-20210301.0-12-g1cd76d958 (automated)
Diffstat (limited to 'pkg/tcpip/network')
-rw-r--r--pkg/tcpip/network/internal/fragmentation/fragmentation.go6
-rw-r--r--pkg/tcpip/network/internal/fragmentation/reassembler.go4
-rw-r--r--pkg/tcpip/network/ipv4/icmp.go25
-rw-r--r--pkg/tcpip/network/ipv4/igmp.go4
-rw-r--r--pkg/tcpip/network/ipv4/ipv4.go20
-rw-r--r--pkg/tcpip/network/ipv6/icmp.go104
-rw-r--r--pkg/tcpip/network/ipv6/ipv6.go17
-rw-r--r--pkg/tcpip/network/ipv6/mld.go6
-rw-r--r--pkg/tcpip/network/ipv6/ndp.go12
9 files changed, 118 insertions, 80 deletions
diff --git a/pkg/tcpip/network/internal/fragmentation/fragmentation.go b/pkg/tcpip/network/internal/fragmentation/fragmentation.go
index 243738951..5168f5361 100644
--- a/pkg/tcpip/network/internal/fragmentation/fragmentation.go
+++ b/pkg/tcpip/network/internal/fragmentation/fragmentation.go
@@ -170,7 +170,7 @@ func (f *Fragmentation) Process(
return nil, 0, false, fmt.Errorf("fragment size=%d bytes is not a multiple of block size=%d on non-final fragment: %w", fragmentSize, f.blockSize, ErrInvalidArgs)
}
- if l := pkt.Data.Size(); l != int(fragmentSize) {
+ if l := pkt.Data().Size(); l != int(fragmentSize) {
return nil, 0, false, fmt.Errorf("got fragment size=%d bytes not equal to the expected fragment size=%d bytes (first=%d last=%d): %w", l, fragmentSize, first, last, ErrInvalidArgs)
}
@@ -293,7 +293,7 @@ func MakePacketFragmenter(pkt *stack.PacketBuffer, fragmentPayloadLen uint32, re
// these headers.
var fragmentableData buffer.VectorisedView
fragmentableData.AppendView(pkt.TransportHeader().View())
- fragmentableData.Append(pkt.Data)
+ fragmentableData.Append(pkt.Data().ExtractVV())
fragmentCount := (uint32(fragmentableData.Size()) + fragmentPayloadLen - 1) / fragmentPayloadLen
return PacketFragmenter{
@@ -323,7 +323,7 @@ func (pf *PacketFragmenter) BuildNextFragment() (*stack.PacketBuffer, int, int,
})
// Copy data for the fragment.
- copied := pf.data.ReadToVV(&fragPkt.Data, pf.fragmentPayloadLen)
+ copied := fragPkt.Data().ReadFromVV(&pf.data, pf.fragmentPayloadLen)
offset := pf.fragmentOffset
pf.fragmentOffset += copied
diff --git a/pkg/tcpip/network/internal/fragmentation/reassembler.go b/pkg/tcpip/network/internal/fragmentation/reassembler.go
index 933d63d32..90075a70c 100644
--- a/pkg/tcpip/network/internal/fragmentation/reassembler.go
+++ b/pkg/tcpip/network/internal/fragmentation/reassembler.go
@@ -167,8 +167,8 @@ func (r *reassembler) process(first, last uint16, more bool, proto uint8, pkt *s
resPkt := r.holes[0].pkt
for i := 1; i < len(r.holes); i++ {
- fragPkt := r.holes[i].pkt
- fragPkt.Data.ReadToVV(&resPkt.Data, fragPkt.Data.Size())
+ fragData := r.holes[i].pkt.Data()
+ resPkt.Data().ReadFromData(fragData, fragData.Size())
}
return resPkt, r.proto, true, memConsumed, nil
}
diff --git a/pkg/tcpip/network/ipv4/icmp.go b/pkg/tcpip/network/ipv4/icmp.go
index 5bf7809e8..deb104837 100644
--- a/pkg/tcpip/network/ipv4/icmp.go
+++ b/pkg/tcpip/network/ipv4/icmp.go
@@ -137,7 +137,7 @@ func (e *endpoint) checkLocalAddress(addr tcpip.Address) bool {
// is used to find out which transport endpoint must be notified about the ICMP
// packet. We only expect the payload, not the enclosing ICMP packet.
func (e *endpoint) handleControl(errInfo stack.TransportError, pkt *stack.PacketBuffer) {
- h, ok := pkt.Data.PullUp(header.IPv4MinimumSize)
+ h, ok := pkt.Data().PullUp(header.IPv4MinimumSize)
if !ok {
return
}
@@ -156,7 +156,7 @@ func (e *endpoint) handleControl(errInfo stack.TransportError, pkt *stack.Packet
}
hlen := int(hdr.HeaderLength())
- if pkt.Data.Size() < hlen || hdr.FragmentOffset() != 0 {
+ if pkt.Data().Size() < hlen || hdr.FragmentOffset() != 0 {
// We won't be able to handle this if it doesn't contain the
// full IPv4 header, or if it's a fragment not at offset 0
// (because it won't have the transport header).
@@ -164,7 +164,7 @@ func (e *endpoint) handleControl(errInfo stack.TransportError, pkt *stack.Packet
}
// Skip the ip header, then deliver the error.
- pkt.Data.TrimFront(hlen)
+ pkt.Data().TrimFront(hlen)
p := hdr.TransportProtocol()
e.dispatcher.DeliverTransportError(srcAddr, hdr.DestinationAddress(), ProtocolNumber, p, errInfo, pkt)
}
@@ -174,7 +174,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer) {
// TODO(gvisor.dev/issue/170): ICMP packets don't have their
// TransportHeader fields set. See icmp/protocol.go:protocol.Parse for a
// full explanation.
- v, ok := pkt.Data.PullUp(header.ICMPv4MinimumSize)
+ v, ok := pkt.Data().PullUp(header.ICMPv4MinimumSize)
if !ok {
received.invalid.Increment()
return
@@ -182,7 +182,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer) {
h := header.ICMPv4(v)
// Only do in-stack processing if the checksum is correct.
- if header.ChecksumVV(pkt.Data, 0 /* initial */) != 0xffff {
+ if pkt.Data().AsRange().Checksum() != 0xffff {
received.invalid.Increment()
// It's possible that a raw socket expects to receive this regardless
// of checksum errors. If it's an echo request we know it's safe because
@@ -253,7 +253,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer) {
// TODO(gvisor.dev/issue/4399): The copy may not be needed if there are no
// waiting endpoints. Consider moving responsibility for doing the copy to
// DeliverTransportPacket so that is is only done when needed.
- replyData := pkt.Data.ToOwnedView()
+ replyData := pkt.Data().AsRange().ToOwnedView()
ipHdr := header.IPv4(pkt.NetworkHeader().View())
localAddressBroadcast := pkt.NetworkPacketInfo.LocalAddressBroadcast
@@ -336,7 +336,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer) {
case header.ICMPv4DstUnreachable:
received.dstUnreachable.Increment()
- pkt.Data.TrimFront(header.ICMPv4MinimumSize)
+ pkt.Data().TrimFront(header.ICMPv4MinimumSize)
switch h.Code() {
case header.ICMPv4HostUnreachable:
e.handleControl(&icmpv4DestinationHostUnreachableSockError{}, pkt)
@@ -571,7 +571,7 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
return nil
}
- payloadLen := len(origIPHdr) + transportHeader.Size() + pkt.Data.Size()
+ payloadLen := len(origIPHdr) + transportHeader.Size() + pkt.Data().Size()
if payloadLen > available {
payloadLen = available
}
@@ -586,8 +586,11 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
newHeader := append(buffer.View(nil), origIPHdr...)
newHeader = append(newHeader, transportHeader...)
payload := newHeader.ToVectorisedView()
- payload.AppendView(pkt.Data.ToView())
- payload.CapLength(payloadLen)
+ if dataCap := payloadLen - payload.Size(); dataCap > 0 {
+ payload.AppendView(pkt.Data().AsRange().Capped(dataCap).ToOwnedView())
+ } else {
+ payload.CapLength(payloadLen)
+ }
icmpPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(route.MaxHeaderLength()) + header.ICMPv4MinimumSize,
@@ -623,7 +626,7 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
default:
panic(fmt.Sprintf("unsupported ICMP type %T", reason))
}
- icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr, icmpPkt.Data))
+ icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr, icmpPkt.Data().AsRange().Checksum()))
if err := route.WritePacket(
nil, /* gso */
diff --git a/pkg/tcpip/network/ipv4/igmp.go b/pkg/tcpip/network/ipv4/igmp.go
index 0a15ae897..f3fc1c87e 100644
--- a/pkg/tcpip/network/ipv4/igmp.go
+++ b/pkg/tcpip/network/ipv4/igmp.go
@@ -197,7 +197,7 @@ func (igmp *igmpState) isPacketValidLocked(pkt *stack.PacketBuffer, messageType
// Precondition: igmp.ep.mu must be locked.
func (igmp *igmpState) handleIGMP(pkt *stack.PacketBuffer, hasRouterAlertOption bool) {
received := igmp.ep.stats.igmp.packetsReceived
- headerView, ok := pkt.Data.PullUp(header.IGMPMinimumSize)
+ headerView, ok := pkt.Data().PullUp(header.IGMPMinimumSize)
if !ok {
received.invalid.Increment()
return
@@ -210,7 +210,7 @@ func (igmp *igmpState) handleIGMP(pkt *stack.PacketBuffer, hasRouterAlertOption
// same set of octets, including the checksum field. If the result
// is all 1 bits (-0 in 1's complement arithmetic), the check
// succeeds.
- if header.ChecksumVV(pkt.Data, 0 /* initial */) != 0xFFFF {
+ if pkt.Data().AsRange().Checksum() != 0xFFFF {
received.checksumErrors.Increment()
return
}
diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go
index 4a429ea6c..cabe274d6 100644
--- a/pkg/tcpip/network/ipv4/ipv4.go
+++ b/pkg/tcpip/network/ipv4/ipv4.go
@@ -492,7 +492,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBuffer) tcpip.Error {
// The packet already has an IP header, but there are a few required
// checks.
- h, ok := pkt.Data.PullUp(header.IPv4MinimumSize)
+ h, ok := pkt.Data().PullUp(header.IPv4MinimumSize)
if !ok {
return &tcpip.ErrMalformedHeader{}
}
@@ -502,14 +502,14 @@ func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBu
return &tcpip.ErrMalformedHeader{}
}
- h, ok = pkt.Data.PullUp(int(hdrLen))
+ h, ok = pkt.Data().PullUp(int(hdrLen))
if !ok {
return &tcpip.ErrMalformedHeader{}
}
ip := header.IPv4(h)
// Always set the total length.
- pktSize := pkt.Data.Size()
+ pktSize := pkt.Data().Size()
ip.SetTotalLength(uint16(pktSize))
// Set the source address when zero.
@@ -687,7 +687,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
stats := e.stats
h := header.IPv4(pkt.NetworkHeader().View())
- if !h.IsValid(pkt.Data.Size() + pkt.NetworkHeader().View().Size() + pkt.TransportHeader().View().Size()) {
+ if !h.IsValid(pkt.Data().Size() + pkt.NetworkHeader().View().Size() + pkt.TransportHeader().View().Size()) {
stats.ip.MalformedPacketsReceived.Increment()
return
}
@@ -765,7 +765,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
}
if h.More() || h.FragmentOffset() != 0 {
- if pkt.Data.Size()+pkt.TransportHeader().View().Size() == 0 {
+ if pkt.Data().Size()+pkt.TransportHeader().View().Size() == 0 {
// Drop the packet as it's marked as a fragment but has
// no payload.
stats.ip.MalformedPacketsReceived.Increment()
@@ -793,10 +793,10 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
// maximum payload size.
//
// Note that this addition doesn't overflow even on 32bit architecture
- // because pkt.Data.Size() should not exceed 65535 (the max IP datagram
+ // because pkt.Data().Size() should not exceed 65535 (the max IP datagram
// size). Otherwise the packet would've been rejected as invalid before
// reaching here.
- if int(start)+pkt.Data.Size() > header.IPv4MaximumPayloadSize {
+ if int(start)+pkt.Data().Size() > header.IPv4MaximumPayloadSize {
stats.ip.MalformedPacketsReceived.Increment()
stats.ip.MalformedFragmentsReceived.Increment()
return
@@ -813,7 +813,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
Protocol: proto,
},
start,
- start+uint16(pkt.Data.Size())-1,
+ start+uint16(pkt.Data().Size())-1,
h.More(),
proto,
pkt,
@@ -831,7 +831,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
// The reassembler doesn't take care of fixing up the header, so we need
// to do it here.
- h.SetTotalLength(uint16(pkt.Data.Size() + len((h))))
+ h.SetTotalLength(uint16(pkt.Data().Size() + len((h))))
h.SetFlagsFragmentOffset(0, 0)
}
stats.ip.PacketsDelivered.Increment()
@@ -1186,7 +1186,7 @@ func calculateNetworkMTU(linkMTU, networkHeaderSize uint32) (uint32, tcpip.Error
}
func packetMustBeFragmented(pkt *stack.PacketBuffer, networkMTU uint32, gso *stack.GSO) bool {
- payload := pkt.TransportHeader().View().Size() + pkt.Data.Size()
+ payload := pkt.TransportHeader().View().Size() + pkt.Data().Size()
return (gso == nil || gso.Type == stack.GSONone) && uint32(payload) > networkMTU
}
diff --git a/pkg/tcpip/network/ipv6/icmp.go b/pkg/tcpip/network/ipv6/icmp.go
index 5f44ab317..e80e681da 100644
--- a/pkg/tcpip/network/ipv6/icmp.go
+++ b/pkg/tcpip/network/ipv6/icmp.go
@@ -18,7 +18,6 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -165,7 +164,7 @@ func (e *endpoint) checkLocalAddress(addr tcpip.Address) bool {
// used to find out which transport endpoint must be notified about the ICMP
// packet.
func (e *endpoint) handleControl(transErr stack.TransportError, pkt *stack.PacketBuffer) {
- h, ok := pkt.Data.PullUp(header.IPv6MinimumSize)
+ h, ok := pkt.Data().PullUp(header.IPv6MinimumSize)
if !ok {
return
}
@@ -184,10 +183,10 @@ func (e *endpoint) handleControl(transErr stack.TransportError, pkt *stack.Packe
// Skip the IP header, then handle the fragmentation header if there
// is one.
- pkt.Data.TrimFront(header.IPv6MinimumSize)
+ pkt.Data().TrimFront(header.IPv6MinimumSize)
p := hdr.TransportProtocol()
if p == header.IPv6FragmentHeader {
- f, ok := pkt.Data.PullUp(header.IPv6FragmentHeaderSize)
+ f, ok := pkt.Data().PullUp(header.IPv6FragmentHeaderSize)
if !ok {
return
}
@@ -200,7 +199,7 @@ func (e *endpoint) handleControl(transErr stack.TransportError, pkt *stack.Packe
// Skip fragmentation header and find out the actual protocol
// number.
- pkt.Data.TrimFront(header.IPv6FragmentHeaderSize)
+ pkt.Data().TrimFront(header.IPv6FragmentHeaderSize)
p = fragHdr.TransportProtocol()
}
@@ -268,7 +267,7 @@ func isMLDValid(pkt *stack.PacketBuffer, iph header.IPv6, routerAlert *header.IP
if routerAlert == nil || routerAlert.Value != header.IPv6RouterAlertMLD {
return false
}
- if pkt.Data.Size() < header.ICMPv6HeaderSize+header.MLDMinimumSize {
+ if pkt.Data().Size() < header.ICMPv6HeaderSize+header.MLDMinimumSize {
return false
}
if iph.HopLimit() != header.MLDHopLimit {
@@ -285,7 +284,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
received := e.stats.icmp.packetsReceived
// TODO(gvisor.dev/issue/170): ICMP packets don't have their TransportHeader
// fields set. See icmp/protocol.go:protocol.Parse for a full explanation.
- v, ok := pkt.Data.PullUp(header.ICMPv6HeaderSize)
+ v, ok := pkt.Data().PullUp(header.ICMPv6HeaderSize)
if !ok {
received.invalid.Increment()
return
@@ -296,11 +295,14 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
dstAddr := iph.DestinationAddress()
// Validate ICMPv6 checksum before processing the packet.
- //
- // This copy is used as extra payload during the checksum calculation.
- payload := pkt.Data.Clone(nil)
- payload.TrimFront(len(h))
- if got, want := h.Checksum(), header.ICMPv6Checksum(h, srcAddr, dstAddr, payload); got != want {
+ payload := pkt.Data().AsRange().SubRange(len(h))
+ if got, want := h.Checksum(), header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: h,
+ Src: srcAddr,
+ Dst: dstAddr,
+ PayloadCsum: payload.Checksum(),
+ PayloadLen: payload.Size(),
+ }); got != want {
received.invalid.Increment()
return
}
@@ -320,12 +322,12 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
switch icmpType := h.Type(); icmpType {
case header.ICMPv6PacketTooBig:
received.packetTooBig.Increment()
- hdr, ok := pkt.Data.PullUp(header.ICMPv6PacketTooBigMinimumSize)
+ hdr, ok := pkt.Data().PullUp(header.ICMPv6PacketTooBigMinimumSize)
if !ok {
received.invalid.Increment()
return
}
- pkt.Data.TrimFront(header.ICMPv6PacketTooBigMinimumSize)
+ pkt.Data().TrimFront(header.ICMPv6PacketTooBigMinimumSize)
networkMTU, err := calculateNetworkMTU(header.ICMPv6(hdr).MTU(), header.IPv6MinimumSize)
if err != nil {
networkMTU = 0
@@ -334,12 +336,12 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
case header.ICMPv6DstUnreachable:
received.dstUnreachable.Increment()
- hdr, ok := pkt.Data.PullUp(header.ICMPv6DstUnreachableMinimumSize)
+ hdr, ok := pkt.Data().PullUp(header.ICMPv6DstUnreachableMinimumSize)
if !ok {
received.invalid.Increment()
return
}
- pkt.Data.TrimFront(header.ICMPv6DstUnreachableMinimumSize)
+ pkt.Data().TrimFront(header.ICMPv6DstUnreachableMinimumSize)
switch header.ICMPv6(hdr).Code() {
case header.ICMPv6NetworkUnreachable:
e.handleControl(&icmpv6DestinationNetworkUnreachableSockError{}, pkt)
@@ -348,16 +350,16 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
}
case header.ICMPv6NeighborSolicit:
received.neighborSolicit.Increment()
- if !isNDPValid() || pkt.Data.Size() < header.ICMPv6NeighborSolicitMinimumSize {
+ if !isNDPValid() || pkt.Data().Size() < header.ICMPv6NeighborSolicitMinimumSize {
received.invalid.Increment()
return
}
// The remainder of payload must be only the neighbor solicitation, so
- // payload.ToView() always returns the solicitation. Per RFC 6980 section 5,
+ // payload.AsView() always returns the solicitation. Per RFC 6980 section 5,
// NDP messages cannot be fragmented. Also note that in the common case NDP
- // datagrams are very small and ToView() will not incur allocations.
- ns := header.NDPNeighborSolicit(payload.ToView())
+ // datagrams are very small and AsView() will not incur allocations.
+ ns := header.NDPNeighborSolicit(payload.AsView())
targetAddr := ns.TargetAddress()
// As per RFC 4861 section 4.3, the Target Address MUST NOT be a multicast
@@ -529,7 +531,11 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
na.SetOverrideFlag(true)
na.SetTargetAddress(targetAddr)
na.Options().Serialize(optsSerializer)
- packet.SetChecksum(header.ICMPv6Checksum(packet, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))
+ packet.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: packet,
+ Src: r.LocalAddress,
+ Dst: r.RemoteAddress,
+ }))
// RFC 4861 Neighbor Discovery for IP version 6 (IPv6)
//
@@ -545,16 +551,16 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
case header.ICMPv6NeighborAdvert:
received.neighborAdvert.Increment()
- if !isNDPValid() || pkt.Data.Size() < header.ICMPv6NeighborAdvertMinimumSize {
+ if !isNDPValid() || pkt.Data().Size() < header.ICMPv6NeighborAdvertMinimumSize {
received.invalid.Increment()
return
}
// The remainder of payload must be only the neighbor advertisement, so
- // payload.ToView() always returns the advertisement. Per RFC 6980 section
+ // payload.AsView() always returns the advertisement. Per RFC 6980 section
// 5, NDP messages cannot be fragmented. Also note that in the common case
- // NDP datagrams are very small and ToView() will not incur allocations.
- na := header.NDPNeighborAdvert(payload.ToView())
+ // NDP datagrams are very small and AsView() will not incur allocations.
+ na := header.NDPNeighborAdvert(payload.AsView())
targetAddr := na.TargetAddress()
e.dad.mu.Lock()
@@ -657,13 +663,20 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
replyPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(r.MaxHeaderLength()) + header.ICMPv6EchoMinimumSize,
- Data: pkt.Data,
+ Data: pkt.Data().ExtractVV(),
})
- packet := header.ICMPv6(replyPkt.TransportHeader().Push(header.ICMPv6EchoMinimumSize))
+ icmp := header.ICMPv6(replyPkt.TransportHeader().Push(header.ICMPv6EchoMinimumSize))
pkt.TransportProtocolNumber = header.ICMPv6ProtocolNumber
- copy(packet, icmpHdr)
- packet.SetType(header.ICMPv6EchoReply)
- packet.SetChecksum(header.ICMPv6Checksum(packet, r.LocalAddress, r.RemoteAddress, pkt.Data))
+ copy(icmp, icmpHdr)
+ icmp.SetType(header.ICMPv6EchoReply)
+ dataRange := replyPkt.Data().AsRange()
+ icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmp,
+ Src: r.LocalAddress,
+ Dst: r.RemoteAddress,
+ PayloadCsum: dataRange.Checksum(),
+ PayloadLen: dataRange.Size(),
+ }))
if err := r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{
Protocol: header.ICMPv6ProtocolNumber,
TTL: r.DefaultTTL(),
@@ -676,7 +689,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
case header.ICMPv6EchoReply:
received.echoReply.Increment()
- if pkt.Data.Size() < header.ICMPv6EchoMinimumSize {
+ if pkt.Data().Size() < header.ICMPv6EchoMinimumSize {
received.invalid.Increment()
return
}
@@ -696,7 +709,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
//
// Is the NDP payload of sufficient size to hold a Router Solictation?
- if !isNDPValid() || pkt.Data.Size()-header.ICMPv6HeaderSize < header.NDPRSMinimumSize {
+ if !isNDPValid() || pkt.Data().Size()-header.ICMPv6HeaderSize < header.NDPRSMinimumSize {
received.invalid.Increment()
return
}
@@ -710,9 +723,9 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
return
}
- // Note that in the common case NDP datagrams are very small and ToView()
+ // Note that in the common case NDP datagrams are very small and AsView()
// will not incur allocations.
- rs := header.NDPRouterSolicit(payload.ToView())
+ rs := header.NDPRouterSolicit(payload.AsView())
it, err := rs.Options().Iter(false /* check */)
if err != nil {
// Options are not valid as per the wire format, silently drop the packet.
@@ -756,7 +769,7 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
//
// Is the NDP payload of sufficient size to hold a Router Advertisement?
- if !isNDPValid() || pkt.Data.Size()-header.ICMPv6HeaderSize < header.NDPRAMinimumSize {
+ if !isNDPValid() || pkt.Data().Size()-header.ICMPv6HeaderSize < header.NDPRAMinimumSize {
received.invalid.Increment()
return
}
@@ -770,9 +783,9 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
return
}
- // Note that in the common case NDP datagrams are very small and ToView()
+ // Note that in the common case NDP datagrams are very small and AsView()
// will not incur allocations.
- ra := header.NDPRouterAdvert(payload.ToView())
+ ra := header.NDPRouterAdvert(payload.AsView())
it, err := ra.Options().Iter(false /* check */)
if err != nil {
// Options are not valid as per the wire format, silently drop the packet.
@@ -850,11 +863,11 @@ func (e *endpoint) handleICMP(pkt *stack.PacketBuffer, hasFragmentHeader bool, r
switch icmpType {
case header.ICMPv6MulticastListenerQuery:
e.mu.Lock()
- e.mu.mld.handleMulticastListenerQuery(header.MLD(payload.ToView()))
+ e.mu.mld.handleMulticastListenerQuery(header.MLD(payload.AsView()))
e.mu.Unlock()
case header.ICMPv6MulticastListenerReport:
e.mu.Lock()
- e.mu.mld.handleMulticastListenerReport(header.MLD(payload.ToView()))
+ e.mu.mld.handleMulticastListenerReport(header.MLD(payload.AsView()))
e.mu.Unlock()
case header.ICMPv6MulticastListenerDone:
default:
@@ -1077,13 +1090,13 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
if available < header.IPv6MinimumSize {
return nil
}
- payloadLen := network.Size() + transport.Size() + pkt.Data.Size()
+ payloadLen := network.Size() + transport.Size() + pkt.Data().Size()
if payloadLen > available {
payloadLen = available
}
payload := network.ToVectorisedView()
payload.AppendView(transport)
- payload.Append(pkt.Data)
+ payload.Append(pkt.Data().ExtractVV())
payload.CapLength(payloadLen)
newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
@@ -1115,7 +1128,14 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
default:
panic(fmt.Sprintf("unsupported ICMP type %T", reason))
}
- icmpHdr.SetChecksum(header.ICMPv6Checksum(icmpHdr, route.LocalAddress, route.RemoteAddress, newPkt.Data))
+ dataRange := newPkt.Data().AsRange()
+ icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmpHdr,
+ Src: route.LocalAddress,
+ Dst: route.RemoteAddress,
+ PayloadCsum: dataRange.Checksum(),
+ PayloadLen: dataRange.Size(),
+ }))
if err := route.WritePacket(
nil, /* gso */
stack.NetworkHeaderParams{
diff --git a/pkg/tcpip/network/ipv6/ipv6.go b/pkg/tcpip/network/ipv6/ipv6.go
index 7638ade35..544717678 100644
--- a/pkg/tcpip/network/ipv6/ipv6.go
+++ b/pkg/tcpip/network/ipv6/ipv6.go
@@ -619,7 +619,7 @@ func addIPHeader(srcAddr, dstAddr tcpip.Address, pkt *stack.PacketBuffer, params
}
func packetMustBeFragmented(pkt *stack.PacketBuffer, networkMTU uint32, gso *stack.GSO) bool {
- payload := pkt.TransportHeader().View().Size() + pkt.Data.Size()
+ payload := pkt.TransportHeader().View().Size() + pkt.Data().Size()
return (gso == nil || gso.Type == stack.GSONone) && uint32(payload) > networkMTU
}
@@ -819,14 +819,14 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
// WriteHeaderIncludedPacket implements stack.NetworkEndpoint.
func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBuffer) tcpip.Error {
// The packet already has an IP header, but there are a few required checks.
- h, ok := pkt.Data.PullUp(header.IPv6MinimumSize)
+ h, ok := pkt.Data().PullUp(header.IPv6MinimumSize)
if !ok {
return &tcpip.ErrMalformedHeader{}
}
ip := header.IPv6(h)
// Always set the payload length.
- pktSize := pkt.Data.Size()
+ pktSize := pkt.Data().Size()
ip.SetPayloadLength(uint16(pktSize - header.IPv6MinimumSize))
// Set the source address when zero.
@@ -964,7 +964,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
stats := e.stats.ip
h := header.IPv6(pkt.NetworkHeader().View())
- if !h.IsValid(pkt.Data.Size() + pkt.NetworkHeader().View().Size() + pkt.TransportHeader().View().Size()) {
+ if !h.IsValid(pkt.Data().Size() + pkt.NetworkHeader().View().Size() + pkt.TransportHeader().View().Size()) {
stats.MalformedPacketsReceived.Increment()
return
}
@@ -993,13 +993,14 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
return
}
+ // Create a VV to parse the packet. We don't plan to modify anything here.
// vv consists of:
// - Any IPv6 header bytes after the first 40 (i.e. extensions).
// - The transport header, if present.
// - Any other payload data.
vv := pkt.NetworkHeader().View()[header.IPv6MinimumSize:].ToVectorisedView()
vv.AppendView(pkt.TransportHeader().View())
- vv.Append(pkt.Data)
+ vv.AppendViews(pkt.Data().Views())
it := header.MakeIPv6PayloadIterator(header.IPv6ExtensionHeaderIdentifier(h.NextHeader()), vv)
// iptables filtering. All packets that reach here are intended for
@@ -1257,7 +1258,9 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
// have more extension headers in the reassembled payload, as per RFC
// 8200 section 4.5. We also use the NextHeader value from the first
// fragment.
- it = header.MakeIPv6PayloadIterator(header.IPv6ExtensionHeaderIdentifier(proto), pkt.Data)
+ data := pkt.Data()
+ dataVV := buffer.NewVectorisedView(data.Size(), data.Views())
+ it = header.MakeIPv6PayloadIterator(header.IPv6ExtensionHeaderIdentifier(proto), dataVV)
}
case header.IPv6DestinationOptionsExtHdr:
@@ -1314,7 +1317,7 @@ func (e *endpoint) handlePacket(pkt *stack.PacketBuffer) {
// For reassembled fragments, pkt.TransportHeader is unset, so this is a
// no-op and pkt.Data begins with the transport header.
extHdr.Buf.TrimFront(pkt.TransportHeader().View().Size())
- pkt.Data = extHdr.Buf
+ pkt.Data().Replace(extHdr.Buf)
stats.PacketsDelivered.Increment()
if p := tcpip.TransportProtocolNumber(extHdr.Identifier); p == header.ICMPv6ProtocolNumber {
diff --git a/pkg/tcpip/network/ipv6/mld.go b/pkg/tcpip/network/ipv6/mld.go
index 205e36cdd..dd153466d 100644
--- a/pkg/tcpip/network/ipv6/mld.go
+++ b/pkg/tcpip/network/ipv6/mld.go
@@ -236,7 +236,11 @@ func (mld *mldState) writePacket(destAddress, groupAddress tcpip.Address, mldTyp
localAddress = header.IPv6Any
}
- icmp.SetChecksum(header.ICMPv6Checksum(icmp, localAddress, destAddress, buffer.VectorisedView{}))
+ icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmp,
+ Src: localAddress,
+ Dst: destAddress,
+ }))
extensionHeaders := header.IPv6ExtHdrSerializer{
header.IPv6SerializableHopByHopExtHdr{
diff --git a/pkg/tcpip/network/ipv6/ndp.go b/pkg/tcpip/network/ipv6/ndp.go
index 721269c58..c22f60709 100644
--- a/pkg/tcpip/network/ipv6/ndp.go
+++ b/pkg/tcpip/network/ipv6/ndp.go
@@ -1721,7 +1721,11 @@ func (ndp *ndpState) startSolicitingRouters() {
icmpData.SetType(header.ICMPv6RouterSolicit)
rs := header.NDPRouterSolicit(icmpData.MessageBody())
rs.Options().Serialize(optsSerializer)
- icmpData.SetChecksum(header.ICMPv6Checksum(icmpData, localAddr, header.IPv6AllRoutersMulticastAddress, buffer.VectorisedView{}))
+ icmpData.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmpData,
+ Src: localAddr,
+ Dst: header.IPv6AllRoutersMulticastAddress,
+ }))
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(ndp.ep.MaxHeaderLength()),
@@ -1812,7 +1816,11 @@ func (e *endpoint) sendNDPNS(srcAddr, dstAddr, targetAddr tcpip.Address, remoteL
ns := header.NDPNeighborSolicit(icmp.MessageBody())
ns.SetTargetAddress(targetAddr)
ns.Options().Serialize(opts)
- icmp.SetChecksum(header.ICMPv6Checksum(icmp, srcAddr, dstAddr, buffer.VectorisedView{}))
+ icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
+ Header: icmp,
+ Src: srcAddr,
+ Dst: dstAddr,
+ }))
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(e.MaxHeaderLength()),