github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/link/qdisc/fifo/packet_buffer_queue.go (about)

     1  // Copyright 2020 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 fifo
    16  
    17  import (
    18  	"github.com/SagerNet/gvisor/pkg/sync"
    19  	"github.com/SagerNet/gvisor/pkg/tcpip/stack"
    20  )
    21  
    22  // packetBufferQueue is a bounded, thread-safe queue of PacketBuffers.
    23  //
    24  type packetBufferQueue struct {
    25  	mu    sync.Mutex
    26  	list  stack.PacketBufferList
    27  	limit int
    28  	used  int
    29  }
    30  
    31  // emptyLocked determines if the queue is empty.
    32  // Preconditions: q.mu must be held.
    33  func (q *packetBufferQueue) emptyLocked() bool {
    34  	return q.used == 0
    35  }
    36  
    37  // empty determines if the queue is empty.
    38  func (q *packetBufferQueue) empty() bool {
    39  	q.mu.Lock()
    40  	r := q.emptyLocked()
    41  	q.mu.Unlock()
    42  
    43  	return r
    44  }
    45  
    46  // setLimit updates the limit. No PacketBuffers are immediately dropped in case
    47  // the queue becomes full due to the new limit.
    48  func (q *packetBufferQueue) setLimit(limit int) {
    49  	q.mu.Lock()
    50  	q.limit = limit
    51  	q.mu.Unlock()
    52  }
    53  
    54  // enqueue adds the given packet to the queue.
    55  //
    56  // Returns true when the PacketBuffer is successfully added to the queue, in
    57  // which case ownership of the reference is transferred to the queue. And
    58  // returns false if the queue is full, in which case ownership is retained by
    59  // the caller.
    60  func (q *packetBufferQueue) enqueue(s *stack.PacketBuffer) bool {
    61  	q.mu.Lock()
    62  	r := q.used < q.limit
    63  	if r {
    64  		q.list.PushBack(s)
    65  		q.used++
    66  	}
    67  	q.mu.Unlock()
    68  
    69  	return r
    70  }
    71  
    72  // dequeue removes and returns the next PacketBuffer from queue, if one exists.
    73  // Ownership is transferred to the caller.
    74  func (q *packetBufferQueue) dequeue() *stack.PacketBuffer {
    75  	q.mu.Lock()
    76  	s := q.list.Front()
    77  	if s != nil {
    78  		q.list.Remove(s)
    79  		q.used--
    80  	}
    81  	q.mu.Unlock()
    82  
    83  	return s
    84  }