github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/network/fragmentation/fragmentation_test.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 "reflect" 19 "testing" 20 "time" 21 22 "github.com/FlowerWrong/netstack/tcpip/buffer" 23 ) 24 25 // vv is a helper to build VectorisedView from different strings. 26 func vv(size int, pieces ...string) buffer.VectorisedView { 27 views := make([]buffer.View, len(pieces)) 28 for i, p := range pieces { 29 views[i] = []byte(p) 30 } 31 32 return buffer.NewVectorisedView(size, views) 33 } 34 35 type processInput struct { 36 id uint32 37 first uint16 38 last uint16 39 more bool 40 vv buffer.VectorisedView 41 } 42 43 type processOutput struct { 44 vv buffer.VectorisedView 45 done bool 46 } 47 48 var processTestCases = []struct { 49 comment string 50 in []processInput 51 out []processOutput 52 }{ 53 { 54 comment: "One ID", 55 in: []processInput{ 56 {id: 0, first: 0, last: 1, more: true, vv: vv(2, "01")}, 57 {id: 0, first: 2, last: 3, more: false, vv: vv(2, "23")}, 58 }, 59 out: []processOutput{ 60 {vv: buffer.VectorisedView{}, done: false}, 61 {vv: vv(4, "01", "23"), done: true}, 62 }, 63 }, 64 { 65 comment: "Two IDs", 66 in: []processInput{ 67 {id: 0, first: 0, last: 1, more: true, vv: vv(2, "01")}, 68 {id: 1, first: 0, last: 1, more: true, vv: vv(2, "ab")}, 69 {id: 1, first: 2, last: 3, more: false, vv: vv(2, "cd")}, 70 {id: 0, first: 2, last: 3, more: false, vv: vv(2, "23")}, 71 }, 72 out: []processOutput{ 73 {vv: buffer.VectorisedView{}, done: false}, 74 {vv: buffer.VectorisedView{}, done: false}, 75 {vv: vv(4, "ab", "cd"), done: true}, 76 {vv: vv(4, "01", "23"), done: true}, 77 }, 78 }, 79 } 80 81 func TestFragmentationProcess(t *testing.T) { 82 for _, c := range processTestCases { 83 t.Run(c.comment, func(t *testing.T) { 84 f := NewFragmentation(1024, 512, DefaultReassembleTimeout) 85 for i, in := range c.in { 86 vv, done := f.Process(in.id, in.first, in.last, in.more, in.vv) 87 if !reflect.DeepEqual(vv, c.out[i].vv) { 88 t.Errorf("got Process(%d) = %+v, want = %+v", i, vv, c.out[i].vv) 89 } 90 if done != c.out[i].done { 91 t.Errorf("got Process(%d) = %+v, want = %+v", i, done, c.out[i].done) 92 } 93 if c.out[i].done { 94 if _, ok := f.reassemblers[in.id]; ok { 95 t.Errorf("Process(%d) did not remove buffer from reassemblers", i) 96 } 97 for n := f.rList.Front(); n != nil; n = n.Next() { 98 if n.id == in.id { 99 t.Errorf("Process(%d) did not remove buffer from rList", i) 100 } 101 } 102 } 103 } 104 }) 105 } 106 } 107 108 func TestReassemblingTimeout(t *testing.T) { 109 timeout := time.Millisecond 110 f := NewFragmentation(1024, 512, timeout) 111 // Send first fragment with id = 0, first = 0, last = 0, and more = true. 112 f.Process(0, 0, 0, true, vv(1, "0")) 113 // Sleep more than the timeout. 114 time.Sleep(2 * timeout) 115 // Send another fragment that completes a packet. 116 // However, no packet should be reassembled because the fragment arrived after the timeout. 117 _, done := f.Process(0, 1, 1, false, vv(1, "1")) 118 if done { 119 t.Errorf("Fragmentation does not respect the reassembling timeout.") 120 } 121 } 122 123 func TestMemoryLimits(t *testing.T) { 124 f := NewFragmentation(3, 1, DefaultReassembleTimeout) 125 // Send first fragment with id = 0. 126 f.Process(0, 0, 0, true, vv(1, "0")) 127 // Send first fragment with id = 1. 128 f.Process(1, 0, 0, true, vv(1, "1")) 129 // Send first fragment with id = 2. 130 f.Process(2, 0, 0, true, vv(1, "2")) 131 132 // Send first fragment with id = 3. This should caused id = 0 and id = 1 to be 133 // evicted. 134 f.Process(3, 0, 0, true, vv(1, "3")) 135 136 if _, ok := f.reassemblers[0]; ok { 137 t.Errorf("Memory limits are not respected: id=0 has not been evicted.") 138 } 139 if _, ok := f.reassemblers[1]; ok { 140 t.Errorf("Memory limits are not respected: id=1 has not been evicted.") 141 } 142 if _, ok := f.reassemblers[3]; !ok { 143 t.Errorf("Implementation of memory limits is wrong: id=3 is not present.") 144 } 145 } 146 147 func TestMemoryLimitsIgnoresDuplicates(t *testing.T) { 148 f := NewFragmentation(1, 0, DefaultReassembleTimeout) 149 // Send first fragment with id = 0. 150 f.Process(0, 0, 0, true, vv(1, "0")) 151 // Send the same packet again. 152 f.Process(0, 0, 0, true, vv(1, "0")) 153 154 got := f.size 155 want := 1 156 if got != want { 157 t.Errorf("Wrong size, duplicates are not handled correctly: got=%d, want=%d.", got, want) 158 } 159 }