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 }