inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/network/internal/fragmentation/reassembler_list.go (about)

     1  package fragmentation
     2  
     3  // ElementMapper provides an identity mapping by default.
     4  //
     5  // This can be replaced to provide a struct that maps elements to linker
     6  // objects, if they are not the same. An ElementMapper is not typically
     7  // required if: Linker is left as is, Element is left as is, or Linker and
     8  // Element are the same type.
     9  type reassemblerElementMapper struct{}
    10  
    11  // linkerFor maps an Element to a Linker.
    12  //
    13  // This default implementation should be inlined.
    14  //
    15  //go:nosplit
    16  func (reassemblerElementMapper) linkerFor(elem *reassembler) *reassembler { return elem }
    17  
    18  // List is an intrusive list. Entries can be added to or removed from the list
    19  // in O(1) time and with no additional memory allocations.
    20  //
    21  // The zero value for List is an empty list ready to use.
    22  //
    23  // To iterate over a list (where l is a List):
    24  //      for e := l.Front(); e != nil; e = e.Next() {
    25  // 		// do something with e.
    26  //      }
    27  //
    28  // +stateify savable
    29  type reassemblerList struct {
    30  	head *reassembler
    31  	tail *reassembler
    32  }
    33  
    34  // Reset resets list l to the empty state.
    35  func (l *reassemblerList) Reset() {
    36  	l.head = nil
    37  	l.tail = nil
    38  }
    39  
    40  // Empty returns true iff the list is empty.
    41  //
    42  //go:nosplit
    43  func (l *reassemblerList) Empty() bool {
    44  	return l.head == nil
    45  }
    46  
    47  // Front returns the first element of list l or nil.
    48  //
    49  //go:nosplit
    50  func (l *reassemblerList) Front() *reassembler {
    51  	return l.head
    52  }
    53  
    54  // Back returns the last element of list l or nil.
    55  //
    56  //go:nosplit
    57  func (l *reassemblerList) Back() *reassembler {
    58  	return l.tail
    59  }
    60  
    61  // Len returns the number of elements in the list.
    62  //
    63  // NOTE: This is an O(n) operation.
    64  //
    65  //go:nosplit
    66  func (l *reassemblerList) Len() (count int) {
    67  	for e := l.Front(); e != nil; e = (reassemblerElementMapper{}.linkerFor(e)).Next() {
    68  		count++
    69  	}
    70  	return count
    71  }
    72  
    73  // PushFront inserts the element e at the front of list l.
    74  //
    75  //go:nosplit
    76  func (l *reassemblerList) PushFront(e *reassembler) {
    77  	linker := reassemblerElementMapper{}.linkerFor(e)
    78  	linker.SetNext(l.head)
    79  	linker.SetPrev(nil)
    80  	if l.head != nil {
    81  		reassemblerElementMapper{}.linkerFor(l.head).SetPrev(e)
    82  	} else {
    83  		l.tail = e
    84  	}
    85  
    86  	l.head = e
    87  }
    88  
    89  // PushBack inserts the element e at the back of list l.
    90  //
    91  //go:nosplit
    92  func (l *reassemblerList) PushBack(e *reassembler) {
    93  	linker := reassemblerElementMapper{}.linkerFor(e)
    94  	linker.SetNext(nil)
    95  	linker.SetPrev(l.tail)
    96  	if l.tail != nil {
    97  		reassemblerElementMapper{}.linkerFor(l.tail).SetNext(e)
    98  	} else {
    99  		l.head = e
   100  	}
   101  
   102  	l.tail = e
   103  }
   104  
   105  // PushBackList inserts list m at the end of list l, emptying m.
   106  //
   107  //go:nosplit
   108  func (l *reassemblerList) PushBackList(m *reassemblerList) {
   109  	if l.head == nil {
   110  		l.head = m.head
   111  		l.tail = m.tail
   112  	} else if m.head != nil {
   113  		reassemblerElementMapper{}.linkerFor(l.tail).SetNext(m.head)
   114  		reassemblerElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
   115  
   116  		l.tail = m.tail
   117  	}
   118  	m.head = nil
   119  	m.tail = nil
   120  }
   121  
   122  // InsertAfter inserts e after b.
   123  //
   124  //go:nosplit
   125  func (l *reassemblerList) InsertAfter(b, e *reassembler) {
   126  	bLinker := reassemblerElementMapper{}.linkerFor(b)
   127  	eLinker := reassemblerElementMapper{}.linkerFor(e)
   128  
   129  	a := bLinker.Next()
   130  
   131  	eLinker.SetNext(a)
   132  	eLinker.SetPrev(b)
   133  	bLinker.SetNext(e)
   134  
   135  	if a != nil {
   136  		reassemblerElementMapper{}.linkerFor(a).SetPrev(e)
   137  	} else {
   138  		l.tail = e
   139  	}
   140  }
   141  
   142  // InsertBefore inserts e before a.
   143  //
   144  //go:nosplit
   145  func (l *reassemblerList) InsertBefore(a, e *reassembler) {
   146  	aLinker := reassemblerElementMapper{}.linkerFor(a)
   147  	eLinker := reassemblerElementMapper{}.linkerFor(e)
   148  
   149  	b := aLinker.Prev()
   150  	eLinker.SetNext(a)
   151  	eLinker.SetPrev(b)
   152  	aLinker.SetPrev(e)
   153  
   154  	if b != nil {
   155  		reassemblerElementMapper{}.linkerFor(b).SetNext(e)
   156  	} else {
   157  		l.head = e
   158  	}
   159  }
   160  
   161  // Remove removes e from l.
   162  //
   163  //go:nosplit
   164  func (l *reassemblerList) Remove(e *reassembler) {
   165  	linker := reassemblerElementMapper{}.linkerFor(e)
   166  	prev := linker.Prev()
   167  	next := linker.Next()
   168  
   169  	if prev != nil {
   170  		reassemblerElementMapper{}.linkerFor(prev).SetNext(next)
   171  	} else if l.head == e {
   172  		l.head = next
   173  	}
   174  
   175  	if next != nil {
   176  		reassemblerElementMapper{}.linkerFor(next).SetPrev(prev)
   177  	} else if l.tail == e {
   178  		l.tail = prev
   179  	}
   180  
   181  	linker.SetNext(nil)
   182  	linker.SetPrev(nil)
   183  }
   184  
   185  // Entry is a default implementation of Linker. Users can add anonymous fields
   186  // of this type to their structs to make them automatically implement the
   187  // methods needed by List.
   188  //
   189  // +stateify savable
   190  type reassemblerEntry struct {
   191  	next *reassembler
   192  	prev *reassembler
   193  }
   194  
   195  // Next returns the entry that follows e in the list.
   196  //
   197  //go:nosplit
   198  func (e *reassemblerEntry) Next() *reassembler {
   199  	return e.next
   200  }
   201  
   202  // Prev returns the entry that precedes e in the list.
   203  //
   204  //go:nosplit
   205  func (e *reassemblerEntry) Prev() *reassembler {
   206  	return e.prev
   207  }
   208  
   209  // SetNext assigns 'entry' as the entry that follows e in the list.
   210  //
   211  //go:nosplit
   212  func (e *reassemblerEntry) SetNext(elem *reassembler) {
   213  	e.next = elem
   214  }
   215  
   216  // SetPrev assigns 'entry' as the entry that precedes e in the list.
   217  //
   218  //go:nosplit
   219  func (e *reassemblerEntry) SetPrev(elem *reassembler) {
   220  	e.prev = elem
   221  }