github.com/vpnishe/netstack@v1.10.6/tcpip/network/fragmentation/frag_heap.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fragmentation 16 17 import ( 18 "container/heap" 19 "fmt" 20 21 "github.com/vpnishe/netstack/tcpip/buffer" 22 ) 23 24 type fragment struct { 25 offset uint16 26 vv buffer.VectorisedView 27 } 28 29 type fragHeap []fragment 30 31 func (h *fragHeap) Len() int { 32 return len(*h) 33 } 34 35 func (h *fragHeap) Less(i, j int) bool { 36 return (*h)[i].offset < (*h)[j].offset 37 } 38 39 func (h *fragHeap) Swap(i, j int) { 40 (*h)[i], (*h)[j] = (*h)[j], (*h)[i] 41 } 42 43 func (h *fragHeap) Push(x interface{}) { 44 *h = append(*h, x.(fragment)) 45 } 46 47 func (h *fragHeap) Pop() interface{} { 48 old := *h 49 n := len(old) 50 x := old[n-1] 51 *h = old[:n-1] 52 return x 53 } 54 55 // reassamble empties the heap and returns a VectorisedView 56 // containing a reassambled version of the fragments inside the heap. 57 func (h *fragHeap) reassemble() (buffer.VectorisedView, error) { 58 curr := heap.Pop(h).(fragment) 59 views := curr.vv.Views() 60 size := curr.vv.Size() 61 62 if curr.offset != 0 { 63 return buffer.VectorisedView{}, fmt.Errorf("offset of the first packet is != 0 (%d)", curr.offset) 64 } 65 66 for h.Len() > 0 { 67 curr := heap.Pop(h).(fragment) 68 if int(curr.offset) < size { 69 curr.vv.TrimFront(size - int(curr.offset)) 70 } else if int(curr.offset) > size { 71 return buffer.VectorisedView{}, fmt.Errorf("packet has a hole, expected offset %d, got %d", size, curr.offset) 72 } 73 size += curr.vv.Size() 74 views = append(views, curr.vv.Views()...) 75 } 76 return buffer.NewVectorisedView(size, views), nil 77 }