github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/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 // 25 // for e := l.Front(); e != nil; e = e.Next() { 26 // // do something with e. 27 // } 28 // 29 // +stateify savable 30 type reassemblerList struct { 31 head *reassembler 32 tail *reassembler 33 } 34 35 // Reset resets list l to the empty state. 36 func (l *reassemblerList) Reset() { 37 l.head = nil 38 l.tail = nil 39 } 40 41 // Empty returns true iff the list is empty. 42 // 43 //go:nosplit 44 func (l *reassemblerList) Empty() bool { 45 return l.head == nil 46 } 47 48 // Front returns the first element of list l or nil. 49 // 50 //go:nosplit 51 func (l *reassemblerList) Front() *reassembler { 52 return l.head 53 } 54 55 // Back returns the last element of list l or nil. 56 // 57 //go:nosplit 58 func (l *reassemblerList) Back() *reassembler { 59 return l.tail 60 } 61 62 // Len returns the number of elements in the list. 63 // 64 // NOTE: This is an O(n) operation. 65 // 66 //go:nosplit 67 func (l *reassemblerList) Len() (count int) { 68 for e := l.Front(); e != nil; e = (reassemblerElementMapper{}.linkerFor(e)).Next() { 69 count++ 70 } 71 return count 72 } 73 74 // PushFront inserts the element e at the front of list l. 75 // 76 //go:nosplit 77 func (l *reassemblerList) PushFront(e *reassembler) { 78 linker := reassemblerElementMapper{}.linkerFor(e) 79 linker.SetNext(l.head) 80 linker.SetPrev(nil) 81 if l.head != nil { 82 reassemblerElementMapper{}.linkerFor(l.head).SetPrev(e) 83 } else { 84 l.tail = e 85 } 86 87 l.head = e 88 } 89 90 // PushFrontList inserts list m at the start of list l, emptying m. 91 // 92 //go:nosplit 93 func (l *reassemblerList) PushFrontList(m *reassemblerList) { 94 if l.head == nil { 95 l.head = m.head 96 l.tail = m.tail 97 } else if m.head != nil { 98 reassemblerElementMapper{}.linkerFor(l.head).SetPrev(m.tail) 99 reassemblerElementMapper{}.linkerFor(m.tail).SetNext(l.head) 100 101 l.head = m.head 102 } 103 m.head = nil 104 m.tail = nil 105 } 106 107 // PushBack inserts the element e at the back of list l. 108 // 109 //go:nosplit 110 func (l *reassemblerList) PushBack(e *reassembler) { 111 linker := reassemblerElementMapper{}.linkerFor(e) 112 linker.SetNext(nil) 113 linker.SetPrev(l.tail) 114 if l.tail != nil { 115 reassemblerElementMapper{}.linkerFor(l.tail).SetNext(e) 116 } else { 117 l.head = e 118 } 119 120 l.tail = e 121 } 122 123 // PushBackList inserts list m at the end of list l, emptying m. 124 // 125 //go:nosplit 126 func (l *reassemblerList) PushBackList(m *reassemblerList) { 127 if l.head == nil { 128 l.head = m.head 129 l.tail = m.tail 130 } else if m.head != nil { 131 reassemblerElementMapper{}.linkerFor(l.tail).SetNext(m.head) 132 reassemblerElementMapper{}.linkerFor(m.head).SetPrev(l.tail) 133 134 l.tail = m.tail 135 } 136 m.head = nil 137 m.tail = nil 138 } 139 140 // InsertAfter inserts e after b. 141 // 142 //go:nosplit 143 func (l *reassemblerList) InsertAfter(b, e *reassembler) { 144 bLinker := reassemblerElementMapper{}.linkerFor(b) 145 eLinker := reassemblerElementMapper{}.linkerFor(e) 146 147 a := bLinker.Next() 148 149 eLinker.SetNext(a) 150 eLinker.SetPrev(b) 151 bLinker.SetNext(e) 152 153 if a != nil { 154 reassemblerElementMapper{}.linkerFor(a).SetPrev(e) 155 } else { 156 l.tail = e 157 } 158 } 159 160 // InsertBefore inserts e before a. 161 // 162 //go:nosplit 163 func (l *reassemblerList) InsertBefore(a, e *reassembler) { 164 aLinker := reassemblerElementMapper{}.linkerFor(a) 165 eLinker := reassemblerElementMapper{}.linkerFor(e) 166 167 b := aLinker.Prev() 168 eLinker.SetNext(a) 169 eLinker.SetPrev(b) 170 aLinker.SetPrev(e) 171 172 if b != nil { 173 reassemblerElementMapper{}.linkerFor(b).SetNext(e) 174 } else { 175 l.head = e 176 } 177 } 178 179 // Remove removes e from l. 180 // 181 //go:nosplit 182 func (l *reassemblerList) Remove(e *reassembler) { 183 linker := reassemblerElementMapper{}.linkerFor(e) 184 prev := linker.Prev() 185 next := linker.Next() 186 187 if prev != nil { 188 reassemblerElementMapper{}.linkerFor(prev).SetNext(next) 189 } else if l.head == e { 190 l.head = next 191 } 192 193 if next != nil { 194 reassemblerElementMapper{}.linkerFor(next).SetPrev(prev) 195 } else if l.tail == e { 196 l.tail = prev 197 } 198 199 linker.SetNext(nil) 200 linker.SetPrev(nil) 201 } 202 203 // Entry is a default implementation of Linker. Users can add anonymous fields 204 // of this type to their structs to make them automatically implement the 205 // methods needed by List. 206 // 207 // +stateify savable 208 type reassemblerEntry struct { 209 next *reassembler 210 prev *reassembler 211 } 212 213 // Next returns the entry that follows e in the list. 214 // 215 //go:nosplit 216 func (e *reassemblerEntry) Next() *reassembler { 217 return e.next 218 } 219 220 // Prev returns the entry that precedes e in the list. 221 // 222 //go:nosplit 223 func (e *reassemblerEntry) Prev() *reassembler { 224 return e.prev 225 } 226 227 // SetNext assigns 'entry' as the entry that follows e in the list. 228 // 229 //go:nosplit 230 func (e *reassemblerEntry) SetNext(elem *reassembler) { 231 e.next = elem 232 } 233 234 // SetPrev assigns 'entry' as the entry that precedes e in the list. 235 // 236 //go:nosplit 237 func (e *reassemblerEntry) SetPrev(elem *reassembler) { 238 e.prev = elem 239 }