Coverage Report

Created: 2026-02-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/runmode-pcap-file.c
Line
Count
Source
1
/* Copyright (C) 2007-2010 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
#include "suricata-common.h"
19
#include "tm-threads.h"
20
#include "conf.h"
21
#include "runmodes.h"
22
#include "runmode-pcap-file.h"
23
#include "output.h"
24
25
#include "detect-engine.h"
26
#include "source-pcap-file.h"
27
28
#include "util-debug.h"
29
#include "util-time.h"
30
#include "util-cpu.h"
31
#include "util-affinity.h"
32
33
#include "util-runmodes.h"
34
35
const char *RunModeFilePcapGetDefaultMode(void)
36
38
{
37
38
    return "autofp";
38
38
}
39
40
void RunModeFilePcapRegister(void)
41
37
{
42
37
    RunModeRegisterNewRunMode(RUNMODE_PCAP_FILE, "single", "Single threaded pcap file mode",
43
37
            RunModeFilePcapSingle, NULL);
44
37
    RunModeRegisterNewRunMode(RUNMODE_PCAP_FILE, "autofp",
45
37
            "Multi-threaded pcap file mode. Packets from each flow are assigned to a consistent "
46
37
            "detection thread",
47
37
            RunModeFilePcapAutoFp, NULL);
48
49
37
    return;
50
37
}
51
52
/**
53
 * \brief Single thread version of the Pcap file processing.
54
 */
55
int RunModeFilePcapSingle(void)
56
0
{
57
0
    const char *file = NULL;
58
0
    char tname[TM_THREAD_NAME_MAX];
59
60
0
    if (ConfGet("pcap-file.file", &file) == 0) {
61
0
        FatalError("Failed retrieving pcap-file from Conf");
62
0
    }
63
64
0
    TimeModeSetOffline();
65
66
0
    PcapFileGlobalInit();
67
68
0
    snprintf(tname, sizeof(tname), "%s#01", thread_name_single);
69
70
    /* create the threads */
71
0
    ThreadVars *tv = TmThreadCreatePacketHandler(tname,
72
0
                                                 "packetpool", "packetpool",
73
0
                                                 "packetpool", "packetpool",
74
0
                                                 "pktacqloop");
75
0
    if (tv == NULL) {
76
0
        FatalError("threading setup failed");
77
0
    }
78
79
0
    TmModule *tm_module = TmModuleGetByName("ReceivePcapFile");
80
0
    if (tm_module == NULL) {
81
0
        FatalError("TmModuleGetByName failed for ReceivePcap");
82
0
    }
83
0
    TmSlotSetFuncAppend(tv, tm_module, file);
84
85
0
    tm_module = TmModuleGetByName("DecodePcapFile");
86
0
    if (tm_module == NULL) {
87
0
        FatalError("TmModuleGetByName DecodePcap failed");
88
0
    }
89
0
    TmSlotSetFuncAppend(tv, tm_module, NULL);
90
91
0
    tm_module = TmModuleGetByName("FlowWorker");
92
0
    if (tm_module == NULL) {
93
0
        FatalError("TmModuleGetByName for FlowWorker failed");
94
0
    }
95
0
    TmSlotSetFuncAppend(tv, tm_module, NULL);
96
97
0
    TmThreadSetCPU(tv, WORKER_CPU_SET);
98
99
0
    if (TmThreadSpawn(tv) != TM_ECODE_OK) {
100
0
        FatalError("TmThreadSpawn failed");
101
0
    }
102
0
    return 0;
103
0
}
104
105
/**
106
 * \brief RunModeFilePcapAutoFp set up the following thread packet handlers:
107
 *        - Receive thread (from pcap file)
108
 *        - Decode thread
109
 *        - Stream thread
110
 *        - Detect: If we have only 1 cpu, it will setup one Detect thread
111
 *                  If we have more than one, it will setup num_cpus - 1
112
 *                  starting from the second cpu available.
113
 *        - Outputs thread
114
 *        By default the threads will use the first cpu available
115
 *        except the Detection threads if we have more than one cpu.
116
 *
117
 * \retval 0 If all goes well. (If any problem is detected the engine will
118
 *           exit()).
119
 */
