tcpPacketsCanCoalesce evaluates if pkt can be coalesced with the packet described by item. This function makes considerations that match the kernel's GRO self tests, which can be found in tools/testing/selftests/net/gro.c.
(pkt []byte, iphLen, tcphLen uint8, seq uint32, pshSet bool, gsoSize uint16, item tcpGROItem, bufs [][]byte, bufsOffset int)
| 332 | // described by item. This function makes considerations that match the kernel's |
| 333 | // GRO self tests, which can be found in tools/testing/selftests/net/gro.c. |
| 334 | func tcpPacketsCanCoalesce(pkt []byte, iphLen, tcphLen uint8, seq uint32, pshSet bool, gsoSize uint16, item tcpGROItem, bufs [][]byte, bufsOffset int) canCoalesce { |
| 335 | pktTarget := bufs[item.bufsIndex][bufsOffset:] |
| 336 | if tcphLen != item.tcphLen { |
| 337 | // cannot coalesce with unequal tcp options len |
| 338 | return coalesceUnavailable |
| 339 | } |
| 340 | if tcphLen > 20 { |
| 341 | if !bytes.Equal(pkt[iphLen+20:iphLen+tcphLen], pktTarget[item.iphLen+20:iphLen+tcphLen]) { |
| 342 | // cannot coalesce with unequal tcp options |
| 343 | return coalesceUnavailable |
| 344 | } |
| 345 | } |
| 346 | if !ipHeadersCanCoalesce(pkt, pktTarget) { |
| 347 | return coalesceUnavailable |
| 348 | } |
| 349 | // seq adjacency |
| 350 | lhsLen := item.gsoSize |
| 351 | lhsLen += item.numMerged * item.gsoSize |
| 352 | if seq == item.sentSeq+uint32(lhsLen) { // pkt aligns following item from a seq num perspective |
| 353 | if item.pshSet { |
| 354 | // We cannot append to a segment that has the PSH flag set, PSH |
| 355 | // can only be set on the final segment in a reassembled group. |
| 356 | return coalesceUnavailable |
| 357 | } |
| 358 | if len(pktTarget[iphLen+tcphLen:])%int(item.gsoSize) != 0 { |
| 359 | // A smaller than gsoSize packet has been appended previously. |
| 360 | // Nothing can come after a smaller packet on the end. |
| 361 | return coalesceUnavailable |
| 362 | } |
| 363 | if gsoSize > item.gsoSize { |
| 364 | // We cannot have a larger packet following a smaller one. |
| 365 | return coalesceUnavailable |
| 366 | } |
| 367 | return coalesceAppend |
| 368 | } else if seq+uint32(gsoSize) == item.sentSeq { // pkt aligns in front of item from a seq num perspective |
| 369 | if pshSet { |
| 370 | // We cannot prepend with a segment that has the PSH flag set, PSH |
| 371 | // can only be set on the final segment in a reassembled group. |
| 372 | return coalesceUnavailable |
| 373 | } |
| 374 | if gsoSize < item.gsoSize { |
| 375 | // We cannot have a larger packet following a smaller one. |
| 376 | return coalesceUnavailable |
| 377 | } |
| 378 | if gsoSize > item.gsoSize && item.numMerged > 0 { |
| 379 | // There's at least one previous merge, and we're larger than all |
| 380 | // previous. This would put multiple smaller packets on the end. |
| 381 | return coalesceUnavailable |
| 382 | } |
| 383 | return coalescePrepend |
| 384 | } |
| 385 | return coalesceUnavailable |
| 386 | } |
| 387 | |
| 388 | func checksumValid(pkt []byte, iphLen, proto uint8, isV6 bool) bool { |
| 389 | srcAddrAt := ipv4SrcAddrOffset |
no test coverage detected