diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index e3ee004875..cebdd53544 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -466,6 +466,19 @@ int StreamTcpReassemblyConfig(char quiet) if (!quiet) SCLogInfo("stream.reassembly \"chunk-prealloc\": %u", stream_chunk_prealloc); StreamMsgQueuesInit(stream_chunk_prealloc); + + intmax_t zero_copy_size = 128; + if (ConfGetInt("stream.reassembly.zero-copy-size", &zero_copy_size) == 1) { + if (zero_copy_size < 0 || zero_copy_size > 0xffff) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "stream.reassembly.zero-copy-size of " + "%"PRIiMAX" is invalid: valid values are 0 to 65535", zero_copy_size); + return -1; + } + } + stream_config.zero_copy_size = (uint16_t)zero_copy_size; + if (!quiet) + SCLogInfo("stream.reassembly \"zero-copy-size\": %u", stream_config.zero_copy_size); + return 0; } @@ -2577,7 +2590,10 @@ static inline int DoReassemble(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Packet *p) { /* fast path 1: segment is exactly what we need */ - if (likely(rd->data_len == 0 && SEQ_EQ(seg->seq, rd->ra_base_seq+1) && SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len)))) { + if (likely(rd->data_len == 0 && + SEQ_EQ(seg->seq, rd->ra_base_seq+1) && + SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len)))) + { /* process single segment directly */ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream, seg->payload, seg->payload_len, @@ -2596,7 +2612,11 @@ static inline int DoReassemble(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, } return 1; /* fast path 2: segment acked completely, meets minimal size req for 0copy processing */ - } else if (rd->data_len == 0 && SEQ_EQ(seg->seq, rd->ra_base_seq+1) && SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) && seg->payload_len >= 128) { + } else if (rd->data_len == 0 && + SEQ_EQ(seg->seq, rd->ra_base_seq+1) && + SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) && + seg->payload_len >= stream_config.zero_copy_size) + { /* process single segment directly */ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream, seg->payload, seg->payload_len, diff --git a/src/stream-tcp.h b/src/stream-tcp.h index b8a31855af..113e2e88a1 100644 --- a/src/stream-tcp.h +++ b/src/stream-tcp.h @@ -51,6 +51,9 @@ typedef struct TcpStreamCnf_ { uint32_t ssn_init_flags; /**< new ssn flags will be initialized to this */ uint8_t segment_init_flags; /**< new seg flags will be initialized to this */ + uint16_t zero_copy_size; /**< use zero copy for app layer above segments + * of this size */ + uint32_t prealloc_sessions; /**< ssns to prealloc per stream thread */ int midstream; int async_oneside; diff --git a/suricata.yaml.in b/suricata.yaml.in index 04cb3b2285..2bb208381e 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -785,6 +785,11 @@ flow-timeouts: # - size: 4 # Size of the (data)segment for a pool # prealloc: 256 # Number of segments to prealloc and keep # # in the pool. +# zero-copy-size: 128 # This option sets in bytes the value at +# # which segment data is passed to the app +# # layer API directly. Data sizes equal to +# # and higher than the value set are passed +# # on directly. # stream: memcap: 32mb @@ -816,6 +821,7 @@ stream: # prealloc: 1024 # - size: 65535 # prealloc: 128 + #zero-copy-size: 128 # Host table: #