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 
43 typedef 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 
51 typedef struct BypassedCheckFuncItem_ {
52  BypassedCheckFunc Func;
53  BypassedCheckFuncInit FuncInit;
54  void *data;
55 } BypassedCheckFuncItem;
56 
57 int g_bypassed_func_max_index = 0;
58 BypassedCheckFuncItem bypassedfunclist[BYPASSFUNCMAX];
59 
60 typedef struct BypassedUpdateFuncItem_ {
61  BypassedUpdateFunc Func;
62  void *data;
63 } BypassedUpdateFuncItem;
64 
65 int g_bypassed_update_max_index = 0;
66 BypassedUpdateFuncItem updatefunclist[BYPASSFUNCMAX];
67 
68 static 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 
98  while (1) {
99  if (TmThreadsCheckFlag(th_v, THV_PAUSE)) {
103  }
104  SCLogDebug("Dumping the table");
105  gettimeofday(&tv, NULL);
106  TIMEVAL_TO_TIMESPEC(&tv, &curtime);
107 
108  for (i = 0; i < g_bypassed_func_max_index; i++) {
109  struct flows_stats bypassstats = { 0, 0, 0};
110  if (bypassedfunclist[i].Func == NULL)
111  continue;
112  tcount = bypassedfunclist[i].Func(th_v, &bypassstats, &curtime, bypassedfunclist[i].data);
113  if (tcount) {
114  StatsAddUI64(th_v, ftd->flow_bypassed_cnt_clo, (uint64_t)bypassstats.count);
115  }
116  StatsAddUI64(th_v, ftd->flow_bypassed_pkts, (uint64_t)bypassstats.packets);
117  StatsAddUI64(th_v, ftd->flow_bypassed_bytes, (uint64_t)bypassstats.bytes);
118  }
119 
120  if (TmThreadsCheckFlag(th_v, THV_KILL)) {
121  StatsSyncCounters(th_v);
122  return TM_ECODE_OK;
123  }
124  for (i = 0; i < FLOW_BYPASS_DELAY * 100; i++) {
125  if (TmThreadsCheckFlag(th_v, THV_KILL)) {
126  StatsSyncCounters(th_v);
127  return TM_ECODE_OK;
128  }
130  usleep(10000);
131  }
132  }
133  return TM_ECODE_OK;
134 }
135 
136 static TmEcode BypassedFlowManagerThreadInit(ThreadVars *t, const void *initdata, void **data)
137 {
138  BypassedFlowManagerThreadData *ftd = SCCalloc(1, sizeof(BypassedFlowManagerThreadData));
139  if (ftd == NULL)
140  return TM_ECODE_FAILED;
141 
142  *data = ftd;
143 
144  ftd->flow_bypassed_cnt_clo = StatsRegisterCounter("flow_bypassed.closed", t);
145  ftd->flow_bypassed_pkts = StatsRegisterCounter("flow_bypassed.pkts", t);
146  ftd->flow_bypassed_bytes = StatsRegisterCounter("flow_bypassed.bytes", t);
147 
148  return TM_ECODE_OK;
149 }
150 
151 static TmEcode BypassedFlowManagerThreadDeinit(ThreadVars *t, void *data)
152 {
153  if (data)
154  SCFree(data);
155  return TM_ECODE_OK;
156 }
157 
159  BypassedCheckFuncInit CheckFuncInit,
160  void *data)
161 {
162  if (g_bypassed_func_max_index < BYPASSFUNCMAX) {
163  bypassedfunclist[g_bypassed_func_max_index].Func = CheckFunc;
164  bypassedfunclist[g_bypassed_func_max_index].FuncInit = CheckFuncInit;
165  bypassedfunclist[g_bypassed_func_max_index].data = data;
166  g_bypassed_func_max_index++;
167  } else {
168  return -1;
169  }
170  return 0;
171 }
172 
174  void *data)
175 {
176  if (!UpdateFunc) {
177  return -1;
178  }
179  if (g_bypassed_update_max_index < BYPASSFUNCMAX) {
180  updatefunclist[g_bypassed_update_max_index].Func = UpdateFunc;
181  updatefunclist[g_bypassed_update_max_index].data = data;
182  g_bypassed_update_max_index++;
183  } else {
184  return -1;
185  }
186  return 0;
187 }
188 #endif
189 
190 /** \brief spawn the flow bypass manager thread */
192 {
193 #ifdef CAPTURE_OFFLOAD_MANAGER
194 
195  ThreadVars *tv_flowmgr = NULL;
197  "BypassedFlowManager", 0);
198  BUG_ON(tv_flowmgr == NULL);
199 
200  if (tv_flowmgr == NULL) {
201  printf("ERROR: TmThreadsCreate failed\n");
202  exit(1);
203  }
204  if (TmThreadSpawn(tv_flowmgr) != TM_ECODE_OK) {
205  printf("ERROR: TmThreadSpawn failed\n");
206  exit(1);
207  }
208 #endif
209 }
210 
212 {
213 #ifdef CAPTURE_OFFLOAD_MANAGER
214  for (int i = 0; i < g_bypassed_update_max_index; i++) {
215  if (updatefunclist[i].Func(f, p, updatefunclist[i].data)) {
216  return;
217  }
218  }
219 #endif
220 }
221 
223 {
224 #ifdef CAPTURE_OFFLOAD_MANAGER
225  tmm_modules[TMM_BYPASSEDFLOWMANAGER].name = "BypassedFlowManager";
226  tmm_modules[TMM_BYPASSEDFLOWMANAGER].ThreadInit = BypassedFlowManagerThreadInit;
227  tmm_modules[TMM_BYPASSEDFLOWMANAGER].ThreadDeinit = BypassedFlowManagerThreadDeinit;
228  tmm_modules[TMM_BYPASSEDFLOWMANAGER].Management = BypassedFlowManager;
231  SCLogDebug("%s registered", tmm_modules[TMM_BYPASSEDFLOWMANAGER].name);
232 #endif
233 }
234 
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:74
tm-threads.h
flow-bypass.h
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1660
TmThreadCreateMgmtThreadByName
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:1093
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:99
BypassedFlowManagerThreadSpawn
void BypassedFlowManagerThreadSpawn(void)
spawn the flow bypass manager thread
Definition: flow-bypass.c:191
flows_stats::count
uint64_t count
Definition: flow-bypass.h:30
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:351
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
BypassedFlowUpdate
void BypassedFlowUpdate(Flow *f, Packet *p)
Definition: flow-bypass.c:211
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
THV_PAUSE
#define THV_PAUSE
Definition: threadvars.h:37
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:50
TmModuleBypassedFlowManagerRegister
void TmModuleBypassedFlowManagerRegister(void)
Definition: flow-bypass.c:222
TmThreadsUnsetFlag
void TmThreadsUnsetFlag(ThreadVars *tv, uint32_t flag)
Unset a thread flag.
Definition: tm-threads.c:107
TMM_BYPASSEDFLOWMANAGER
@ TMM_BYPASSEDFLOWMANAGER
Definition: tm-threads-common.h:74
thread_name_flow_bypass
const char * thread_name_flow_bypass
Definition: runmodes.c:85
util-ebpf.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
BypassedCheckFunc
int(* BypassedCheckFunc)(ThreadVars *th_v, struct flows_stats *bypassstats, struct timespec *curtime, void *data)
Definition: flow-bypass.h:35
TmThreadTestThreadUnPaused
void TmThreadTestThreadUnPaused(ThreadVars *tv)
Tests if the thread represented in the arg has been unpaused or not.
Definition: tm-threads.c:1762
TmModule_::Management
TmEcode(* Management)(ThreadVars *, void *)
Definition: tm-modules.h:66
THV_KILL
#define THV_KILL
Definition: threadvars.h:39
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
Packet_
Definition: decode.h:437
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:33
TmEcode
TmEcode
Definition: tm-threads-common.h:83
TmModule_::name
const char * name
Definition: tm-modules.h:45
runmodes.h
THV_PAUSED
#define THV_PAUSED
Definition: threadvars.h:38
flows_stats::bytes
uint64_t bytes
Definition: flow-bypass.h:32
suricata-common.h
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:48
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
StatsSyncCounters
void StatsSyncCounters(ThreadVars *tv)
Definition: counters.c:456
BypassedCheckFuncInit
int(* BypassedCheckFuncInit)(ThreadVars *th_v, struct timespec *curtime, void *data)
Definition: flow-bypass.h:38
BypassedFlowManagerRegisterUpdateFunc
int BypassedFlowManagerRegisterUpdateFunc(BypassedUpdateFunc UpdateFunc, void *data)
StatsAddUI64
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
SCFree
#define SCFree(p)
Definition: util-mem.h:61
StatsSyncCountersIfSignalled
void StatsSyncCountersIfSignalled(ThreadVars *tv)
Definition: counters.c:461
flow.h
BypassedUpdateFunc
int(* BypassedUpdateFunc)(Flow *f, Packet *p, void *data)
Definition: flow-bypass.h:40
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:91
BypassedFlowManagerRegisterCheckFunc
int BypassedFlowManagerRegisterCheckFunc(BypassedCheckFunc CheckFunc, BypassedCheckFuncInit CheckFuncInit, void *data)
StatsRegisterCounter
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
Definition: counters.c:971
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
flows_stats::packets
uint64_t packets
Definition: flow-bypass.h:31
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:77
TM_FLAG_MANAGEMENT_TM
#define TM_FLAG_MANAGEMENT_TM
Definition: tm-modules.h:37
flows_stats
Definition: flow-bypass.h:29