diff options
Diffstat (limited to 'pkg/tcpip/network')
-rw-r--r-- | pkg/tcpip/network/internal/fragmentation/fragmentation.go | 6 | ||||
-rw-r--r-- | pkg/tcpip/network/internal/fragmentation/fragmentation_test.go | 16 | ||||
-rw-r--r-- | pkg/tcpip/network/internal/fragmentation/reassembler.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/network/internal/fragmentation/reassembler_test.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/network/ip_test.go | 21 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv4/icmp.go | 25 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv4/igmp.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv4/igmp_test.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv4/ipv4.go | 20 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv4/ipv4_test.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/icmp.go | 104 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/icmp_test.go | 52 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/ipv6.go | 17 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/ipv6_test.go | 14 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/mld.go | 6 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/mld_test.go | 10 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/ndp.go | 12 | ||||
-rw-r--r-- | pkg/tcpip/network/ipv6/ndp_test.go | 44 | ||||
-rw-r--r-- | pkg/tcpip/network/multicast_group_test.go | 14 |
19 files changed, 251 insertions, 126 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/fragmentation_test.go b/pkg/tcpip/network/internal/fragmentation/fragmentation_test.go index 47ea3173e..7daf64b4a 100644 --- a/pkg/tcpip/network/internal/fragmentation/fragmentation_test.go +++ b/pkg/tcpip/network/internal/fragmentation/fragmentation_test.go @@ -121,7 +121,7 @@ func TestFragmentationProcess(t *testing.T) { in.id, in.first, in.last, in.more, in.proto, done, c.out[i].done) } if c.out[i].done { - if diff := cmp.Diff(c.out[i].vv.ToOwnedView(), resPkt.Data.ToOwnedView()); diff != "" { + if diff := cmp.Diff(c.out[i].vv.ToOwnedView(), resPkt.Data().AsRange().ToOwnedView()); diff != "" { t.Errorf("got Process(%+v, %d, %d, %t, %d, %#v) result mismatch (-want, +got):\n%s", in.id, in.first, in.last, in.more, in.proto, in.pkt, diff) } @@ -470,9 +470,7 @@ func TestPacketFragmenter(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkt := testutil.MakeRandPkt(test.transportHeaderLen, reserve, []int{test.payloadSize}, proto) - var originalPayload buffer.VectorisedView - originalPayload.AppendView(pkt.TransportHeader().View()) - originalPayload.Append(pkt.Data) + originalPayload := stack.PayloadSince(pkt.TransportHeader()) var reassembledPayload buffer.VectorisedView pf := MakePacketFragmenter(pkt, test.fragmentPayloadLen, reserve) for i := 0; ; i++ { @@ -499,7 +497,7 @@ func TestPacketFragmenter(t *testing.T) { if got := fragPkt.TransportHeader().View().Size(); got != 0 { t.Errorf("(fragment #%d) got fragPkt.TransportHeader().View().Size() = %d, want = 0", i, got) } - reassembledPayload.Append(fragPkt.Data) + reassembledPayload.AppendViews(fragPkt.Data().Views()) if !more { if i != len(test.wantFragments)-1 { t.Errorf("got fragment count = %d, want = %d", i, len(test.wantFragments)-1) @@ -507,7 +505,7 @@ func TestPacketFragmenter(t *testing.T) { break } } - if diff := cmp.Diff(reassembledPayload.ToView(), originalPayload.ToView()); diff != "" { + if diff := cmp.Diff(reassembledPayload.ToView(), originalPayload); diff != "" { t.Errorf("reassembledPayload mismatch (-want +got):\n%s", diff) } }) @@ -625,11 +623,11 @@ func TestTimeoutHandler(t *testing.T) { } switch { case handler.pkt != nil && test.wantPkt == nil: - t.Errorf("got handler.pkt = not nil (pkt.Data = %x), want = nil", handler.pkt.Data.ToView()) + t.Errorf("got handler.pkt = not nil (pkt.Data = %x), want = nil", handler.pkt.Data().AsRange().ToOwnedView()) case handler.pkt == nil && test.wantPkt != nil: - t.Errorf("got handler.pkt = nil, want = not nil (pkt.Data = %x)", test.wantPkt.Data.ToView()) + t.Errorf("got handler.pkt = nil, want = not nil (pkt.Data = %x)", test.wantPkt.Data().AsRange().ToOwnedView()) case handler.pkt != nil && test.wantPkt != nil: - if diff := cmp.Diff(test.wantPkt.Data.ToView(), handler.pkt.Data.ToView()); diff != "" { + if diff := cmp.Diff(test.wantPkt.Data().AsRange().ToOwnedView(), handler.pkt.Data().AsRange().ToOwnedView()); diff != "" { t.Errorf("pkt.Data mismatch (-want, +got):\n%s", diff) } } 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/internal/fragmentation/reassembler_test.go b/pkg/tcpip/network/internal/fragmentation/reassembler_test.go index 214a93709..cfd9f00ef 100644 --- a/pkg/tcpip/network/internal/fragmentation/reassembler_test.go +++ b/pkg/tcpip/network/internal/fragmentation/reassembler_test.go @@ -204,7 +204,7 @@ func TestReassemblerProcess(t *testing.T) { if a == nil || b == nil { return a == b } - return bytes.Equal(a.Data.ToOwnedView(), b.Data.ToOwnedView()) + return bytes.Equal(a.Data().AsRange().ToOwnedView(), b.Data().AsRange().ToOwnedView()) } if isDone { diff --git a/pkg/tcpip/network/ip_test.go b/pkg/tcpip/network/ip_test.go index 90236ed9e..aee1652fa 100644 --- a/pkg/tcpip/network/ip_test.go +++ b/pkg/tcpip/network/ip_test.go @@ -90,8 +90,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) { - v := vv.ToView() +func (t *testObject) checkValues(protocol tcpip.TransportProtocolNumber, v buffer.View, srcAddr, dstAddr tcpip.Address) { if protocol != t.protocol { t.t.Errorf("protocol = %v, want %v", protocol, t.protocol) } @@ -120,7 +119,7 @@ func (t *testObject) checkValues(protocol tcpip.TransportProtocolNumber, vv buff // parsing are expected. func (t *testObject) DeliverTransportPacket(protocol tcpip.TransportProtocolNumber, pkt *stack.PacketBuffer) stack.TransportPacketDisposition { netHdr := pkt.Network() - t.checkValues(protocol, pkt.Data, netHdr.SourceAddress(), netHdr.DestinationAddress()) + t.checkValues(protocol, pkt.Data().AsRange().ToOwnedView(), netHdr.SourceAddress(), netHdr.DestinationAddress()) t.dataCalls++ return stack.TransportPacketHandled } @@ -129,7 +128,7 @@ func (t *testObject) DeliverTransportPacket(protocol tcpip.TransportProtocolNumb // incoming control (ICMP) packets. This is used by the test object to verify // that the results of the parsing are expected. func (t *testObject) DeliverTransportError(local, remote tcpip.Address, net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, transErr stack.TransportError, pkt *stack.PacketBuffer) { - t.checkValues(trans, pkt.Data, remote, local) + t.checkValues(trans, pkt.Data().AsRange().ToOwnedView(), remote, local) if diff := cmp.Diff( t.transErr, transportError{ @@ -198,7 +197,7 @@ func (t *testObject) WritePacket(_ *stack.Route, _ *stack.GSO, protocol tcpip.Ne srcAddr = h.SourceAddress() dstAddr = h.DestinationAddress() } - t.checkValues(prot, pkt.Data, srcAddr, dstAddr) + t.checkValues(prot, pkt.Data().AsRange().ToOwnedView(), srcAddr, dstAddr) return nil } @@ -371,7 +370,11 @@ func TestSourceAddressValidation(t *testing.T) { pkt.SetType(header.ICMPv6EchoRequest) pkt.SetCode(0) pkt.SetChecksum(0) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, src, localIPv6Addr, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: src, + Dst: localIPv6Addr, + })) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ PayloadLength: header.ICMPv6MinimumSize, @@ -1199,7 +1202,11 @@ func TestIPv6ReceiveControl(t *testing.T) { nic.testObject.transErr = c.transErr // Set ICMPv6 checksum. - icmp.SetChecksum(header.ICMPv6Checksum(icmp, outerSrcAddr, localIPv6Addr, buffer.VectorisedView{})) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: outerSrcAddr, + Dst: localIPv6Addr, + })) addressableEndpoint, ok := ep.(stack.AddressableEndpoint) if !ok { 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/igmp_test.go b/pkg/tcpip/network/ipv4/igmp_test.go index c5f68e411..e5e1b89cc 100644 --- a/pkg/tcpip/network/ipv4/igmp_test.go +++ b/pkg/tcpip/network/ipv4/igmp_test.go @@ -106,9 +106,9 @@ func createAndInjectIGMPPacket(e *channel.Endpoint, igmpType header.IGMPType, ma igmp.SetGroupAddress(groupAddress) igmp.SetChecksum(header.IGMPCalculateChecksum(igmp)) - e.InjectInbound(ipv4.ProtocolNumber, &stack.PacketBuffer{ + e.InjectInbound(ipv4.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{ Data: buf.ToVectorisedView(), - }) + })) } // TestIGMPV1Present tests the node's ability to fallback to V1 when a V1 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/ipv4/ipv4_test.go b/pkg/tcpip/network/ipv4/ipv4_test.go index dc4db6e5f..26d9696d7 100644 --- a/pkg/tcpip/network/ipv4/ipv4_test.go +++ b/pkg/tcpip/network/ipv4/ipv4_test.go @@ -1211,7 +1211,7 @@ func compareFragments(packets []*stack.PacketBuffer, sourcePacket *stack.PacketB sourceCopy.SetFlagsFragmentOffset(sourceCopy.Flags()&^header.IPv4FlagMoreFragments, wantFragments[i].offset) } reassembledPayload.AppendView(packet.TransportHeader().View()) - reassembledPayload.Append(packet.Data) + reassembledPayload.AppendView(packet.Data().AsRange().ToOwnedView()) // Clear out the checksum and length from the ip because we can't compare // it. sourceCopy.SetTotalLength(wantFragments[i].payloadSize + header.IPv4MinimumSize) 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/icmp_test.go b/pkg/tcpip/network/ipv6/icmp_test.go index c27164344..d4e63710c 100644 --- a/pkg/tcpip/network/ipv6/icmp_test.go +++ b/pkg/tcpip/network/ipv6/icmp_test.go @@ -324,7 +324,13 @@ func TestICMPCounts(t *testing.T) { icmp := header.ICMPv6(buffer.NewView(typ.size + len(typ.extraData))) copy(icmp[typ.size:], typ.extraData) icmp.SetType(typ.typ) - icmp.SetChecksum(header.ICMPv6Checksum(icmp[:typ.size], lladdr0, lladdr1, buffer.View(typ.extraData).ToVectorisedView())) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp[:typ.size], + Src: lladdr0, + Dst: lladdr1, + PayloadCsum: header.Checksum(typ.extraData, 0 /* initial */), + PayloadLen: len(typ.extraData), + })) handleICMPInIPv6(ep, lladdr1, lladdr0, icmp, typ.hopLimit, typ.includeRouterAlert) } @@ -498,7 +504,11 @@ 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(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: r.LocalAddress, + Dst: r.RemoteAddress, + })) // We can't send our payload directly over the route because that // doesn't provoke NDP discovery. @@ -687,7 +697,11 @@ func TestICMPChecksumValidationSimple(t *testing.T) { copy(icmp[typ.size:], typ.extraData) icmp.SetType(typ.typ) if checksum { - icmp.SetChecksum(header.ICMPv6Checksum(icmp, lladdr1, lladdr0, buffer.View{}.ToVectorisedView())) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: lladdr1, + Dst: lladdr0, + })) } ip := header.IPv6(buffer.NewView(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -879,7 +893,11 @@ func TestICMPChecksumValidationWithPayload(t *testing.T) { payloadFn(icmpHdr.Payload()) if checksum { - icmpHdr.SetChecksum(header.ICMPv6Checksum(icmpHdr, lladdr1, lladdr0, buffer.VectorisedView{})) + icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmpHdr, + Src: lladdr1, + Dst: lladdr0, + })) } ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) @@ -1058,7 +1076,13 @@ func TestICMPChecksumValidationWithPayloadMultipleViews(t *testing.T) { payloadFn(payload) if checksum { - icmpHdr.SetChecksum(header.ICMPv6Checksum(icmpHdr, lladdr1, lladdr0, payload.ToVectorisedView())) + icmpHdr.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmpHdr, + Src: lladdr1, + Dst: lladdr0, + PayloadCsum: header.Checksum(payload, 0 /* initial */), + PayloadLen: len(payload), + })) } ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) @@ -1324,7 +1348,11 @@ func TestPacketQueing(t *testing.T) { pkt.SetType(header.ICMPv6EchoRequest) pkt.SetCode(0) pkt.SetChecksum(0) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: host2IPv6Addr.AddressWithPrefix.Address, + Dst: host1IPv6Addr.AddressWithPrefix.Address, + })) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ PayloadLength: header.ICMPv6MinimumSize, @@ -1422,7 +1450,11 @@ func TestPacketQueing(t *testing.T) { na.Options().Serialize(header.NDPOptionsSerializer{ header.NDPTargetLinkLayerAddressOption(host2NICLinkAddr), }) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: host2IPv6Addr.AddressWithPrefix.Address, + Dst: host1IPv6Addr.AddressWithPrefix.Address, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -1661,7 +1693,11 @@ func TestCallsToNeighborCache(t *testing.T) { } icmp := test.createPacket() - icmp.SetChecksum(header.ICMPv6Checksum(icmp, test.source, test.destination, buffer.VectorisedView{})) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: test.source, + Dst: test.destination, + })) handleICMPInIPv6(ep, test.source, test.destination, icmp, header.NDPHopLimit, false) // Confirm the endpoint calls the correct NUDHandler method. 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/ipv6_test.go b/pkg/tcpip/network/ipv6/ipv6_test.go index 05c9f4dbf..266a53e3b 100644 --- a/pkg/tcpip/network/ipv6/ipv6_test.go +++ b/pkg/tcpip/network/ipv6/ipv6_test.go @@ -68,7 +68,11 @@ func testReceiveICMP(t *testing.T, s *stack.Stack, e *channel.Endpoint, src, dst hdr := buffer.NewPrependable(header.IPv6MinimumSize + header.ICMPv6NeighborAdvertMinimumSize) pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertMinimumSize)) pkt.SetType(header.ICMPv6NeighborAdvert) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, src, dst, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: src, + Dst: dst, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -216,7 +220,7 @@ func compareFragments(packets []*stack.PacketBuffer, sourcePacket *stack.PacketB // Store the reassembled payload as we parse each fragment. The payload // includes the Transport header and everything after. reassembledPayload.AppendView(fragment.TransportHeader().View()) - reassembledPayload.Append(fragment.Data) + reassembledPayload.AppendView(fragment.Data().AsRange().ToOwnedView()) } if diff := cmp.Diff(buffer.View(source[sourceIPHeadersLen:]), reassembledPayload.ToView()); diff != "" { @@ -3065,7 +3069,11 @@ func TestForwarding(t *testing.T) { icmp.SetType(header.ICMPv6EchoRequest) icmp.SetCode(header.ICMPv6UnusedCode) icmp.SetChecksum(0) - icmp.SetChecksum(header.ICMPv6Checksum(icmp, remoteIPv6Addr1, remoteIPv6Addr2, buffer.VectorisedView{})) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: remoteIPv6Addr1, + Dst: remoteIPv6Addr2, + })) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ PayloadLength: header.ICMPv6MinimumSize, 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/mld_test.go b/pkg/tcpip/network/ipv6/mld_test.go index f1b8d58f2..9a425e50a 100644 --- a/pkg/tcpip/network/ipv6/mld_test.go +++ b/pkg/tcpip/network/ipv6/mld_test.go @@ -326,11 +326,15 @@ func createAndInjectMLDPacket(e *channel.Endpoint, mldType header.ICMPv6Type, ho mld := header.MLD(icmp.MessageBody()) mld.SetMaximumResponseDelay(0) mld.SetMulticastAddress(header.IPv6Any) - icmp.SetChecksum(header.ICMPv6Checksum(icmp, srcAddress, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{})) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: srcAddress, + Dst: header.IPv6AllNodesMulticastAddress, + })) - e.InjectInbound(ipv6.ProtocolNumber, &stack.PacketBuffer{ + e.InjectInbound(ipv6.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{ Data: buf.ToVectorisedView(), - }) + })) } func TestMLDPacketValidation(t *testing.T) { 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()), diff --git a/pkg/tcpip/network/ipv6/ndp_test.go b/pkg/tcpip/network/ipv6/ndp_test.go index ce20af0e3..0d53c260d 100644 --- a/pkg/tcpip/network/ipv6/ndp_test.go +++ b/pkg/tcpip/network/ipv6/ndp_test.go @@ -215,7 +215,11 @@ func TestNeighborSolicitationWithSourceLinkLayerOption(t *testing.T) { ns.SetTargetAddress(lladdr0) opts := ns.Options() copy(opts, test.optsBuf) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: lladdr1, + Dst: lladdr0, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -478,7 +482,11 @@ func TestNeighborSolicitationResponse(t *testing.T) { ns.SetTargetAddress(nicAddr) opts := ns.Options() opts.Serialize(test.nsOpts) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, test.nsSrc, test.nsDst, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: test.nsSrc, + Dst: test.nsDst, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -554,7 +562,11 @@ func TestNeighborSolicitationResponse(t *testing.T) { na.SetOverrideFlag(true) na.SetTargetAddress(test.nsSrc) na.Options().Serialize(ser) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, test.nsSrc, nicAddr, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: test.nsSrc, + Dst: nicAddr, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -657,7 +669,11 @@ func TestNeighborAdvertisementWithTargetLinkLayerOption(t *testing.T) { ns.SetTargetAddress(lladdr1) opts := ns.Options() copy(opts, test.optsBuf) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, lladdr0, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: lladdr1, + Dst: lladdr0, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -874,7 +890,13 @@ func TestNDPValidation(t *testing.T) { copy(icmp[typ.size:], typ.extraData) icmp.SetType(typ.typ) icmp.SetCode(test.code) - icmp.SetChecksum(header.ICMPv6Checksum(icmp[:typ.size], lladdr0, lladdr1, buffer.View(typ.extraData).ToVectorisedView())) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp[:typ.size], + Src: lladdr0, + Dst: lladdr1, + PayloadCsum: header.Checksum(typ.extraData /* initial */, 0), + PayloadLen: len(typ.extraData), + })) // Rx count of the NDP message should initially be 0. if got := typStat.Value(); got != 0 { @@ -987,7 +1009,11 @@ func TestNeighborAdvertisementValidation(t *testing.T) { na := header.NDPNeighborAdvert(pkt.MessageBody()) na.SetTargetAddress(lladdr1) na.SetSolicitedFlag(test.solicitedFlag) - pkt.SetChecksum(header.ICMPv6Checksum(pkt, lladdr1, test.ipDstAddr, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: lladdr1, + Dst: test.ipDstAddr, + })) payloadLength := hdr.UsedLength() ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ @@ -1182,7 +1208,11 @@ func TestRouterAdvertValidation(t *testing.T) { pkt.SetCode(test.code) copy(pkt.MessageBody(), test.ndpPayload) payloadLength := hdr.UsedLength() - pkt.SetChecksum(header.ICMPv6Checksum(pkt, test.src, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{})) + pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: pkt, + Src: test.src, + Dst: header.IPv6AllNodesMulticastAddress, + })) ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) ip.Encode(&header.IPv6Fields{ PayloadLength: uint16(payloadLength), diff --git a/pkg/tcpip/network/multicast_group_test.go b/pkg/tcpip/network/multicast_group_test.go index 73913aef8..ecd5003a7 100644 --- a/pkg/tcpip/network/multicast_group_test.go +++ b/pkg/tcpip/network/multicast_group_test.go @@ -230,9 +230,9 @@ func createAndInjectIGMPPacket(e *channel.Endpoint, igmpType byte, maxRespTime b igmp.SetGroupAddress(groupAddress) igmp.SetChecksum(header.IGMPCalculateChecksum(igmp)) - e.InjectInbound(ipv4.ProtocolNumber, &stack.PacketBuffer{ + e.InjectInbound(ipv4.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{ Data: buf.ToVectorisedView(), - }) + })) } // createAndInjectMLDPacket creates and injects an MLD packet with the @@ -263,11 +263,15 @@ func createAndInjectMLDPacket(e *channel.Endpoint, mldType uint8, maxRespDelay b mld := header.MLD(icmp.MessageBody()) mld.SetMaximumResponseDelay(uint16(maxRespDelay)) mld.SetMulticastAddress(groupAddress) - icmp.SetChecksum(header.ICMPv6Checksum(icmp, linkLocalIPv6Addr2, header.IPv6AllNodesMulticastAddress, buffer.VectorisedView{})) + icmp.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{ + Header: icmp, + Src: linkLocalIPv6Addr2, + Dst: header.IPv6AllNodesMulticastAddress, + })) - e.InjectInbound(ipv6.ProtocolNumber, &stack.PacketBuffer{ + e.InjectInbound(ipv6.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{ Data: buf.ToVectorisedView(), - }) + })) } // TestMGPDisabled tests that the multicast group protocol is not enabled by |