lane_entry_test.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package batch
  2. //TODO refactor this away
  3. // This file holds the lanes' self-parsing Commit entries and the proto-checking parsers behind
  4. // them. Production traffic enters the lanes only through MultiCoalescer.dispatch and the At
  5. // parsers; these wrappers reproduce that path (including seal-all on unparseable shapes) on top
  6. // of a local parse, so tests and benches can drive one lane with nothing but a packet.
  7. // parseIPPrologue resolves the IP version, requires the L4 protocol to match wantProto (6 TCP,
  8. // 17 UDP), and defers to the shared per-version cores. Returns the trimmed packet and the L4
  9. // offset; fk must be zero on entry and is filled in place.
  10. func (fk *flowKey) parseIPPrologue(pkt []byte, wantProto byte) ([]byte, int, bool) {
  11. if len(pkt) < 20 {
  12. return nil, 0, false
  13. }
  14. switch pkt[0] >> 4 {
  15. case 4:
  16. if pkt[9] != wantProto {
  17. return nil, 0, false
  18. }
  19. trimmed, ok := fk.parseIPv4Prologue(pkt)
  20. return trimmed, 20, ok
  21. case 6:
  22. if len(pkt) < 40 {
  23. return nil, 0, false
  24. }
  25. if pkt[6] != wantProto {
  26. return nil, 0, false
  27. }
  28. trimmed, ok := fk.parseIPv6Prologue(pkt)
  29. return trimmed, 40, ok
  30. }
  31. return nil, 0, false
  32. }
  33. // parseBase extracts the flow key and IP/TCP offsets for any TCP packet, admissible for
  34. // coalescing or not. Returns false for non-TCP or malformed input.
  35. func (p *parsedTCP) parseBase(pkt []byte) bool {
  36. trimmed, ipHdrLen, ok := p.fk.parseIPPrologue(pkt, ipProtoTCP)
  37. if !ok {
  38. return false
  39. }
  40. return p.parseTail(trimmed, ipHdrLen)
  41. }
  42. // parseBase extracts the flow key and IP/UDP offsets for a UDP packet.
  43. func (p *parsedUDP) parseBase(pkt []byte) bool {
  44. trimmed, ipHdrLen, ok := p.fk.parseIPPrologue(pkt, ipProtoUDP)
  45. if !ok {
  46. return false
  47. }
  48. return p.parseTail(trimmed, ipHdrLen)
  49. }
  50. // Commit borrows pkt. The caller must keep pkt valid until the next Flush.
  51. func (c *TCPCoalescer) Commit(pkt []byte) error {
  52. var info parsedTCP
  53. if !info.parseBase(pkt) {
  54. // Unparseable: flow key unknown, seal everything so later data cannot emit ahead of it.
  55. c.sealAllOpen()
  56. c.addVerbatim(pkt)
  57. return nil
  58. }
  59. return c.commitParsed(pkt, &info)
  60. }
  61. // Commit borrows pkt. The caller must keep pkt valid until the next Flush.
  62. func (c *UDPCoalescer) Commit(pkt []byte) error {
  63. var info parsedUDP
  64. if !info.parseBase(pkt) {
  65. c.sealAllOpen()
  66. c.addVerbatim(pkt)
  67. return nil
  68. }
  69. return c.commitParsed(pkt, &info)
  70. }