suricata
flow-bypass.c
Go to the documentation of this file.
1/* Copyright (C) 2016-2018 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 Eric Leblond <eleblond@stamus-networks.com>
22 */
23
24#include "suricata-common.h"
25#include "tm-threads.h"
26#include "flow.h"
27#include "flow-bypass.h"
28#include "flow-private.h"
29#include "util-ebpf.h"
30#include "runmodes.h"
31
32#ifdef CAPTURE_OFFLOAD_MANAGER
33
34#define FLOW_BYPASS_DELAY 10
35
36#ifndef TIMEVAL_TO_TIMESPEC
37#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
38 (ts)->tv_sec = (tv)->tv_sec; \
39 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
40}
41#endif
42
43typedef struct BypassedFlowManagerThreadData_ {
44 uint16_t flow_bypassed_cnt_clo;
45 uint16_t flow_bypassed_pkts;
46 uint16_t flow_bypassed_bytes;
47} BypassedFlowManagerThreadData;
48
49#define BYPASSFUNCMAX 4
50
51typedef struct BypassedCheckFuncItem_ {
53 BypassedCheckFuncInit FuncInit;
54 void *data;
55} BypassedCheckFuncItem;
56
57int g_bypassed_func_max_index = 0;
58BypassedCheckFuncItem bypassedfunclist[BYPASSFUNCMAX];
59
60typedef struct BypassedUpdateFuncItem_ {
62 void *data;
63} BypassedUpdateFuncItem;
64
65int g_bypassed_update_max_index = 0;
66BypassedUpdateFuncItem updatefunclist[BYPASSFUNCMAX];
67
68static TmEcode BypassedFlowManager(ThreadVars *th_v, void *thread_data)
69{
70 int tcount = 0;
71 int i;
72 BypassedFlowManagerThreadData *ftd = thread_data;
73 struct timespec curtime = {0, 0};
74
75 struct timeval tv;
76 gettimeofday(&tv, NULL);
77 TIMEVAL_TO_TIMESPEC(&tv, &curtime);
78
79 for (i = 0; i < g_bypassed_func_max_index; i++) {
80 if (bypassedfunclist[i].FuncInit) {
81 bypassedfunclist[i].FuncInit(th_v, &curtime, bypassedfunclist[i].data);
82 }
83 }
84
85 /* check if we have a periodic check function */
86 bool found = false;
87 for (i = 0; i < g_bypassed_func_max_index; i++) {
88 if (bypassedfunclist[i].FuncInit) {
89 found = true;
90 break;
91 }
92 }
93 if (!found)
94 return TM_ECODE_OK;
95
97 bool run = TmThreadsWaitForUnpause(th_v);
98
99 while (run) {
100 SCLogDebug("Dumping the table");
101 gettimeofday(&tv, NULL);
102 TIMEVAL_TO_TIMESPEC(&tv, &curtime);
103
104 for (i = 0; i < g_bypassed_func_max_index; i++) {
105 struct flows_stats bypassstats = { 0, 0, 0};
106 if (bypassedfunclist[i].Func == NULL)
107 continue;
108 tcount = bypassedfunclist[i].Func(th_v, &bypassstats, &curtime, bypassedfunclist[i].data);
109 if (tcount) {
110 StatsAddUI64(th_v, ftd->flow_bypassed_cnt_clo, (uint64_t)bypassstats.count);
111 }
112 StatsAddUI64(th_v, ftd->flow_bypassed_pkts, (uint64_t)bypassstats.packets);
113 StatsAddUI64(th_v, ftd->flow_bypassed_bytes, (uint64_t)bypassstats.bytes);
114 }
115
116 if (TmThreadsCheckFlag(th_v, THV_KILL)) {
117 StatsSyncCounters(th_v);
118 return TM_ECODE_OK;
119 }
120 for (i = 0; i < FLOW_BYPASS_DELAY * 100; i++) {
121 if (TmThreadsCheckFlag(th_v, THV_KILL)) {
122 StatsSyncCounters(th_v);
123 return TM_ECODE_OK;
124 }
126 SleepMsec(10);
127 }
128 }
129 return TM_ECODE_OK;
130}
131
132static TmEcode BypassedFlowManagerThreadInit(ThreadVars *t, const void *initdata, void **data)
133{
134 BypassedFlowManagerThreadData *ftd = SCCalloc(1, sizeof(BypassedFlowManagerThreadData));
135 if (ftd == NULL)
136 return TM_ECODE_FAILED;
137
138 *data = ftd;
139
140 ftd->flow_bypassed_cnt_clo = StatsRegisterCounter("flow_bypassed.closed", t);
141 ftd->flow_bypassed_pkts = StatsRegisterCounter("flow_bypassed.pkts", t);
142 ftd->flow_bypassed_bytes = StatsRegisterCounter("flow_bypassed.bytes", t);
143
144 return TM_ECODE_OK;
145}
146
147static TmEcode BypassedFlowManagerThreadDeinit(ThreadVars *t, void *data)
148{
149 if (data)
150 SCFree(data);
151 return TM_ECODE_OK;
152}
153
155 BypassedCheckFuncInit CheckFuncInit,
156 void *data)
157{
158 if (g_bypassed_func_max_index < BYPASSFUNCMAX) {
159 bypassedfunclist[g_bypassed_func_max_index].Func = CheckFunc;
160 bypassedfunclist[g_bypassed_func_max_index].FuncInit = CheckFuncInit;
161 bypassedfunclist[g_bypassed_func_max_index].data = data;
162 g_bypassed_func_max_index++;
163 } else {
164 return -1;
165 }
166 return 0;
167}
168
170 void *data)
171{
172 if (!UpdateFunc) {
173 return -1;
174 }
175 if (g_bypassed_update_max_index < BYPASSFUNCMAX) {
176 updatefunclist[g_bypassed_update_max_index].Func = UpdateFunc;
177 updatefunclist[g_bypassed_update_max_index].data = data;
178 g_bypassed_update_max_index++;
179 } else {
180 return -1;
181 }
182 return 0;
183}
184#endif
185
186/** \brief spawn the flow bypass manager thread */
188{
189#ifdef CAPTURE_OFFLOAD_MANAGER
190
191 ThreadVars *tv_flowmgr = NULL;
193 "BypassedFlowManager", 0);
194 BUG_ON(tv_flowmgr == NULL);
195
196 if (tv_flowmgr == NULL) {
197 printf("ERROR: TmThreadsCreate failed\n");
198 exit(1);
199 }
200 if (TmThreadSpawn(tv_flowmgr) != TM_ECODE_OK) {
201 printf("ERROR: TmThreadSpawn failed\n");
202 exit(1);
203 }
204#endif
205}
206
208{
209#ifdef CAPTURE_OFFLOAD_MANAGER
210 for (int i = 0; i < g_bypassed_update_max_index; i++) {
211 if (updatefunclist[i].Func(f, p, updatefunclist[i].data)) {
212 return;
213 }
214 }
215#endif
216}
217
219{
220#ifdef CAPTURE_OFFLOAD_MANAGER
221 tmm_modules[TMM_BYPASSEDFLOWMANAGER].name = "BypassedFlowManager";
222 tmm_modules[TMM_BYPASSEDFLOWMANAGER].ThreadInit = BypassedFlowManagerThreadInit;
223 tmm_modules[TMM_BYPASSEDFLOWMANAGER].ThreadDeinit = BypassedFlowManagerThreadDeinit;
224 tmm_modules[TMM_BYPASSEDFLOWMANAGER].Management = BypassedFlowManager;
228#endif
229}
230
void StatsSyncCounters(ThreadVars *tv)
Definition counters.c:445
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition counters.c:952
void StatsSyncCountersIfSignalled(ThreadVars *tv)
Definition counters.c:450
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
Definition counters.c:146
void BypassedFlowManagerThreadSpawn(void)
spawn the flow bypass manager thread
void BypassedFlowUpdate(Flow *f, Packet *p)
void TmModuleBypassedFlowManagerRegister(void)
int(* BypassedCheckFuncInit)(ThreadVars *th_v, struct timespec *curtime, void *data)
Definition flow-bypass.h:38
int(* BypassedCheckFunc)(ThreadVars *th_v, struct flows_stats *bypassstats, struct timespec *curtime, void *data)
Definition flow-bypass.h:35
int BypassedFlowManagerRegisterUpdateFunc(BypassedUpdateFunc UpdateFunc, void *data)
int BypassedFlowManagerRegisterCheckFunc(BypassedCheckFunc CheckFunc, BypassedCheckFuncInit CheckFuncInit, void *data)
int(* BypassedUpdateFunc)(Flow *f, Packet *p, void *data)
Definition flow-bypass.h:40
ThreadVars * tv
const char * thread_name_flow_bypass
Definition runmodes.c:72
Flow data structure.
Definition flow.h:356
Per thread variable structure.
Definition threadvars.h:58
const char * name
Definition tm-modules.h:48
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition tm-modules.h:53
uint8_t cap_flags
Definition tm-modules.h:77
uint8_t flags
Definition tm-modules.h:80
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition tm-modules.h:51
TmEcode(* Management)(ThreadVars *, void *)
Definition tm-modules.h:69
uint64_t bytes
Definition flow-bypass.h:32
uint64_t count
Definition flow-bypass.h:30
uint64_t packets
Definition flow-bypass.h:31
#define BUG_ON(x)
#define THV_KILL
Definition threadvars.h:40
#define THV_RUNNING
Definition threadvars.h:55
TmModule tmm_modules[TMM_SIZE]
Definition tm-modules.c:29
#define TM_FLAG_MANAGEMENT_TM
Definition tm-modules.h:36
@ TMM_BYPASSEDFLOWMANAGER
@ TM_ECODE_FAILED
@ TM_ECODE_OK
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition tm-threads.c:93
ThreadVars * TmThreadCreateMgmtThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
const char * name
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition tm-threads.c:363
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition tm-threads.c:101
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
#define SleepMsec(msec)
Definition tm-threads.h:45
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53