func BenchmarkSingleStreamSkips(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, SYN: true, Seq: 1000, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) skipped := false for i := 0; i < b.N; i++ { if i%10 == 9 { t.Seq += 10 skipped = true } else if skipped { t.Seq -= 20 } a.Assemble(netFlow, &t) if t.SYN { t.SYN = false t.Seq++ } t.Seq += 10 if skipped { t.Seq += 10 skipped = false } } }
func BenchmarkMultiStreamConn(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, Seq: 0, SYN: true, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { t.SrcPort = layers.TCPPort(i) a.Assemble(netFlow, &t) if i%65536 == 65535 { if t.SYN { t.SYN = false t.Seq += 1 } t.Seq += 10 } } }
func BenchmarkMultiStreamGrow(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, Seq: 0, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { t.SrcPort = layers.TCPPort(i) a.Assemble(netFlow, &t) t.Seq += 10 } }
func BenchmarkSingleStreamLoss(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, SYN: true, Seq: 1000, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { a.Assemble(netFlow, &t) t.SYN = false t.Seq += 11 } }
func (tcp *Tcp) Process(id *flows.FlowID, tcphdr *layers.TCP, pkt *protos.Packet) { // This Recover should catch all exceptions in // protocol modules. defer logp.Recover("Process tcp exception") stream, created := tcp.getStream(pkt) if stream.conn == nil { return } conn := stream.conn if id != nil { id.AddConnectionID(uint64(conn.id)) } if isDebug { debugf("tcp flow id: %p", id) } if len(pkt.Payload) == 0 && !tcphdr.FIN { // return early if packet is not interesting. Still need to find/create // stream first in order to update the TCP stream timer return } tcpStartSeq := tcphdr.Seq tcpSeq := tcpStartSeq + uint32(len(pkt.Payload)) lastSeq := conn.lastSeq[stream.dir] if isDebug { debugf("pkt.start_seq=%v pkt.last_seq=%v stream.last_seq=%v (len=%d)", tcpStartSeq, tcpSeq, lastSeq, len(pkt.Payload)) } if len(pkt.Payload) > 0 && lastSeq != 0 { if tcpSeqBeforeEq(tcpSeq, lastSeq) { if isDebug { debugf("Ignoring retransmitted segment. pkt.seq=%v len=%v stream.seq=%v", tcphdr.Seq, len(pkt.Payload), lastSeq) } return } switch tcpSeqCompare(lastSeq, tcpStartSeq) { case seqLT: // lastSeq < tcpStartSeq => Gap in tcp stream detected if created { break } gap := int(tcpStartSeq - lastSeq) debugf("Gap in tcp stream. last_seq: %d, seq: %d, gap: %d", lastSeq, tcpStartSeq, gap) drop := stream.gapInStream(gap) if drop { if isDebug { debugf("Dropping connection state because of gap") } droppedBecauseOfGaps.Add(1) // drop application layer connection state and // update stream_id for app layer analysers using stream_id for lookups conn.id = tcp.getId() conn.data = nil } case seqGT: // lastSeq > tcpStartSeq => overlapping TCP segment detected. shrink packet delta := lastSeq - tcpStartSeq if isDebug { debugf("Overlapping tcp segment. last_seq %d, seq: %d, delta: %d", lastSeq, tcpStartSeq, delta) } pkt.Payload = pkt.Payload[delta:] tcphdr.Seq += delta } } conn.lastSeq[stream.dir] = tcpSeq stream.addPacket(pkt, tcphdr) }