github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/tcpip/stack/packet_buffer_list.go (about)

     1  // Copyright 2022 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  //     http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package stack
    15  
    16  // PacketBufferList is a slice-backed list. All operations are O(1) unless
    17  // otherwise noted.
    18  //
    19  // Note: this is intentionally backed by a slice, not an intrusive list. We've
    20  // switched PacketBufferList back-and-forth between intrusive list and
    21  // slice-backed implementations, and the latter has proven to be preferable:
    22  //
    23  //   - Intrusive lists are a refcounting nightmare, as modifying the list
    24  //     sometimes-but-not-always modifies the list for others.
    25  //   - The slice-backed implementation has been benchmarked and is slightly more
    26  //     performant.
    27  //
    28  // +stateify savable
    29  type PacketBufferList struct {
    30  	pbs []*PacketBuffer
    31  }
    32  
    33  // AsSlice returns a slice containing the packets in the list.
    34  //
    35  //go:nosplit
    36  func (pl *PacketBufferList) AsSlice() []*PacketBuffer {
    37  	return pl.pbs
    38  }
    39  
    40  // Reset decrements all elements and resets the list to the empty state.
    41  //
    42  //go:nosplit
    43  func (pl *PacketBufferList) Reset() {
    44  	for i, pb := range pl.pbs {
    45  		pb.DecRef()
    46  		pl.pbs[i] = nil
    47  	}
    48  	pl.pbs = pl.pbs[:0]
    49  }
    50  
    51  // Len returns the number of elements in the list.
    52  //
    53  //go:nosplit
    54  func (pl *PacketBufferList) Len() int {
    55  	return len(pl.pbs)
    56  }
    57  
    58  // PushBack inserts the PacketBuffer at the back of the list.
    59  //
    60  //go:nosplit
    61  func (pl *PacketBufferList) PushBack(pb *PacketBuffer) {
    62  	pl.pbs = append(pl.pbs, pb)
    63  }
    64  
    65  // DecRef decreases the reference count on each PacketBuffer
    66  // stored in the list.
    67  //
    68  // NOTE: runs in O(n) time.
    69  //
    70  //go:nosplit
    71  func (pl PacketBufferList) DecRef() {
    72  	for _, pb := range pl.pbs {
    73  		pb.DecRef()
    74  	}
    75  }