]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dns: optimize tx list walks
authorVictor Julien <victor@inliniac.net>
Tue, 17 Mar 2015 22:05:07 +0000 (23:05 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 20 Mar 2015 10:13:12 +0000 (11:13 +0100)
The detection engine and log engines can walk the tx list indirectly,
by looping AppLayerParserGetTx. This would lead to new list walks in
the DNS tx list though. Leading to bad performance.

This patch stores the last returned tx and uses that to determine if
the next tx is what we need next. If so, we can return that w/o list
walk.

src/app-layer-dns-common.c
src/app-layer-dns-common.h

index 95eaf131520e4a6ec5a8925bd046635995ba95c5..4d724dfaa4d117a1f20ea2186bb3166017ed802b 100644 (file)
@@ -173,15 +173,31 @@ void *DNSGetTx(void *alstate, uint64_t tx_id)
     DNSState *dns_state = (DNSState *)alstate;
     DNSTransaction *tx = NULL;
 
+    /* fast track: try the current tx */
     if (dns_state->curr && dns_state->curr->tx_num == tx_id + 1)
         return dns_state->curr;
 
+    /* fast track:
+     * if the prev tx_id is equal to the stored tx ptr, we can
+     * use this shortcut to get to the next. */
+    if (dns_state->iter) {
+        if (tx_id == dns_state->iter->tx_num) {
+            tx = TAILQ_NEXT(dns_state->iter, next);
+            if (tx && tx->tx_num == tx_id + 1) {
+                dns_state->iter = tx;
+                return tx;
+            }
+        }
+    }
+
+    /* no luck with the fast tracks, do the full list walk */
     TAILQ_FOREACH(tx, &dns_state->tx_list, next) {
         SCLogDebug("tx->tx_num %u, tx_id %"PRIu64, tx->tx_num, (tx_id+1));
         if ((tx_id+1) != tx->tx_num)
             continue;
 
         SCLogDebug("returning tx %p", tx);
+        dns_state->iter = tx;
         return tx;
     }
 
@@ -280,6 +296,9 @@ static void DNSTransactionFree(DNSTransaction *tx, DNSState *state)
     if (tx->de_state != NULL)
         DetectEngineStateFree(tx->de_state);
 
+    if (state->iter == tx)
+        state->iter = NULL;
+
     DNSDecrMemcap(sizeof(DNSTransaction), state);
     SCFree(tx);
     SCReturn;
index 5977a74df84153eda841beb3412a3a8adf3d84ff..d795f0cba6578ff1cb15cf9b6b4695670720b6ab 100644 (file)
@@ -156,6 +156,7 @@ typedef struct DNSTransaction_ {
 typedef struct DNSState_ {
     TAILQ_HEAD(, DNSTransaction_) tx_list;  /**< transaction list */
     DNSTransaction *curr;                   /**< ptr to current tx */
+    DNSTransaction *iter;
     uint64_t transaction_max;
     uint32_t unreplied_cnt;                 /**< number of unreplied requests in a row */
     uint32_t memuse;                        /**< state memuse, for comparing with