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