Coverage Report

Created: 2025-12-31 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/packet-queue.c
Line
Count
Source
1
/* Copyright (C) 2007-2019 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 *
23
 * Packet Queue portion of the engine.
24
 */
25
26
#include "suricata-common.h"
27
#include "decode.h"
28
#include "packet-queue.h"
29
#include "threads.h"
30
#include "suricata.h"
31
#include "util-var.h"
32
#include "pkt-var.h"
33
#include "util-validate.h"
34
35
#ifdef DEBUG
36
void PacketQueueValidateDebug(PacketQueue *q);
37
void PacketQueueValidate(PacketQueue *q);
38
39
void PacketQueueValidateDebug(PacketQueue *q)
40
{
41
    SCLogDebug("q->len %u, q->top %p, q->bot %p", q->len, q->top, q->bot);
42
43
    if (q->len == 0) {
44
        BUG_ON(q->top != NULL);
45
        BUG_ON(q->bot != NULL);
46
    } else if(q->len == 1) {
47
        SCLogDebug("q->top->next %p, q->top->prev %p", q->top->next, q->top->prev);
48
        SCLogDebug("q->bot->next %p, q->bot->prev %p", q->bot->next, q->bot->prev);
49
50
        BUG_ON(q->top != q->bot);
51
        BUG_ON(q->top->next != NULL);
52
        BUG_ON(q->bot->next != NULL);
53
        BUG_ON(q->top->prev != NULL);
54
        BUG_ON(q->bot->prev != NULL);
55
    } else if (q->len == 2) {
56
        SCLogDebug("q->top->next %p, q->top->prev %p", q->top->next, q->top->prev);
57
        SCLogDebug("q->bot->next %p, q->bot->prev %p", q->bot->next, q->bot->prev);
58
59
        BUG_ON(q->top == NULL);
60
        BUG_ON(q->bot == NULL);
61
62
        BUG_ON(q->top == q->bot);
63
64
        BUG_ON(q->top->prev != NULL);
65
        BUG_ON(q->top->next != q->bot);
66
67
        BUG_ON(q->bot->prev != q->top);
68
        BUG_ON(q->bot->next != NULL);
69
    } else {
70
        BUG_ON(q->top == NULL);
71
        BUG_ON(q->bot == NULL);
72
73
        SCLogDebug("q->top->next %p, q->top->prev %p", q->top->next, q->top->prev);
74
        SCLogDebug("q->bot->next %p, q->bot->prev %p", q->bot->next, q->bot->prev);
75
76
        BUG_ON(q->top == q->bot);
77
        BUG_ON(q->top->prev != NULL);
78
        BUG_ON(q->bot->next != NULL);
79
80
        BUG_ON(q->top->next == q->bot);
81
        BUG_ON(q->bot->prev == q->top);
82
83
        Packet *p, *pp;
84
        for (p = q->top, pp = p->prev; p != NULL; pp = p, p = p->next) {
85
            SCLogDebug("p %p, pp %p, p->next %p, p->prev %p", p, pp, p->next, p->prev);
86
            BUG_ON(pp != p->prev);
87
        }
88
89
    }
90
}
91
92
#define BUGGER_ON(cond) { \
93
    if ((cond)) { \
94
        PacketQueueValidateDebug(q); \
95
    } \
