stream: use reassembly fast path after proto detect

Use the reassembly fast paths only after protocol detection has completed.
In some corner cases the sending of smaller segments lead to protocol
detection failing.
pull/1652/head
Victor Julien 10 years ago
parent 34ed15e182
commit 596465b76d

@ -2620,51 +2620,58 @@ static inline int DoReassemble(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
TcpSession *ssn, TcpStream *stream, TcpSegment *seg, ReassembleData *rd, TcpSession *ssn, TcpStream *stream, TcpSegment *seg, ReassembleData *rd,
Packet *p) Packet *p)
{ {
/* fast path 1: segment is exactly what we need */ /* fast paths: send data directly into the app layer, w/o first doing
if (likely(rd->data_len == 0 && * a copy step. However, don't use the fast path until protocol detection
SEQ_EQ(seg->seq, rd->ra_base_seq+1) && * has been completed
SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len)))) * TODO if initial data is big enough for proto detect, we could do the
{ * fast path anyway. */
/* process single segment directly */ if (stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) {
AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream, /* fast path 1: segment is exactly what we need */
seg->payload, seg->payload_len, if (likely(rd->data_len == 0 &&
StreamGetAppLayerFlags(ssn, stream, p)); SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
AppLayerProfilingStore(ra_ctx->app_tctx, p); SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len))))
rd->data_sent += seg->payload_len; {
rd->ra_base_seq += seg->payload_len; /* process single segment directly */
AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
seg->payload, seg->payload_len,
StreamGetAppLayerFlags(ssn, stream, p));
AppLayerProfilingStore(ra_ctx->app_tctx, p);
rd->data_sent += seg->payload_len;
rd->ra_base_seq += seg->payload_len;
#ifdef DEBUG #ifdef DEBUG
ra_ctx->fp1++; ra_ctx->fp1++;
#endif #endif
/* if after the first data chunk we have no alproto yet, /* if after the first data chunk we have no alproto yet,
* there is no point in continueing here. */ * there is no point in continueing here. */
if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) { if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
SCLogDebug("no alproto after first data chunk"); SCLogDebug("no alproto after first data chunk");
return 0; return 0;
} }
return 1; return 1;
/* fast path 2: segment acked completely, meets minimal size req for 0copy processing */ /* fast path 2: segment acked completely, meets minimal size req for 0copy processing */
} else if (rd->data_len == 0 && } else if (rd->data_len == 0 &&
SEQ_EQ(seg->seq, rd->ra_base_seq+1) && SEQ_EQ(seg->seq, rd->ra_base_seq+1) &&
SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) && SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) &&
seg->payload_len >= stream_config.zero_copy_size) seg->payload_len >= stream_config.zero_copy_size)
{ {
/* process single segment directly */ /* process single segment directly */
AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream, AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
seg->payload, seg->payload_len, seg->payload, seg->payload_len,
StreamGetAppLayerFlags(ssn, stream, p)); StreamGetAppLayerFlags(ssn, stream, p));
AppLayerProfilingStore(ra_ctx->app_tctx, p); AppLayerProfilingStore(ra_ctx->app_tctx, p);
rd->data_sent += seg->payload_len; rd->data_sent += seg->payload_len;
rd->ra_base_seq += seg->payload_len; rd->ra_base_seq += seg->payload_len;
#ifdef DEBUG #ifdef DEBUG
ra_ctx->fp2++; ra_ctx->fp2++;
#endif #endif
/* if after the first data chunk we have no alproto yet, /* if after the first data chunk we have no alproto yet,
* there is no point in continueing here. */ * there is no point in continueing here. */
if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) { if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
SCLogDebug("no alproto after first data chunk"); SCLogDebug("no alproto after first data chunk");
return 0; return 0;
}
return 1;
} }
return 1;
} }
#ifdef DEBUG #ifdef DEBUG
ra_ctx->sp++; ra_ctx->sp++;

Loading…
Cancel
Save