120
int RunModeFilePcapAutoFp(void)
121
0
{
122
0
    SCEnter();
123
0
    char tname[TM_THREAD_NAME_MAX];
124
0
    char qname[TM_QUEUE_NAME_MAX];
125
0
    uint16_t cpu = 0;
126
0
    char *queues = NULL;
127
0
    uint16_t thread;
128
129
0
    const char *file = NULL;
130
0
    if (ConfGet("pcap-file.file", &file) == 0) {
131
0
        FatalError("Failed retrieving pcap-file from Conf");
132
0
    }
133
0
    SCLogDebug("file %s", file);
134
135
0
    TimeModeSetOffline();
136
137
0
    PcapFileGlobalInit();
138
139
    /* Available cpus */
140
0
    uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
141
142
    /* start with cpu 1 so that if we're creating an odd number of detect
143
     * threads we're not creating the most on CPU0. */
144
0
    if (ncpus > 0)
145
0
        cpu = 1;
146
147
    /* always create at least one thread */
148
0
    int thread_max = TmThreadGetNbThreads(WORKER_CPU_SET);
149
0
    if (thread_max == 0)
150
0
        thread_max = ncpus * threading_detect_ratio;
151
0
    if (thread_max < 1)
152
0
        thread_max = 1;
153
0
    if (thread_max > 1024)
154
0
        thread_max = 1024;
155
156
0
    queues = RunmodeAutoFpCreatePickupQueuesString(thread_max);
157
0
    if (queues == NULL) {
158
0
        FatalError("RunmodeAutoFpCreatePickupQueuesString failed");
159
0
    }
160
161
0
    snprintf(tname, sizeof(tname), "%s#01", thread_name_autofp);
162
163
    /* create the threads */
164
0
    ThreadVars *tv_receivepcap =
165
0
        TmThreadCreatePacketHandler(tname,
166
0
                                    "packetpool", "packetpool",
167
0
                                    queues, "flow",
168
0
                                    "pktacqloop");
169
0
    SCFree(queues);
170
171
0
    if (tv_receivepcap == NULL) {
172
0
        FatalError("threading setup failed");
173
0
    }
174
0
    TmModule *tm_module = TmModuleGetByName("ReceivePcapFile");
175
0
    if (tm_module == NULL) {
176
0
        FatalError("TmModuleGetByName failed for ReceivePcap");
177
0
    }
178
0
    TmSlotSetFuncAppend(tv_receivepcap, tm_module, file);
179
180
0
    tm_module = TmModuleGetByName("DecodePcapFile");
181
0
    if (tm_module == NULL) {
182
0
        FatalError("TmModuleGetByName DecodePcap failed");
183
0
    }
184
0
    TmSlotSetFuncAppend(tv_receivepcap, tm_module, NULL);
185
186
0
    TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);
187
188
0
    if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
189
0
        FatalError("TmThreadSpawn failed");
190
0
    }
191
192
0
    for (thread = 0; thread < (uint16_t)thread_max; thread++) {
193
0
        snprintf(tname, sizeof(tname), "%s#%02d", thread_name_workers, thread + 1);
194
0
        snprintf(qname, sizeof(qname), "pickup%d", thread + 1);
195
196
0
        SCLogDebug("tname %s, qname %s", tname, qname);
197
0
        SCLogDebug("Assigning %s affinity to cpu %u", tname, cpu);
198
199
0
        ThreadVars *tv_detect_ncpu =
200
0
            TmThreadCreatePacketHandler(tname,
201
0
                                        qname, "flow",
202
0
                                        "packetpool", "packetpool",
203
0
                                        "varslot");
204
0
        if (tv_detect_ncpu == NULL) {
205
0
            FatalError("TmThreadsCreate failed");
206
0
        }
207
208
0
        tm_module = TmModuleGetByName("FlowWorker");
209
0
        if (tm_module == NULL) {
210
0
            FatalError("TmModuleGetByName for FlowWorker failed");
211
0
        }
212
0
        TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL);
213
214
0
        TmThreadSetGroupName(tv_detect_ncpu, "Detect");
215
216
0
        TmThreadSetCPU(tv_detect_ncpu, WORKER_CPU_SET);
217
218
0
        if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
219
0
            FatalError("TmThreadSpawn failed");
220
0
        }
221
222
0
        if ((cpu + 1) == ncpus)
223
0
            cpu = 0;
224
0
        else
225
0
            cpu++;
226
0
    }
227
228
0
    return 0;
229
0
}