38 #ifdef NAPATECH_ENABLE_BYPASS
44 typedef struct FlowStatsCounters_
46 uint16_t active_bypass_flows;
47 uint16_t total_bypass_flows;
51 static int bypass_supported;
52 int NapatechIsBypassSupported(
void)
54 return bypass_supported;
62 int NapatechGetNumAdapters(
void)
67 static int num_adapters = -1;
69 if (num_adapters == -1) {
70 if ((status = NT_InfoOpen(&hInfo,
"InfoStream")) != NT_SUCCESS) {
75 hInfoSys.cmd = NT_INFO_CMD_READ_SYSTEM;
76 if ((status = NT_InfoRead(hInfo, &hInfoSys)) != NT_SUCCESS) {
81 num_adapters = hInfoSys.u.system.data.numAdapters;
97 int NapatechVerifyBypassSupport(
void)
101 int num_adapters = NapatechGetNumAdapters();
102 SCLogInfo(
"Found %d Napatech adapters.", num_adapters);
103 NtFlowStream_t hFlowStream;
110 for (adapter = 0; adapter < num_adapters; ++adapter) {
114 NT_FlowOpenAttrInit(&attr);
115 NT_FlowOpenAttrSetAdapterNo(&attr, adapter);
117 snprintf(flow_name,
sizeof(flow_name),
"Flow stream %d", adapter );
118 SCLogInfo(
"Opening flow programming stream: %s\n", flow_name);
119 if ((status = NT_FlowOpen_Attr(&hFlowStream, flow_name, &attr)) != NT_SUCCESS) {
120 SCLogWarning(
"Napatech bypass functionality not supported by the FPGA version on "
121 "adapter %d - disabling support.",
123 bypass_supported = 0;
126 NT_FlowClose(hFlowStream);
129 bypass_supported = 1;
130 return bypass_supported;
144 static void UpdateFlowStats(
146 NtInfoStream_t hInfo,
147 NtStatStream_t hstat_stream,
148 FlowStatsCounters flow_counters,
152 NtStatistics_t hStat;
155 uint64_t programed = 0;
156 uint64_t removed = 0;
159 for (adapter = 0; adapter < NapatechGetNumAdapters(); ++adapter) {
160 hStat.cmd = NT_STATISTICS_READ_CMD_FLOW_V0;
161 hStat.u.flowData_v0.clear = clear_stats;
162 hStat.u.flowData_v0.adapterNo = adapter;
163 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
167 programed = hStat.u.flowData_v0.learnDone;
168 removed = hStat.u.flowData_v0.unlearnDone
169 + hStat.u.flowData_v0.automaticUnlearnDone
170 + hStat.u.flowData_v0.timeoutUnlearnDone;
173 StatsSetUI64(
tv, flow_counters.active_bypass_flows, programed - removed);
208 #define MAX_HOSTBUFFERS 8
219 static uint16_t TestStreamConfig(
220 NtInfoStream_t hInfo,
221 NtStatStream_t hstat_stream,
225 uint16_t num_active = 0;
227 for (uint16_t inst = 0; inst < num_inst; ++inst) {
232 memset(&stat, 0,
sizeof (NtStatistics_t));
235 stat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
236 stat.u.usageData_v0.streamid = (uint8_t)
stream_config[inst].stream_id;
238 if ((status = NT_StatRead(hstat_stream, &stat)) != NT_SUCCESS) {
243 if (stat.u.usageData_v0.data.numHostBufferUsed > 0) {
274 NtInfoStream_t hInfo,
275 NtStatStream_t hstat_stream,
276 uint16_t num_streams,
283 int enable_stream_stats,
292 NtInfo_t hStreamInfo;
293 NtStatistics_t hStat;
296 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
297 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
303 if ((num_active = TestStreamConfig(hInfo, hstat_stream,
stream_config, num_streams)) == 0) {
309 uint16_t inst_id = 0;
310 uint32_t stream_cnt = 0;
311 for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
312 while (inst_id < num_streams) {
319 if (inst_id == num_streams)
323 memset(&hStat, 0,
sizeof (NtStatistics_t));
324 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
325 hStat.u.usageData_v0.streamid = (uint8_t)
stream_config[inst_id].stream_id;
327 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
334 uint64_t rx_pkts_total = 0;
335 uint64_t rx_byte_total = 0;
336 uint64_t drop_pkts_total = 0;
337 uint64_t drop_byte_total = 0;
339 for (uint32_t hbCount = 0; hbCount < hStat.u.usageData_v0.data.numHostBufferUsed; hbCount++) {
341 rxPktsStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
342 rxByteStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
343 dropPktStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
344 dropByteStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.bytes;
347 rx_pkts_total += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
348 rx_byte_total += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
349 drop_pkts_total += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
350 drop_byte_total += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.bytes;
360 if (enable_stream_stats) {
371 for (stream_id = 0; stream_id < num_streams; ++stream_id) {
373 #ifndef NAPATECH_ENABLE_BYPASS
382 #ifndef NAPATECH_ENABLE_BYPASS
396 memset(&hStat, 0,
sizeof (NtStatistics_t));
398 #ifdef NAPATECH_ENABLE_BYPASS
399 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V3;
400 hStat.u.query_v3.clear = 0;
403 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V2;
404 hStat.u.query_v2.clear = 0;
407 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
408 if (status == NT_STATUS_TIMEOUT) {
409 SCLogInfo(
"Statistics timed out - will retry next time.");
417 #ifdef NAPATECH_ENABLE_BYPASS
420 uint64_t total_dispatch_host_pkts = 0;
421 uint64_t total_dispatch_host_byte = 0;
422 uint64_t total_dispatch_drop_pkts = 0;
423 uint64_t total_dispatch_drop_byte = 0;
424 uint64_t total_dispatch_fwd_pkts = 0;
425 uint64_t total_dispatch_fwd_byte = 0;
427 for (adapter = 0; adapter < NapatechGetNumAdapters(); ++adapter) {
428 total_dispatch_host_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[0].pkts;
429 total_dispatch_host_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[0].octets;
431 total_dispatch_drop_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].pkts
432 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].pkts;
433 total_dispatch_drop_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].octets
434 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].octets;
436 total_dispatch_fwd_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].pkts
437 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[4].pkts;
438 total_dispatch_fwd_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].octets
439 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[4].octets;
442 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].pkts
443 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].pkts
444 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].pkts;
447 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].octets
448 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].octets;
478 static void *NapatechStatsLoop(
void *arg)
483 NtInfoStream_t hInfo;
484 NtStatStream_t hstat_stream;
486 int enable_stream_stats = 0;
489 if (
ConfGetBool(
"napatech.inline", &is_inline) == 0) {
493 if (
ConfGetBool(
"napatech.enable-stream-stats", &enable_stream_stats) == 0) {
495 enable_stream_stats = 0;
502 if ((status = NT_InfoOpen(&hInfo,
"StatsLoopInfoStream")) != NT_SUCCESS) {
507 if ((status = NT_StatOpen(&hstat_stream,
"StatsLoopStatsStream")) != NT_SUCCESS) {
512 NtStatistics_t hStat;
513 memset(&hStat, 0,
sizeof (NtStatistics_t));
515 #ifdef NAPATECH_ENABLE_BYPASS
516 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V3;
517 hStat.u.query_v3.clear = 1;
519 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V2;
520 hStat.u.query_v2.clear = 1;
523 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
529 memset(&total_counters, 0,
sizeof(total_counters));
532 memset(&dispatch_host, 0,
sizeof(dispatch_host));
535 memset(&dispatch_drop, 0,
sizeof(dispatch_drop));
538 memset(&dispatch_fwd, 0,
sizeof(dispatch_fwd));
557 if (enable_stream_stats) {
558 for (
int i = 0; i < stream_cnt; ++i) {
561 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
564 snprintf(pkts_buf, 32,
"napa%d.pkts",
stream_config[i].stream_id);
569 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
571 snprintf(byte_buf, 32,
"napa%d.bytes",
stream_config[i].stream_id);
574 char *drop_pkts_buf =
SCCalloc(1, 32);
575 if (
unlikely(drop_pkts_buf == NULL)) {
576 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
578 snprintf(drop_pkts_buf, 32,
"napa%d.drop_pkts",
stream_config[i].stream_id);
581 char *drop_byte_buf =
SCCalloc(1, 32);
582 if (
unlikely(drop_byte_buf == NULL)) {
583 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
585 snprintf(drop_byte_buf, 32,
"napa%d.drop_byte",
stream_config[i].stream_id);
590 #ifdef NAPATECH_ENABLE_BYPASS
591 FlowStatsCounters flow_counters;
592 if (bypass_supported) {
605 #ifdef NAPATECH_ENABLE_BYPASS
606 if (bypass_supported) {
620 if (enable_stream_stats) {
621 for (
int i = 0; i < stream_cnt; ++i) {
631 UpdateFlowStats(
tv, hInfo, hstat_stream, flow_counters, 1);
635 uint32_t num_active = UpdateStreamStats(
tv, hInfo, hstat_stream,
637 dispatch_host, dispatch_drop, dispatch_fwd,
638 is_inline, enable_stream_stats, stream_counters);
641 SCLogInfo(
"num_active: %d, stream_cnt: %d", num_active, stream_cnt);
642 SCLogWarning(
"Some or all of the configured streams are not created. Proceeding with "
649 SCLogDebug(
"NapatechStatsLoop THV_KILL detected");
653 UpdateStreamStats(
tv, hInfo, hstat_stream,
655 dispatch_host, dispatch_drop, dispatch_fwd,
656 is_inline, enable_stream_stats,
659 #ifdef NAPATECH_ENABLE_BYPASS
660 if (bypass_supported) {
661 UpdateFlowStats(
tv, hInfo, hstat_stream, flow_counters, 0);
670 if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
676 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
689 #define MAX_HOSTBUFFER 4
690 #define MAX_STREAMS 256
691 #define HB_HIGHWATER 2048 //1982
703 static bool RegisteredStream(uint16_t stream_id, uint16_t num_registered,
706 for (uint16_t reg_id = 0; reg_id < num_registered; ++reg_id) {
707 if (stream_id == registered_streams[reg_id].stream_id) {
719 static uint32_t CountWorkerThreads(
void)
721 int worker_count = 0;
730 if (strcmp(affinity->
val,
"decode-cpu-set") == 0 ||
731 strcmp(affinity->
val,
"stream-cpu-set") == 0 ||
732 strcmp(affinity->
val,
"reject-cpu-set") == 0 ||
733 strcmp(affinity->
val,
"output-cpu-set") == 0) {
737 if (strcmp(affinity->
val,
"worker-cpu-set") == 0) {
747 if (strncmp(lnode->
val,
"all", 4) == 0) {
750 FatalError(
"Only one Napatech port specifier type allowed.");
754 }
else if ((end_str = strchr(lnode->
val,
'-'))) {
757 FatalError(
"Only one Napatech port specifier type allowed.");
764 " worker range start: '%s'",
769 " worker range end: '%s'",
770 (end_str != NULL) ? (
const char *)(end_str + 1) :
"Null");
774 " worker range start: '%d' is greater than end: '%d'",
777 worker_count = end - start + 1;
782 FatalError(
"Napatech port range specifiers cannot be combined with "
783 "individual stream specifiers.");
807 char error_buffer[80];
808 NtStatStream_t hstat_stream;
809 NtStatistics_t hStat;
810 NtInfoStream_t info_stream;
812 uint16_t instance_cnt = 0;
813 int use_all_streams = 0;
814 int set_cpu_affinity = 0;
816 uint16_t stream_id = 0;
826 if (
ConfGetBool(
"napatech.use-all-streams", &use_all_streams) == 0) {
831 if ((status = NT_InfoOpen(&info_stream,
"SuricataStreamInfo")) != NT_SUCCESS) {
836 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
841 if (use_all_streams) {
842 info.cmd = NT_INFO_CMD_READ_STREAM;
843 if ((status = NT_InfoRead(info_stream, &info)) != NT_SUCCESS) {
848 while (instance_cnt < info.u.stream.data.count) {
856 memset(&hStat, 0,
sizeof (NtStatistics_t));
859 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
860 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
862 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
864 NT_ExplainError(status, error_buffer,
sizeof (error_buffer));
865 SCLogError(
"NT_StatRead() failed: %s\n", error_buffer);
869 if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
881 (void)
ConfGetBool(
"threading.set-cpu-affinity", &set_cpu_affinity);
884 end = CountWorkerThreads() - 1;
888 if ((ntstreams =
ConfGetNode(
"napatech.streams")) == NULL) {
889 SCLogError(
"Failed retrieving napatech.streams from Config");
891 SCLogError(
"if set-cpu-affinity: no in conf then napatech.streams must be "
905 if (stream == NULL) {
906 SCLogError(
"Couldn't Parse Stream Configuration");
910 char *end_str = strchr(stream->
val,
'-');
913 SCLogError(
"Only one Napatech stream range specifier allowed.");
919 (
const char *)stream->
val) < 0) {
921 "stream id start: '%s'",
926 "stream id end: '%s'",
927 (end_str != NULL) ? (
const char *)(end_str + 1) :
"Null");
931 FatalError(
"Napatech range and individual specifiers cannot be combined.");
935 10, 0, (
const char *)stream->
val) < 0) {
946 for (stream_id = start; stream_id <= end; ++stream_id) {
951 memset(&hStat, 0,
sizeof (NtStatistics_t));
954 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
955 hStat.u.usageData_v0.streamid =
958 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
963 if (hStat.u.usageData_v0.data.numHostBufferUsed > 0) {
971 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
976 if ((status = NT_InfoClose(info_stream)) != NT_SUCCESS) {
984 static void *NapatechBufMonitorLoop(
void *arg)
988 NtInfo_t hStreamInfo;
989 NtStatistics_t hStat;
990 NtInfoStream_t hInfo;
991 NtStatStream_t hstat_stream;
994 const uint32_t alertInterval = 25;
996 #ifndef NAPATECH_ENABLE_BYPASS
1007 if ((status = NT_InfoOpen(&hInfo,
"InfoStream")) != NT_SUCCESS) {
1012 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
1018 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
1019 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
1026 if (num_registered == -1) {
1033 SCLogDebug(
"NapatechBufMonitorLoop THV_KILL detected");
1040 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
1041 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
1046 char pktCntStr[4096];
1047 memset(pktCntStr, 0,
sizeof (pktCntStr));
1049 uint32_t stream_id = 0;
1050 uint32_t stream_cnt = 0;
1051 uint32_t num_streams = hStreamInfo.u.stream.data.count;
1053 for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
1058 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
1059 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
1061 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
1066 if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
1070 }
while (hStat.u.usageData_v0.data.numHostBufferUsed == 0);
1072 if (RegisteredStream(stream_id, num_registered, registered_streams)) {
1074 #ifndef NAPATECH_ENABLE_BYPASS
1075 ave_OB_fill_level[stream_id] = 0;
1078 ave_HB_fill_level[stream_id] = 0;
1080 for (uint32_t hb_count = 0; hb_count < hStat.u.usageData_v0.data.numHostBufferUsed; hb_count++) {
1082 #ifndef NAPATECH_ENABLE_BYPASS
1083 OB_fill_level[hb_count] =
1084 ((100 * hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.used) /
1085 hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.size);
1087 if (OB_fill_level[hb_count] > 100) {
1088 OB_fill_level[hb_count] = 100;
1091 uint32_t bufSize = hStat.u.usageData_v0.data.hb[hb_count].enQueuedAdapter / 1024
1092 + hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024
1093 + hStat.u.usageData_v0.data.hb[hb_count].enQueued / 1024
1096 HB_fill_level[hb_count] = (uint32_t)
1097 ((100 * hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024) /
1100 #ifndef NAPATECH_ENABLE_BYPASS
1101 ave_OB_fill_level[stream_id] += OB_fill_level[hb_count];
1104 ave_HB_fill_level[stream_id] += HB_fill_level[hb_count];
1107 #ifndef NAPATECH_ENABLE_BYPASS
1108 ave_OB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
1111 ave_HB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
1114 if (ave_HB_fill_level[stream_id] >= (HB_alert_level[stream_id] + alertInterval)) {
1116 while (ave_HB_fill_level[stream_id] >= HB_alert_level[stream_id] + alertInterval) {
1117 HB_alert_level[stream_id] += alertInterval;
1119 SCLogPerf(
"nt%d - Increasing Host Buffer Fill Level : %4d%%",
1120 stream_id, ave_HB_fill_level[stream_id] - 1);
1123 if (HB_alert_level[stream_id] > 0) {
1124 if ((ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval))) {
1125 SCLogPerf(
"nt%d - Decreasing Host Buffer Fill Level: %4d%%",
1126 stream_id, ave_HB_fill_level[stream_id]);
1128 while (ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval)) {
1129 if ((HB_alert_level[stream_id]) > 0) {
1130 HB_alert_level[stream_id] -= alertInterval;
1136 #ifndef NAPATECH_ENABLE_BYPASS
1138 if (ave_OB_fill_level[stream_id] >= (OB_alert_level[stream_id] + alertInterval)) {
1139 while (ave_OB_fill_level[stream_id] >= OB_alert_level[stream_id] + alertInterval) {
1140 OB_alert_level[stream_id] += alertInterval;
1143 SCLogPerf(
"nt%d - Increasing Adapter SDRAM Fill Level: %4d%%",
1144 stream_id, ave_OB_fill_level[stream_id]);
1147 if (OB_alert_level[stream_id] > 0) {
1148 if ((ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval))) {
1149 SCLogPerf(
"nt%d - Decreasing Adapter SDRAM Fill Level : %4d%%",
1150 stream_id, ave_OB_fill_level[stream_id]);
1152 while (ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval)) {
1153 if ((OB_alert_level[stream_id]) > 0) {
1154 OB_alert_level[stream_id] -= alertInterval;
1165 if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
1171 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
1191 "custom", NapatechStatsLoop, 0);
1193 if (stats_tv == NULL) {
1194 FatalError(
"Error creating a thread for NapatechStats - Killing engine.");
1198 FatalError(
"Failed to spawn thread for NapatechStats - Killing engine.");
1201 #ifdef NAPATECH_ENABLE_BYPASS
1202 if (bypass_supported) {
1203 SCLogInfo(
"Napatech bypass functionality enabled.");
1210 "custom", NapatechBufMonitorLoop, 0);
1212 if (buf_monitor_tv == NULL) {
1213 FatalError(
"Error creating a thread for NapatechBufMonitor - Killing engine.");
1217 FatalError(
"Failed to spawn thread for NapatechBufMonitor - Killing engine.");
1223 uint32_t status = 0;
1224 static NtConfigStream_t hconfig;
1227 snprintf(ntpl_cmd, 64,
"setup[numanode=%d] = streamid == %d", numa, stream);
1229 NtNtplInfo_t ntpl_info;
1231 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1236 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info, NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1237 status = ntpl_info.ntplId;
1247 static uint32_t NapatechSetHashmode(
void)
1249 uint32_t status = 0;
1250 const char *hash_mode;
1251 static NtConfigStream_t hconfig;
1253 NtNtplInfo_t ntpl_info;
1255 uint32_t filter_id = 0;
1258 ConfGet(
"napatech.hashmode", &hash_mode);
1260 snprintf(ntpl_cmd, 64,
"hashmode = %s", hash_mode);
1263 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1268 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1269 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1270 filter_id = ntpl_info.ntplId;
1271 SCLogConfig(
"Napatech hashmode: %s ID: %d", hash_mode, status);
1280 static uint32_t GetStreamNUMAs(uint32_t stream_id,
int stream_numas[])
1282 NtStatistics_t hStat;
1283 NtStatStream_t hstat_stream;
1287 stream_numas[i] = -1;
1289 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
1294 char pktCntStr[4096];
1295 memset(pktCntStr, 0,
sizeof (pktCntStr));
1299 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
1300 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
1302 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
1307 for (uint32_t hb_id = 0; hb_id < hStat.u.usageData_v0.data.numHostBufferUsed; ++hb_id) {
1308 stream_numas[hb_id] = hStat.u.usageData_v0.data.hb[hb_id].numaNode;
1311 return hStat.u.usageData_v0.data.numHostBufferUsed;
1314 static int NapatechSetFilter(NtConfigStream_t hconfig,
char *ntpl_cmd)
1317 int local_filter_id = 0;
1319 NtNtplInfo_t ntpl_info;
1320 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1321 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1322 SCLogConfig(
"NTPL filter assignment \"%s\" returned filter id %4d",
1323 ntpl_cmd, local_filter_id);
1329 return local_filter_id;
1334 uint32_t status = 0;
1335 static NtConfigStream_t hconfig;
1337 NtNtplInfo_t ntpl_info;
1339 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1344 snprintf(ntpl_cmd, 64,
"delete = all");
1345 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1346 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1347 status = ntpl_info.ntplId;
1353 NT_ConfigClose(hconfig);
1361 #define PORTS_SPEC_SIZE 64
1363 struct ports_spec_s {
1370 ports_spec.all =
false;
1375 NtConfigStream_t hconfig;
1378 #ifdef NAPATECH_ENABLE_BYPASS
1382 char span_ports[128];
1383 memset(span_ports, 0,
sizeof(span_ports));
1385 if (
ConfGetBool(
"napatech.inline", &is_inline) == 0) {
1389 NapatechSetHashmode();
1391 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1396 if (first_stream == last_stream) {
1397 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1398 "Setup[state=inactive] = StreamId == %d",
1401 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1402 "Setup[state=inactive] = StreamId == (%d..%d)",
1403 first_stream, last_stream);
1405 NapatechSetFilter(hconfig, ntpl_cmd);
1407 #ifdef NAPATECH_ENABLE_BYPASS
1409 SCLogInfo(
"Napatech Hardware Bypass enabled.");
1413 SCLogInfo(
"Napatech Hardware Bypass requested in conf but is not available.");
1416 SCLogInfo(
"Napatech Hardware Bypass disabled.");
1421 SCLogInfo(
"Napatech configured for inline mode.");
1424 SCLogInfo(
"Napatech configured for passive (non-inline) mode.");
1430 if ((ntports =
ConfGetNode(
"napatech.ports")) == NULL) {
1431 FatalError(
"Failed retrieving napatech.ports from Conf");
1439 SCLogInfo(
"Listening on the following Napatech ports:");
1445 FatalError(
"Couldn't Parse Port Configuration");
1449 #ifdef NAPATECH_ENABLE_BYPASS
1450 if (strchr(port->
val,
'-')) {
1454 FatalError(
"Invalid value '%s' in napatech.ports specification in conf file.",
1459 strchr(port->
val,
'-') + 1) == -1) {
1460 FatalError(
"Invalid value '%s' in napatech.ports specification in conf file.",
1464 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1467 "Error with napatech.ports in conf file. When running in inline "
1468 "mode the two ports specifying a segment must be different.");
1471 is_span_port[ports_spec.first[iteration]] = 1;
1473 if (strlen(span_ports) == 0) {
1474 snprintf(span_ports,
sizeof (span_ports),
"%d", ports_spec.first[iteration]);
1477 snprintf(temp,
sizeof(temp),
",%d", ports_spec.first[iteration]);
1478 strlcat(span_ports, temp,
sizeof(span_ports));
1485 SCLogError(
"Invalid napatech.ports specification in conf file.");
1486 SCLogError(
"Two ports on a segment must reside on the same adapter. port %d "
1487 "is on adapter %d, port %d is on adapter %d.",
1488 ports_spec.first[iteration],
1490 ports_spec.second[iteration],
1496 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1497 SCLogInfo(
" span_port: %d", ports_spec.first[iteration]);
1499 SCLogInfo(
" %s: %d - %d", is_inline ?
"inline_ports" :
"tap_ports", ports_spec.first[iteration], ports_spec.second[iteration]);
1502 if (iteration == 0) {
1503 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1504 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%d", ports_spec.first[iteration]);
1506 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%d,%d", ports_spec.first[iteration], ports_spec.second[iteration]);
1510 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1511 snprintf(temp,
sizeof(temp),
",%d", ports_spec.first[iteration]);
1513 snprintf(temp,
sizeof(temp),
",%d,%d", ports_spec.first[iteration], ports_spec.second[iteration]);
1515 strlcat(ports_spec.str, temp,
sizeof(ports_spec.str));
1518 FatalError(
"When using hardware flow bypass ports must be specified as segments. "
1519 "E.g. ports: [0-1, 0-2]");
1523 if (strncmp(port->
val,
"all", 3) == 0) {
1526 FatalError(
"Only one Napatech port specifier type is allowed.");
1530 ports_spec.all =
true;
1531 snprintf(ports_spec.str, sizeof (ports_spec.str),
"all");
1532 }
else if (strchr(port->
val,
'-')) {
1535 FatalError(
"Only one Napatech port specifier is allowed when hardware bypass "
1536 "is disabled. (E.g. ports: [0-4], NOT ports: [0-1,2-3])");
1541 FatalError(
"Invalid value '%s' in napatech.ports specification in conf file.",
1546 strchr(port->
val,
'-') + 1) == -1) {
1547 FatalError(
"Invalid value '%s' in napatech.ports specification in conf file.",
1551 snprintf(ports_spec.str, sizeof (ports_spec.str),
"(%d..%d)", ports_spec.first[iteration], ports_spec.second[iteration]);
1555 FatalError(
"Napatech port range specifiers cannot be combined with individual "
1556 "stream specifiers.");
1561 FatalError(
"Invalid value '%s' in napatech.ports specification in conf file.",
1566 if (iteration == 0) {
1567 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%s", port->
val);
1569 strlcat(ports_spec.str,
",",
sizeof(ports_spec.str));
1570 strlcat(ports_spec.str, port->
val,
sizeof(ports_spec.str));
1577 #ifdef NAPATECH_ENABLE_BYPASS
1578 if (bypass_supported) {
1580 char inline_setup_cmd[512];
1581 if (first_stream == last_stream) {
1582 snprintf(inline_setup_cmd,
sizeof (ntpl_cmd),
1583 "Setup[TxDescriptor=Dyn;TxPorts=%s;RxCRC=False;TxPortPos=112;UseWL=True] = StreamId == %d",
1584 ports_spec.str, first_stream);
1586 snprintf(inline_setup_cmd,
sizeof (ntpl_cmd),
1587 "Setup[TxDescriptor=Dyn;TxPorts=%s;RxCRC=False;TxPortPos=112;UseWL=True] = StreamId == (%d..%d)",
1588 ports_spec.str, first_stream, last_stream);
1590 NapatechSetFilter(hconfig, inline_setup_cmd);
1593 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1594 "assign[priority=3;streamid=(%d..%d);colormask=0x10000000;"
1595 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s",
1596 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1597 NapatechSetFilter(hconfig, ntpl_cmd);
1600 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1601 "assign[priority=2;streamid=(%d..%d);colormask=0x11000000;"
1602 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1603 "]= %s%s and (Layer3Protocol==IPV4)",
1604 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1605 NapatechSetFilter(hconfig, ntpl_cmd);
1608 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1609 "assign[priority=2;streamid=(%d..%d);colormask=0x14000000;"
1610 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s and (Layer3Protocol==IPV6)",
1611 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1612 NapatechSetFilter(hconfig, ntpl_cmd);
1614 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1615 "assign[priority=2;streamid=(%d..%d);colormask=0x10100000;"
1616 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s and (Layer4Protocol==TCP)",
1617 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1618 NapatechSetFilter(hconfig, ntpl_cmd);
1620 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1621 "assign[priority=2;streamid=(%d..%d);colormask=0x10200000;"
1622 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1623 "]= %s%s and (Layer4Protocol==UDP)",
1624 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1625 NapatechSetFilter(hconfig, ntpl_cmd);
1627 if (strlen(span_ports) > 0) {
1628 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1629 "assign[priority=2;streamid=(%d..%d);colormask=0x00001000;"
1630 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1632 first_stream, last_stream, span_ports);
1633 NapatechSetFilter(hconfig, ntpl_cmd);
1636 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1637 "KeyType[name=KT%u]={sw_32_32,sw_16_16}",
1638 NAPATECH_KEYTYPE_IPV4);
1639 NapatechSetFilter(hconfig, ntpl_cmd);
1641 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1642 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER]=(Layer3Header[12]/32/32,Layer4Header[0]/16/16)",
1643 NAPATECH_KEYTYPE_IPV4, NAPATECH_KEYTYPE_IPV4);
1644 NapatechSetFilter(hconfig, ntpl_cmd);
1646 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1647 "KeyType[name=KT%u]={32,32,16,16}",
1648 NAPATECH_KEYTYPE_IPV4_SPAN);
1649 NapatechSetFilter(hconfig, ntpl_cmd);
1651 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1652 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER;keysort=sorted]=(Layer3Header[12]/32,Layer3Header[16]/32,Layer4Header[0]/16,Layer4Header[2]/16)",
1653 NAPATECH_KEYTYPE_IPV4_SPAN, NAPATECH_KEYTYPE_IPV4_SPAN);
1654 NapatechSetFilter(hconfig, ntpl_cmd);
1657 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1658 "KeyType[name=KT%u]={sw_128_128,sw_16_16}",
1659 NAPATECH_KEYTYPE_IPV6);
1660 NapatechSetFilter(hconfig, ntpl_cmd);
1662 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1663 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER]=(Layer3Header[8]/128/128,Layer4Header[0]/16/16)",
1664 NAPATECH_KEYTYPE_IPV6, NAPATECH_KEYTYPE_IPV6);
1665 NapatechSetFilter(hconfig, ntpl_cmd);
1668 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1669 "KeyType[name=KT%u]={128,128,16,16}",
1670 NAPATECH_KEYTYPE_IPV6_SPAN);
1671 NapatechSetFilter(hconfig, ntpl_cmd);
1673 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1674 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER;keysort=sorted]=(Layer3Header[8]/128,Layer3Header[24]/128,Layer4Header[0]/16,Layer4Header[2]/16)",
1675 NAPATECH_KEYTYPE_IPV6_SPAN, NAPATECH_KEYTYPE_IPV6_SPAN);
1676 NapatechSetFilter(hconfig, ntpl_cmd);
1680 char ports_ntpl_a[64];
1681 char ports_ntpl_b[64];
1682 memset(ports_ntpl_a, 0,
sizeof(ports_ntpl_a));
1683 memset(ports_ntpl_b, 0,
sizeof(ports_ntpl_b));
1685 for (pair = 0; pair < iteration; ++pair) {
1688 if (!is_span_port[ports_spec.first[pair]]) {
1689 snprintf(port_str,
sizeof(port_str),
"%s%u ", strlen(ports_ntpl_a) == 0 ?
"" :
",", ports_spec.first[pair]);
1690 strlcat(ports_ntpl_a, port_str,
sizeof(ports_ntpl_a));
1692 snprintf(port_str,
sizeof(port_str),
"%s%u ", strlen(ports_ntpl_b) == 0 ?
"" :
",", ports_spec.second[pair]);
1693 strlcat(ports_ntpl_b, port_str,
sizeof(ports_ntpl_b));
1697 if (strlen(ports_ntpl_a) > 0) {
1699 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1700 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1702 NAPATECH_KEYTYPE_IPV4,
1703 NAPATECH_KEYTYPE_IPV4,
1704 NAPATECH_FLOWTYPE_DROP);
1705 NapatechSetFilter(hconfig, ntpl_cmd);
1708 if (strlen(ports_ntpl_b) > 0) {
1710 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1711 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1713 NAPATECH_KEYTYPE_IPV4,
1714 NAPATECH_KEYTYPE_IPV4,
1715 NAPATECH_FLOWTYPE_DROP);
1716 NapatechSetFilter(hconfig, ntpl_cmd);
1719 if (strlen(span_ports) > 0) {
1721 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1722 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1724 NAPATECH_KEYTYPE_IPV4_SPAN,
1725 NAPATECH_KEYTYPE_IPV4_SPAN,
1726 NAPATECH_FLOWTYPE_DROP);
1727 NapatechSetFilter(hconfig, ntpl_cmd);
1731 for (pair = 0; pair < iteration; ++pair) {
1733 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1734 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x2]=(Layer3Protocol==IPV4)and(port == %d)and(Key(KDEF%u,KeyID=%u)==%u)",
1735 ports_spec.second[pair],
1736 ports_spec.first[pair],
1737 NAPATECH_KEYTYPE_IPV4,
1738 NAPATECH_KEYTYPE_IPV4,
1739 NAPATECH_FLOWTYPE_PASS);
1740 NapatechSetFilter(hconfig, ntpl_cmd);
1742 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1743 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x2]=(Layer3Protocol==IPV4)and(port == %d)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1744 ports_spec.first[pair],
1745 ports_spec.second[pair],
1746 NAPATECH_KEYTYPE_IPV4,
1747 NAPATECH_KEYTYPE_IPV4,
1748 NAPATECH_FLOWTYPE_PASS);
1749 NapatechSetFilter(hconfig, ntpl_cmd);
1753 if (strlen(ports_ntpl_a) > 0) {
1755 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1756 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1758 NAPATECH_KEYTYPE_IPV6,
1759 NAPATECH_KEYTYPE_IPV6,
1760 NAPATECH_FLOWTYPE_DROP);
1761 NapatechSetFilter(hconfig, ntpl_cmd);
1764 if (strlen(ports_ntpl_b) > 0) {
1766 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1767 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1769 NAPATECH_KEYTYPE_IPV6,
1770 NAPATECH_KEYTYPE_IPV6,
1771 NAPATECH_FLOWTYPE_DROP);
1772 NapatechSetFilter(hconfig, ntpl_cmd);
1775 if (strlen(span_ports) > 0) {
1777 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1778 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1780 NAPATECH_KEYTYPE_IPV6_SPAN,
1781 NAPATECH_KEYTYPE_IPV6_SPAN,
1782 NAPATECH_FLOWTYPE_DROP);
1783 NapatechSetFilter(hconfig, ntpl_cmd);
1787 for (pair = 0; pair < iteration; ++pair) {
1788 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1789 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x4]=(Layer3Protocol==IPV6)and(port==%d)and(Key(KDEF%u,KeyID=%u)==%u)",
1790 ports_spec.second[pair],
1791 ports_spec.first[pair],
1792 NAPATECH_KEYTYPE_IPV6,
1793 NAPATECH_KEYTYPE_IPV6,
1794 NAPATECH_FLOWTYPE_PASS);
1795 NapatechSetFilter(hconfig, ntpl_cmd);
1797 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1798 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x4]=(Layer3Protocol==IPV6)and(port==%d)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1799 ports_spec.first[pair],
1800 ports_spec.second[pair],
1801 NAPATECH_KEYTYPE_IPV6,
1802 NAPATECH_KEYTYPE_IPV6,
1803 NAPATECH_FLOWTYPE_PASS);
1804 NapatechSetFilter(hconfig, ntpl_cmd);
1809 FatalError(
"Napatech Inline operation not supported by this FPGA version.");
1813 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
"assign[streamid=(%d..%d);colormask=0x0] = %s%s",
1814 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1815 NapatechSetFilter(hconfig, ntpl_cmd);
1820 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
"assign[streamid=(%d..%d)] = %s%s",
1821 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1822 NapatechSetFilter(hconfig, ntpl_cmd);
1829 for (stream_id = first_stream; stream_id < last_stream; ++stream_id) {
1833 uint32_t num_host_buffers = GetStreamNUMAs(stream_id, numa_nodes);
1835 snprintf(temp1, 256,
" stream %d: ", stream_id);
1837 for (uint32_t hb_id = 0; hb_id < num_host_buffers; ++hb_id) {
1838 snprintf(temp2, 256,
"%d ", numa_nodes[hb_id]);
1839 strlcat(temp1, temp2,
sizeof(temp1));
1845 if (first_stream == last_stream) {
1846 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1847 "Setup[state=active] = StreamId == %d",
1850 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1851 "Setup[state=active] = StreamId == (%d..%d)",
1852 first_stream, last_stream);
1854 NapatechSetFilter(hconfig, ntpl_cmd);
1856 NT_ConfigClose(hconfig);
1861 #endif // HAVE_NAPATECH