96
}
97
98
void PacketQueueValidate(PacketQueue *q)
99
{
100
    if (q->len == 0) {
101
        BUGGER_ON(q->top != NULL);
102
        BUGGER_ON(q->bot != NULL);
103
    } else if(q->len == 1) {
104
        BUGGER_ON(q->top != q->bot);
105
        BUGGER_ON(q->top->next != NULL);
106
        BUGGER_ON(q->bot->next != NULL);
107
        BUGGER_ON(q->top->prev != NULL);
108
        BUGGER_ON(q->bot->prev != NULL);
109
    } else if (q->len == 2) {
110
        BUGGER_ON(q->top == NULL);
111
        BUGGER_ON(q->bot == NULL);
112
113
        BUGGER_ON(q->top == q->bot);
114
115
        BUGGER_ON(q->top->prev != NULL);
116
        BUGGER_ON(q->top->next != q->bot);
117
118
        BUGGER_ON(q->bot->prev != q->top);
119
        BUGGER_ON(q->bot->next != NULL);
120
    } else {
121
        BUGGER_ON(q->top == NULL);
122
        BUGGER_ON(q->bot == NULL);
123
124
        BUGGER_ON(q->top == q->bot);
125
        BUGGER_ON(q->top->prev != NULL);
126
        BUGGER_ON(q->bot->next != NULL);
127
128
        BUGGER_ON(q->top->next == q->bot);
129
        BUGGER_ON(q->bot->prev == q->top);
130
131
        Packet *p, *pp;
132
        for (p = q->top, pp = p->prev; p != NULL; pp = p, p = p->next) {
133
            BUGGER_ON(pp != p->prev);
134
        }
135
136
    }
137
}
138
#endif /* DEBUG */
139
140
static inline void PacketEnqueueDo(PacketQueue *q, Packet *p)
141
139k
{
142
    //PacketQueueValidateDebug(q);
143
144
139k
    if (p == NULL)
145
0
        return;
146
147
    /* more packets in queue */
148
139k
    if (q->top != NULL) {
149
42.9k
        p->prev = NULL;
150
42.9k
        p->next = q->top;
151
42.9k
        q->top->prev = p;
152
42.9k
        q->top = p;
153
    /* only packet */
154
96.6k
    } else {
155
96.6k
        p->prev = NULL;
156
96.6k
        p->next = NULL;
157
96.6k
        q->top = p;
158
96.6k
        q->bot = p;
159
96.6k
    }
160
139k
    q->len++;
161
#ifdef DBG_PERF
162
    if (q->len > q->dbg_maxlen)
163
        q->dbg_maxlen = q->len;
164
#endif /* DBG_PERF */
165
    //PacketQueueValidateDebug(q);
166
139k
}
167
168
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
169
139k
{
170
139k
    DEBUG_VALIDATE_BUG_ON(p->pkt_src == 0);
171
139k
    PacketQueue *q = (PacketQueue *)qnl;
172
139k
    PacketEnqueueDo(q, p);
173
139k
}
174
175
void PacketEnqueue (PacketQueue *q, Packet *p)
176
0
{
177
0
    PacketEnqueueDo(q, p);
178
0
}
179
180
static inline Packet *PacketDequeueDo (PacketQueue *q)
181
49.8M
{
182
    //PacketQueueValidateDebug(q);
183
    /* if the queue is empty there are no packets left. */
184
49.8M
    if (q->len == 0) {
185
49.6M
        return NULL;
186
49.6M
    }
187
139k
    q->len--;
188
189
    /* pull the bottom packet from the queue */
190
139k
    Packet *p = q->bot;
191
192
    /* more packets in queue */
193
139k
    if (q->bot->prev != NULL) {
194
42.9k
        q->bot = q->bot->prev;
195
42.9k
        q->bot->next = NULL;
196
        /* just the one we remove, so now empty */
197
96.6k
    } else {
198
96.6k
        q->top = NULL;
199
96.6k
        q->bot = NULL;
200
96.6k
    }
201
202
    //PacketQueueValidateDebug(q);
203
139k
    p->next = NULL;
204
139k
    p->prev = NULL;
205
139k
    return p;
206
49.8M
}
207
208
Packet *PacketDequeueNoLock (PacketQueueNoLock *qnl)
209
49.8M
{
210
49.8M
    PacketQueue *q = (PacketQueue *)qnl;
211
49.8M
    Packet *p = PacketDequeueDo(q);
212
49.8M
    DEBUG_VALIDATE_BUG_ON(p != NULL && p->pkt_src == 0);
213
49.8M
    return p;
214
49.8M
}
215
216
Packet *PacketDequeue (PacketQueue *q)
217
0
{
218
0
    return PacketDequeueDo(q);
219
0
}
220
221
PacketQueue *PacketQueueAlloc(void)
222
0
{
223
0
    PacketQueue *pq = SCCalloc(1, sizeof(*pq));
224
0
    if (pq == NULL)
225
0
        return NULL;
226
0
    SCMutexInit(&pq->mutex_q, NULL);
227
0
    SCCondInit(&pq->cond_q, NULL);
228
0
    return pq;
229
0
}
230
231
void PacketQueueFree(PacketQueue *pq)
232
0
{
233
0
    SCCondDestroy(&pq->cond_q);
234
0
    SCMutexDestroy(&pq->mutex_q);
235
0
    SCFree(pq);
236
0
}