github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/link/sharedmem/queue/queue_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 queue 16 17 import ( 18 "encoding/binary" 19 "reflect" 20 "testing" 21 22 "github.com/FlowerWrong/netstack/tcpip/link/sharedmem/pipe" 23 ) 24 25 func TestBasicTxQueue(t *testing.T) { 26 // Tests that a basic transmit on a queue works, and that completion 27 // gets properly reported as well. 28 pb1 := make([]byte, 100) 29 pb2 := make([]byte, 100) 30 31 var rxp pipe.Rx 32 rxp.Init(pb1) 33 34 var txp pipe.Tx 35 txp.Init(pb2) 36 37 var q Tx 38 q.Init(pb1, pb2) 39 40 // Enqueue two buffers. 41 b := []TxBuffer{ 42 {nil, 100, 60}, 43 {nil, 200, 40}, 44 } 45 46 b[0].Next = &b[1] 47 48 const usedID = 1002 49 const usedTotalSize = 100 50 if !q.Enqueue(usedID, usedTotalSize, 2, &b[0]) { 51 t.Fatalf("Enqueue failed on empty queue") 52 } 53 54 // Check the contents of the pipe. 55 d := rxp.Pull() 56 if d == nil { 57 t.Fatalf("Tx pipe is empty after Enqueue") 58 } 59 60 want := []byte{ 61 234, 3, 0, 0, 0, 0, 0, 0, // id 62 100, 0, 0, 0, // total size 63 0, 0, 0, 0, // reserved 64 100, 0, 0, 0, 0, 0, 0, 0, // offset 1 65 60, 0, 0, 0, // size 1 66 200, 0, 0, 0, 0, 0, 0, 0, // offset 2 67 40, 0, 0, 0, // size 2 68 } 69 70 if !reflect.DeepEqual(want, d) { 71 t.Fatalf("Bad posted packet: got %v, want %v", d, want) 72 } 73 74 rxp.Flush() 75 76 // Check that there are no completions yet. 77 if _, ok := q.CompletedPacket(); ok { 78 t.Fatalf("Packet reported as completed too soon") 79 } 80 81 // Post a completion. 82 d = txp.Push(8) 83 if d == nil { 84 t.Fatalf("Unable to push to rx pipe") 85 } 86 binary.LittleEndian.PutUint64(d, usedID) 87 txp.Flush() 88 89 // Check that completion is properly reported. 90 id, ok := q.CompletedPacket() 91 if !ok { 92 t.Fatalf("Completion not reported") 93 } 94 95 if id != usedID { 96 t.Fatalf("Bad completion id: got %v, want %v", id, usedID) 97 } 98 } 99 100 func TestBasicRxQueue(t *testing.T) { 101 // Tests that a basic receive on a queue works. 102 pb1 := make([]byte, 100) 103 pb2 := make([]byte, 100) 104 105 var rxp pipe.Rx 106 rxp.Init(pb1) 107 108 var txp pipe.Tx 109 txp.Init(pb2) 110 111 var q Rx 112 q.Init(pb1, pb2, nil) 113 114 // Post two buffers. 115 b := []RxBuffer{ 116 {100, 60, 1077, 0}, 117 {200, 40, 2123, 0}, 118 } 119 120 if !q.PostBuffers(b) { 121 t.Fatalf("PostBuffers failed on empty queue") 122 } 123 124 // Check the contents of the pipe. 125 want := [][]byte{ 126 { 127 100, 0, 0, 0, 0, 0, 0, 0, // Offset1 128 60, 0, 0, 0, // Size1 129 0, 0, 0, 0, // Remaining in group 1 130 0, 0, 0, 0, 0, 0, 0, 0, // User data 1 131 53, 4, 0, 0, 0, 0, 0, 0, // ID 1 132 }, 133 { 134 200, 0, 0, 0, 0, 0, 0, 0, // Offset2 135 40, 0, 0, 0, // Size2 136 0, 0, 0, 0, // Remaining in group 2 137 0, 0, 0, 0, 0, 0, 0, 0, // User data 2 138 75, 8, 0, 0, 0, 0, 0, 0, // ID 2 139 }, 140 } 141 142 for i := range b { 143 d := rxp.Pull() 144 if d == nil { 145 t.Fatalf("Tx pipe is empty after PostBuffers") 146 } 147 148 if !reflect.DeepEqual(want[i], d) { 149 t.Fatalf("Bad posted packet: got %v, want %v", d, want[i]) 150 } 151 152 rxp.Flush() 153 } 154 155 // Check that there are no completions. 156 if _, n := q.Dequeue(nil); n != 0 { 157 t.Fatalf("Packet reported as received too soon") 158 } 159 160 // Post a completion. 161 d := txp.Push(sizeOfConsumedPacketHeader + 2*sizeOfConsumedBuffer) 162 if d == nil { 163 t.Fatalf("Unable to push to rx pipe") 164 } 165 166 copy(d, []byte{ 167 100, 0, 0, 0, // packet size 168 0, 0, 0, 0, // reserved 169 170 100, 0, 0, 0, 0, 0, 0, 0, // offset 1 171 60, 0, 0, 0, // size 1 172 0, 0, 0, 0, 0, 0, 0, 0, // user data 1 173 53, 4, 0, 0, 0, 0, 0, 0, // ID 1 174 175 200, 0, 0, 0, 0, 0, 0, 0, // offset 2 176 40, 0, 0, 0, // size 2 177 0, 0, 0, 0, 0, 0, 0, 0, // user data 2 178 75, 8, 0, 0, 0, 0, 0, 0, // ID 2 179 }) 180 181 txp.Flush() 182 183 // Check that completion is properly reported. 184 bufs, n := q.Dequeue(nil) 185 if n != 100 { 186 t.Fatalf("Bad packet size: got %v, want %v", n, 100) 187 } 188 189 if !reflect.DeepEqual(bufs, b) { 190 t.Fatalf("Bad returned buffers: got %v, want %v", bufs, b) 191 } 192 } 193 194 func TestBadTxCompletion(t *testing.T) { 195 // Check that tx completions with bad sizes are properly ignored. 196 pb1 := make([]byte, 100) 197 pb2 := make([]byte, 100) 198 199 var rxp pipe.Rx 200 rxp.Init(pb1) 201 202 var txp pipe.Tx 203 txp.Init(pb2) 204 205 var q Tx 206 q.Init(pb1, pb2) 207 208 // Post a completion that is too short, and check that it is ignored. 209 if d := txp.Push(7); d == nil { 210 t.Fatalf("Unable to push to rx pipe") 211 } 212 txp.Flush() 213 214 if _, ok := q.CompletedPacket(); ok { 215 t.Fatalf("Bad completion not ignored") 216 } 217 218 // Post a completion that is too long, and check that it is ignored. 219 if d := txp.Push(10); d == nil { 220 t.Fatalf("Unable to push to rx pipe") 221 } 222 txp.Flush() 223 224 if _, ok := q.CompletedPacket(); ok { 225 t.Fatalf("Bad completion not ignored") 226 } 227 } 228 229 func TestBadRxCompletion(t *testing.T) { 230 // Check that bad rx completions are properly ignored. 231 pb1 := make([]byte, 100) 232 pb2 := make([]byte, 100) 233 234 var rxp pipe.Rx 235 rxp.Init(pb1) 236 237 var txp pipe.Tx 238 txp.Init(pb2) 239 240 var q Rx 241 q.Init(pb1, pb2, nil) 242 243 // Post a completion that is too short, and check that it is ignored. 244 if d := txp.Push(7); d == nil { 245 t.Fatalf("Unable to push to rx pipe") 246 } 247 txp.Flush() 248 249 if b, _ := q.Dequeue(nil); b != nil { 250 t.Fatalf("Bad completion not ignored") 251 } 252 253 // Post a completion whose buffer sizes add up to less than the total 254 // size. 255 d := txp.Push(sizeOfConsumedPacketHeader + 2*sizeOfConsumedBuffer) 256 if d == nil { 257 t.Fatalf("Unable to push to rx pipe") 258 } 259 260 copy(d, []byte{ 261 100, 0, 0, 0, // packet size 262 0, 0, 0, 0, // reserved 263 264 100, 0, 0, 0, 0, 0, 0, 0, // offset 1 265 10, 0, 0, 0, // size 1 266 0, 0, 0, 0, 0, 0, 0, 0, // user data 1 267 53, 4, 0, 0, 0, 0, 0, 0, // ID 1 268 269 200, 0, 0, 0, 0, 0, 0, 0, // offset 2 270 10, 0, 0, 0, // size 2 271 0, 0, 0, 0, 0, 0, 0, 0, // user data 2 272 75, 8, 0, 0, 0, 0, 0, 0, // ID 2 273 }) 274 275 txp.Flush() 276 if b, _ := q.Dequeue(nil); b != nil { 277 t.Fatalf("Bad completion not ignored") 278 } 279 280 // Post a completion whose buffer sizes will cause a 32-bit overflow, 281 // but adds up to the right number. 282 d = txp.Push(sizeOfConsumedPacketHeader + 2*sizeOfConsumedBuffer) 283 if d == nil { 284 t.Fatalf("Unable to push to rx pipe") 285 } 286 287 copy(d, []byte{ 288 100, 0, 0, 0, // packet size 289 0, 0, 0, 0, // reserved 290 291 100, 0, 0, 0, 0, 0, 0, 0, // offset 1 292 255, 255, 255, 255, // size 1 293 0, 0, 0, 0, 0, 0, 0, 0, // user data 1 294 53, 4, 0, 0, 0, 0, 0, 0, // ID 1 295 296 200, 0, 0, 0, 0, 0, 0, 0, // offset 2 297 101, 0, 0, 0, // size 2 298 0, 0, 0, 0, 0, 0, 0, 0, // user data 2 299 75, 8, 0, 0, 0, 0, 0, 0, // ID 2 300 }) 301 302 txp.Flush() 303 if b, _ := q.Dequeue(nil); b != nil { 304 t.Fatalf("Bad completion not ignored") 305 } 306 } 307 308 func TestFillTxPipe(t *testing.T) { 309 // Check that transmitting a new buffer when the buffer pipe is full 310 // fails gracefully. 311 pb1 := make([]byte, 104) 312 pb2 := make([]byte, 104) 313 314 var rxp pipe.Rx 315 rxp.Init(pb1) 316 317 var txp pipe.Tx 318 txp.Init(pb2) 319 320 var q Tx 321 q.Init(pb1, pb2) 322 323 // Transmit twice, which should fill the tx pipe. 324 b := []TxBuffer{ 325 {nil, 100, 60}, 326 {nil, 200, 40}, 327 } 328 329 b[0].Next = &b[1] 330 331 const usedID = 1002 332 const usedTotalSize = 100 333 for i := uint64(0); i < 2; i++ { 334 if !q.Enqueue(usedID+i, usedTotalSize, 2, &b[0]) { 335 t.Fatalf("Failed to transmit buffer") 336 } 337 } 338 339 // Transmit another packet now that the tx pipe is full. 340 if q.Enqueue(usedID+2, usedTotalSize, 2, &b[0]) { 341 t.Fatalf("Enqueue succeeded when tx pipe is full") 342 } 343 } 344 345 func TestFillRxPipe(t *testing.T) { 346 // Check that posting a new buffer when the buffer pipe is full fails 347 // gracefully. 348 pb1 := make([]byte, 100) 349 pb2 := make([]byte, 100) 350 351 var rxp pipe.Rx 352 rxp.Init(pb1) 353 354 var txp pipe.Tx 355 txp.Init(pb2) 356 357 var q Rx 358 q.Init(pb1, pb2, nil) 359 360 // Post a buffer twice, it should fill the tx pipe. 361 b := []RxBuffer{ 362 {100, 60, 1077, 0}, 363 } 364 365 for i := 0; i < 2; i++ { 366 if !q.PostBuffers(b) { 367 t.Fatalf("PostBuffers failed on non-full queue") 368 } 369 } 370 371 // Post another buffer now that the tx pipe is full. 372 if q.PostBuffers(b) { 373 t.Fatalf("PostBuffers succeeded on full queue") 374 } 375 } 376 377 func TestLotsOfTransmissions(t *testing.T) { 378 // Make sure pipes are being properly flushed when transmitting packets. 379 pb1 := make([]byte, 100) 380 pb2 := make([]byte, 100) 381 382 var rxp pipe.Rx 383 rxp.Init(pb1) 384 385 var txp pipe.Tx 386 txp.Init(pb2) 387 388 var q Tx 389 q.Init(pb1, pb2) 390 391 // Prepare packet with two buffers. 392 b := []TxBuffer{ 393 {nil, 100, 60}, 394 {nil, 200, 40}, 395 } 396 397 b[0].Next = &b[1] 398 399 const usedID = 1002 400 const usedTotalSize = 100 401 402 // Post 100000 packets and completions. 403 for i := 100000; i > 0; i-- { 404 if !q.Enqueue(usedID, usedTotalSize, 2, &b[0]) { 405 t.Fatalf("Enqueue failed on non-full queue") 406 } 407 408 if d := rxp.Pull(); d == nil { 409 t.Fatalf("Tx pipe is empty after Enqueue") 410 } 411 rxp.Flush() 412 413 d := txp.Push(8) 414 if d == nil { 415 t.Fatalf("Unable to write to rx pipe") 416 } 417 binary.LittleEndian.PutUint64(d, usedID) 418 txp.Flush() 419 if _, ok := q.CompletedPacket(); !ok { 420 t.Fatalf("Completion not returned") 421 } 422 } 423 } 424 425 func TestLotsOfReceptions(t *testing.T) { 426 // Make sure pipes are being properly flushed when receiving packets. 427 pb1 := make([]byte, 100) 428 pb2 := make([]byte, 100) 429 430 var rxp pipe.Rx 431 rxp.Init(pb1) 432 433 var txp pipe.Tx 434 txp.Init(pb2) 435 436 var q Rx 437 q.Init(pb1, pb2, nil) 438 439 // Prepare for posting two buffers. 440 b := []RxBuffer{ 441 {100, 60, 1077, 0}, 442 {200, 40, 2123, 0}, 443 } 444 445 // Post 100000 buffers and completions. 446 for i := 100000; i > 0; i-- { 447 if !q.PostBuffers(b) { 448 t.Fatalf("PostBuffers failed on non-full queue") 449 } 450 451 if d := rxp.Pull(); d == nil { 452 t.Fatalf("Tx pipe is empty after PostBuffers") 453 } 454 rxp.Flush() 455 456 if d := rxp.Pull(); d == nil { 457 t.Fatalf("Tx pipe is empty after PostBuffers") 458 } 459 rxp.Flush() 460 461 d := txp.Push(sizeOfConsumedPacketHeader + 2*sizeOfConsumedBuffer) 462 if d == nil { 463 t.Fatalf("Unable to push to rx pipe") 464 } 465 466 copy(d, []byte{ 467 100, 0, 0, 0, // packet size 468 0, 0, 0, 0, // reserved 469 470 100, 0, 0, 0, 0, 0, 0, 0, // offset 1 471 60, 0, 0, 0, // size 1 472 0, 0, 0, 0, 0, 0, 0, 0, // user data 1 473 53, 4, 0, 0, 0, 0, 0, 0, // ID 1 474 475 200, 0, 0, 0, 0, 0, 0, 0, // offset 2 476 40, 0, 0, 0, // size 2 477 0, 0, 0, 0, 0, 0, 0, 0, // user data 2 478 75, 8, 0, 0, 0, 0, 0, 0, // ID 2 479 }) 480 481 txp.Flush() 482 483 if _, n := q.Dequeue(nil); n == 0 { 484 t.Fatalf("Dequeue failed when there is a completion") 485 } 486 } 487 } 488 489 func TestRxEnableNotification(t *testing.T) { 490 // Check that enabling nofifications results in properly updated state. 491 pb1 := make([]byte, 100) 492 pb2 := make([]byte, 100) 493 494 var state uint32 495 var q Rx 496 q.Init(pb1, pb2, &state) 497 498 q.EnableNotification() 499 if state != eventFDEnabled { 500 t.Fatalf("Bad value in shared state: got %v, want %v", state, eventFDEnabled) 501 } 502 } 503 504 func TestRxDisableNotification(t *testing.T) { 505 // Check that disabling nofifications results in properly updated state. 506 pb1 := make([]byte, 100) 507 pb2 := make([]byte, 100) 508 509 var state uint32 510 var q Rx 511 q.Init(pb1, pb2, &state) 512 513 q.DisableNotification() 514 if state != eventFDDisabled { 515 t.Fatalf("Bad value in shared state: got %v, want %v", state, eventFDDisabled) 516 } 517 }