app-layer: tx counter implementation

This patch adds a transaction counter for application layers
supporting it. Analysis is done after the parsing by the
different application layers.

This result in new data in the stats output, that looks like:
```
    "app-layer": {
      "tx": {
        "dns_udp": 21433,
        "http": 12766,
        "smtp": 0,
        "dns_tcp": 0
      }
    },
```
pull/2292/head
Eric Leblond 10 years ago committed by Giuseppe Longo
parent 675fa56497
commit a194dfbd5b

@ -923,6 +923,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow
AppLayerParserState *pstate = NULL;
AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto];
void *alstate = NULL;
uint64_t p_tx_cnt = 0;
/* we don't have the parser registered for this protocol */
if (p->StateAlloc == NULL)
@ -964,6 +965,10 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow
alstate, AppLayerGetProtoName(f->alproto));
}
if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
p_tx_cnt = AppLayerParserGetTxCnt(f->proto, alproto, f->alstate);
}
/* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
if (input_len > 0 || (flags & STREAM_EOF)) {
/* invoke the parser */
@ -1011,6 +1016,14 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow
}
}
if (AppLayerParserProtocolIsTxAware(f->proto, alproto)) {
if (likely(tv)) {
uint64_t cur_tx_cnt = AppLayerParserGetTxCnt(f->proto, alproto, f->alstate);
if (cur_tx_cnt > p_tx_cnt) {
AppLayerIncTxCounter(tv, f, cur_tx_cnt - p_tx_cnt);
}
}
}
/* next, see if we can get rid of transactions now */
AppLayerParserTransactionsCleanup(f);

@ -69,7 +69,9 @@ struct AppLayerThreadCtx_ {
typedef struct AppLayerCounters_ {
char *name;
char *tx_name;
uint16_t counter_id;
uint16_t counter_tx_id;
} AppLayerCounters;
AppLayerCounters applayer_counters[FLOW_PROTO_MAX][ALPROTO_MAX];
@ -98,6 +100,13 @@ static void AppLayerIncFlowCounter(ThreadVars *tv, Flow *f)
}
}
void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step)
{
if (likely(tv)) {
StatsAddUI64(tv, applayer_counters[f->protomap][f->alproto].counter_tx_id, step);
}
}
int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
Packet *p, Flow *f,
TcpSession *ssn, TcpStream *stream,
@ -696,31 +705,49 @@ void AppLayerSetupCounters()
for (alproto = 0; alproto < ALPROTO_MAX; alproto++) {
if (alprotos[alproto] == 1) {
char *str = "app_layer.flow.";
char *tx_str = "app_layer.tx.";
char *alproto_str = AppLayerGetProtoName(alproto);
int alproto_len = strlen(alproto_str) + 1;
uint8_t ipproto_map = FlowGetProtoMapping(ipprotos[ipproto]);
size_t size;
if (AppLayerParserProtoIsRegistered(ipprotos[ipproto], alproto) &&
AppLayerParserProtoIsRegistered(other_ipproto, alproto))
{
applayer_counters[ipproto_map][alproto].name =
SCMalloc(strlen(str) + alproto_len + strlen(ipproto_suffix));
size = strlen(str) + alproto_len + strlen(ipproto_suffix);
applayer_counters[ipproto_map][alproto].name = SCMalloc(size);
if (applayer_counters[ipproto_map][alproto].name == NULL) {
return;
}
snprintf(applayer_counters[ipproto_map][alproto].name,
strlen(str) + alproto_len + strlen(ipproto_suffix),
"%s%s%s", str, alproto_str, ipproto_suffix);
snprintf(applayer_counters[ipproto_map][alproto].name, size,
"%s%s%s", str, alproto_str, ipproto_suffix);
if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) {
size = strlen(tx_str) + alproto_len + strlen(ipproto_suffix);
applayer_counters[ipproto_map][alproto].tx_name = SCMalloc(size);
if (applayer_counters[ipproto_map][alproto].tx_name == NULL) {
return;
}
snprintf(applayer_counters[ipproto_map][alproto].tx_name, size,
"%s%s%s", tx_str, alproto_str, ipproto_suffix);
}
} else {
applayer_counters[ipproto_map][alproto].name =
SCMalloc(strlen(str) + alproto_len);
size = strlen(str) + alproto_len;
applayer_counters[ipproto_map][alproto].name = SCMalloc(size);
if (applayer_counters[ipproto_map][alproto].name == NULL) {
return;
}
snprintf(applayer_counters[ipproto_map][alproto].name,
strlen(str) + alproto_len,
"%s%s", str, alproto_str);
snprintf(applayer_counters[ipproto_map][alproto].name, size,
"%s%s", str, alproto_str);
if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) {
size = strlen(tx_str) + alproto_len;
applayer_counters[ipproto_map][alproto].tx_name = SCMalloc(size);
if (applayer_counters[ipproto_map][alproto].tx_name == NULL) {
return;
}
snprintf(applayer_counters[ipproto_map][alproto].tx_name, size,
"%s%s", tx_str, alproto_str);
}
}
}
}
@ -742,6 +769,11 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv)
uint8_t ipproto_map = FlowGetProtoMapping(ipprotos[ipproto]);
applayer_counters[ipproto_map][alproto].counter_id =
StatsRegisterCounter(applayer_counters[ipproto_map][alproto].name, tv);
if (AppLayerParserProtocolIsTxAware(ipprotos[ipproto], alproto)) {
applayer_counters[ipproto_map][alproto].counter_tx_id =
StatsRegisterCounter(applayer_counters[ipproto_map][alproto].tx_name, tv);
}
}
}
}
@ -764,6 +796,10 @@ void AppLayerDeSetupCounters()
applayer_counters[FlowGetProtoMapping(ipprotos[ipproto])][alproto].name = NULL;
}
}
if (applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name) {
SCFree(applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name);
applayer_counters[FlowGetProtoMapping(ipproto)][alproto].tx_name = NULL;
}
}
}
}

@ -143,4 +143,6 @@ void AppLayerRegisterGlobalCounters(void);
void AppLayerUnittestsRegister(void);
#endif
void AppLayerIncTxCounter(ThreadVars *tv, Flow *f, uint64_t step);
#endif

Loading…
Cancel
Save