37 #ifdef NAPATECH_ENABLE_BYPASS
43 typedef struct FlowStatsCounters_
45 uint16_t active_bypass_flows;
46 uint16_t total_bypass_flows;
50 static int bypass_supported;
51 int NapatechIsBypassSupported(
void)
53 return bypass_supported;
61 int NapatechGetNumAdapters(
void)
66 static int num_adapters = -1;
68 if (num_adapters == -1) {
69 if ((status = NT_InfoOpen(&hInfo,
"InfoStream")) != NT_SUCCESS) {
74 hInfoSys.cmd = NT_INFO_CMD_READ_SYSTEM;
75 if ((status = NT_InfoRead(hInfo, &hInfoSys)) != NT_SUCCESS) {
80 num_adapters = hInfoSys.u.system.data.numAdapters;
96 int NapatechVerifyBypassSupport(
void)
100 int num_adapters = NapatechGetNumAdapters();
101 SCLogInfo(
"Found %d Napatech adapters.", num_adapters);
102 NtFlowStream_t hFlowStream;
109 for (adapter = 0; adapter < num_adapters; ++adapter) {
113 NT_FlowOpenAttrInit(&attr);
114 NT_FlowOpenAttrSetAdapterNo(&attr, adapter);
116 snprintf(flow_name,
sizeof(flow_name),
"Flow stream %d", adapter );
117 SCLogInfo(
"Opening flow programming stream: %s\n", flow_name);
118 if ((status = NT_FlowOpen_Attr(&hFlowStream, flow_name, &attr)) != NT_SUCCESS) {
119 SCLogWarning(
"Napatech bypass functionality not supported by the FPGA version on "
120 "adapter %d - disabling support.",
122 bypass_supported = 0;
125 NT_FlowClose(hFlowStream);
128 bypass_supported = 1;
129 return bypass_supported;
143 static void UpdateFlowStats(
145 NtInfoStream_t hInfo,
146 NtStatStream_t hstat_stream,
147 FlowStatsCounters flow_counters,
151 NtStatistics_t hStat;
154 uint64_t programed = 0;
155 uint64_t removed = 0;
158 for (adapter = 0; adapter < NapatechGetNumAdapters(); ++adapter) {
159 hStat.cmd = NT_STATISTICS_READ_CMD_FLOW_V0;
160 hStat.u.flowData_v0.clear = clear_stats;
161 hStat.u.flowData_v0.adapterNo = adapter;
162 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
166 programed = hStat.u.flowData_v0.learnDone;
167 removed = hStat.u.flowData_v0.unlearnDone
168 + hStat.u.flowData_v0.automaticUnlearnDone
169 + hStat.u.flowData_v0.timeoutUnlearnDone;
172 StatsSetUI64(
tv, flow_counters.active_bypass_flows, programed - removed);
207 #define MAX_HOSTBUFFERS 8
218 static uint16_t TestStreamConfig(
219 NtInfoStream_t hInfo,
220 NtStatStream_t hstat_stream,
224 uint16_t num_active = 0;
226 for (uint16_t inst = 0; inst < num_inst; ++inst) {
231 memset(&stat, 0,
sizeof (NtStatistics_t));
234 stat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
235 stat.u.usageData_v0.streamid = (uint8_t)
stream_config[inst].stream_id;
237 if ((status = NT_StatRead(hstat_stream, &stat)) != NT_SUCCESS) {
242 if (stat.u.usageData_v0.data.numHostBufferUsed > 0) {
273 NtInfoStream_t hInfo,
274 NtStatStream_t hstat_stream,
275 uint16_t num_streams,
282 int enable_stream_stats,
291 NtInfo_t hStreamInfo;
292 NtStatistics_t hStat;
295 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
296 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
302 if ((num_active = TestStreamConfig(hInfo, hstat_stream,
stream_config, num_streams)) == 0) {
308 uint16_t inst_id = 0;
309 uint32_t stream_cnt = 0;
310 for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
311 while (inst_id < num_streams) {
318 if (inst_id == num_streams)
322 memset(&hStat, 0,
sizeof (NtStatistics_t));
323 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
324 hStat.u.usageData_v0.streamid = (uint8_t)
stream_config[inst_id].stream_id;
326 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
333 uint64_t rx_pkts_total = 0;
334 uint64_t rx_byte_total = 0;
335 uint64_t drop_pkts_total = 0;
336 uint64_t drop_byte_total = 0;
338 for (uint32_t hbCount = 0; hbCount < hStat.u.usageData_v0.data.numHostBufferUsed; hbCount++) {
340 rxPktsStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
341 rxByteStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
342 dropPktStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
343 dropByteStart[stream_id] += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.bytes;
346 rx_pkts_total += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.frames;
347 rx_byte_total += hStat.u.usageData_v0.data.hb[hbCount].stat.rx.bytes;
348 drop_pkts_total += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.frames;
349 drop_byte_total += hStat.u.usageData_v0.data.hb[hbCount].stat.drop.bytes;
359 if (enable_stream_stats) {
370 for (stream_id = 0; stream_id < num_streams; ++stream_id) {
372 #ifndef NAPATECH_ENABLE_BYPASS
381 #ifndef NAPATECH_ENABLE_BYPASS
395 memset(&hStat, 0,
sizeof (NtStatistics_t));
397 #ifdef NAPATECH_ENABLE_BYPASS
398 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V3;
399 hStat.u.query_v3.clear = 0;
402 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V2;
403 hStat.u.query_v2.clear = 0;
406 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
407 if (status == NT_STATUS_TIMEOUT) {
408 SCLogInfo(
"Statistics timed out - will retry next time.");
416 #ifdef NAPATECH_ENABLE_BYPASS
419 uint64_t total_dispatch_host_pkts = 0;
420 uint64_t total_dispatch_host_byte = 0;
421 uint64_t total_dispatch_drop_pkts = 0;
422 uint64_t total_dispatch_drop_byte = 0;
423 uint64_t total_dispatch_fwd_pkts = 0;
424 uint64_t total_dispatch_fwd_byte = 0;
426 for (adapter = 0; adapter < NapatechGetNumAdapters(); ++adapter) {
427 total_dispatch_host_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[0].pkts;
428 total_dispatch_host_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[0].octets;
430 total_dispatch_drop_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].pkts
431 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].pkts;
432 total_dispatch_drop_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].octets
433 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].octets;
435 total_dispatch_fwd_pkts += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].pkts
436 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[4].pkts;
437 total_dispatch_fwd_byte += hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].octets
438 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[4].octets;
441 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].pkts
442 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].pkts
443 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[3].pkts;
446 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[1].octets
447 + hStat.u.query_v3.data.adapter.aAdapters[adapter].color.aColor[2].octets;
477 static void *NapatechStatsLoop(
void *arg)
482 NtInfoStream_t hInfo;
483 NtStatStream_t hstat_stream;
485 int enable_stream_stats = 0;
488 if (
ConfGetBool(
"napatech.inline", &is_inline) == 0) {
492 if (
ConfGetBool(
"napatech.enable-stream-stats", &enable_stream_stats) == 0) {
494 enable_stream_stats = 0;
501 if ((status = NT_InfoOpen(&hInfo,
"StatsLoopInfoStream")) != NT_SUCCESS) {
506 if ((status = NT_StatOpen(&hstat_stream,
"StatsLoopStatsStream")) != NT_SUCCESS) {
511 NtStatistics_t hStat;
512 memset(&hStat, 0,
sizeof (NtStatistics_t));
514 #ifdef NAPATECH_ENABLE_BYPASS
515 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V3;
516 hStat.u.query_v3.clear = 1;
518 hStat.cmd = NT_STATISTICS_READ_CMD_QUERY_V2;
519 hStat.u.query_v2.clear = 1;
522 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
528 memset(&total_counters, 0,
sizeof(total_counters));
531 memset(&dispatch_host, 0,
sizeof(dispatch_host));
534 memset(&dispatch_drop, 0,
sizeof(dispatch_drop));
537 memset(&dispatch_fwd, 0,
sizeof(dispatch_fwd));
556 if (enable_stream_stats) {
557 for (
int i = 0; i < stream_cnt; ++i) {
560 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
563 snprintf(pkts_buf, 32,
"napa%d.pkts",
stream_config[i].stream_id);
568 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
570 snprintf(byte_buf, 32,
"napa%d.bytes",
stream_config[i].stream_id);
573 char *drop_pkts_buf =
SCCalloc(1, 32);
574 if (
unlikely(drop_pkts_buf == NULL)) {
575 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
577 snprintf(drop_pkts_buf, 32,
"napa%d.drop_pkts",
stream_config[i].stream_id);
580 char *drop_byte_buf =
SCCalloc(1, 32);
581 if (
unlikely(drop_byte_buf == NULL)) {
582 FatalError(
"Failed to allocate memory for NAPATECH stream counter.");
584 snprintf(drop_byte_buf, 32,
"napa%d.drop_byte",
stream_config[i].stream_id);
589 #ifdef NAPATECH_ENABLE_BYPASS
590 FlowStatsCounters flow_counters;
591 if (bypass_supported) {
604 #ifdef NAPATECH_ENABLE_BYPASS
605 if (bypass_supported) {
619 if (enable_stream_stats) {
620 for (
int i = 0; i < stream_cnt; ++i) {
630 UpdateFlowStats(
tv, hInfo, hstat_stream, flow_counters, 1);
634 uint32_t num_active = UpdateStreamStats(
tv, hInfo, hstat_stream,
636 dispatch_host, dispatch_drop, dispatch_fwd,
637 is_inline, enable_stream_stats, stream_counters);
640 SCLogInfo(
"num_active: %d, stream_cnt: %d", num_active, stream_cnt);
641 SCLogWarning(
"Some or all of the configured streams are not created. Proceeding with "
648 SCLogDebug(
"NapatechStatsLoop THV_KILL detected");
652 UpdateStreamStats(
tv, hInfo, hstat_stream,
654 dispatch_host, dispatch_drop, dispatch_fwd,
655 is_inline, enable_stream_stats,
658 #ifdef NAPATECH_ENABLE_BYPASS
659 if (bypass_supported) {
660 UpdateFlowStats(
tv, hInfo, hstat_stream, flow_counters, 0);
669 if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
675 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
688 #define MAX_HOSTBUFFER 4
689 #define MAX_STREAMS 256
690 #define HB_HIGHWATER 2048 //1982
702 static bool RegisteredStream(uint16_t stream_id, uint16_t num_registered,
705 for (uint16_t reg_id = 0; reg_id < num_registered; ++reg_id) {
706 if (stream_id == registered_streams[reg_id].stream_id) {
718 static uint32_t CountWorkerThreads(
void)
720 int worker_count = 0;
729 if (strcmp(affinity->
val,
"decode-cpu-set") == 0 ||
730 strcmp(affinity->
val,
"stream-cpu-set") == 0 ||
731 strcmp(affinity->
val,
"reject-cpu-set") == 0 ||
732 strcmp(affinity->
val,
"output-cpu-set") == 0) {
736 if (strcmp(affinity->
val,
"worker-cpu-set") == 0) {
746 if (strncmp(lnode->
val,
"all", 4) == 0) {
749 FatalError(
"Only one Napatech port specifier type allowed.");
753 }
else if ((end_str = strchr(lnode->
val,
'-'))) {
756 FatalError(
"Only one Napatech port specifier type allowed.");
763 " worker range start: '%s'",
768 " worker range end: '%s'",
769 (end_str != NULL) ? (
const char *)(end_str + 1) :
"Null");
773 " worker range start: '%d' is greater than end: '%d'",
776 worker_count = end - start + 1;
781 FatalError(
"Napatech port range specifiers cannot be combined with "
782 "individual stream specifiers.");
806 char error_buffer[80];
807 NtStatStream_t hstat_stream;
808 NtStatistics_t hStat;
809 NtInfoStream_t info_stream;
811 uint16_t instance_cnt = 0;
812 int use_all_streams = 0;
813 int set_cpu_affinity = 0;
815 uint16_t stream_id = 0;
825 if (
ConfGetBool(
"napatech.use-all-streams", &use_all_streams) == 0) {
830 if ((status = NT_InfoOpen(&info_stream,
"SuricataStreamInfo")) != NT_SUCCESS) {
835 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
840 if (use_all_streams) {
841 info.cmd = NT_INFO_CMD_READ_STREAM;
842 if ((status = NT_InfoRead(info_stream, &info)) != NT_SUCCESS) {
847 while (instance_cnt < info.u.stream.data.count) {
855 memset(&hStat, 0,
sizeof (NtStatistics_t));
858 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
859 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
861 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
863 NT_ExplainError(status, error_buffer,
sizeof (error_buffer));
864 SCLogError(
"NT_StatRead() failed: %s\n", error_buffer);
868 if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
880 (void)
ConfGetBool(
"threading.set-cpu-affinity", &set_cpu_affinity);
883 end = CountWorkerThreads() - 1;
887 if ((ntstreams =
ConfGetNode(
"napatech.streams")) == NULL) {
888 SCLogError(
"Failed retrieving napatech.streams from Config");
890 SCLogError(
"if set-cpu-affinity: no in conf then napatech.streams must be "
904 if (stream == NULL) {
905 SCLogError(
"Couldn't Parse Stream Configuration");
909 char *end_str = strchr(stream->
val,
'-');
912 SCLogError(
"Only one Napatech stream range specifier allowed.");
918 (
const char *)stream->
val) < 0) {
920 "stream id start: '%s'",
925 "stream id end: '%s'",
926 (end_str != NULL) ? (
const char *)(end_str + 1) :
"Null");
930 FatalError(
"Napatech range and individual specifiers cannot be combined.");
934 10, 0, (
const char *)stream->
val) < 0) {
945 for (stream_id = start; stream_id <= end; ++stream_id) {
950 memset(&hStat, 0,
sizeof (NtStatistics_t));
953 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
954 hStat.u.usageData_v0.streamid =
957 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
962 if (hStat.u.usageData_v0.data.numHostBufferUsed > 0) {
970 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
975 if ((status = NT_InfoClose(info_stream)) != NT_SUCCESS) {
983 static void *NapatechBufMonitorLoop(
void *arg)
987 NtInfo_t hStreamInfo;
988 NtStatistics_t hStat;
989 NtInfoStream_t hInfo;
990 NtStatStream_t hstat_stream;
993 const uint32_t alertInterval = 25;
995 #ifndef NAPATECH_ENABLE_BYPASS
1006 if ((status = NT_InfoOpen(&hInfo,
"InfoStream")) != NT_SUCCESS) {
1011 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
1017 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
1018 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
1025 if (num_registered == -1) {
1032 SCLogDebug(
"NapatechBufMonitorLoop THV_KILL detected");
1039 hStreamInfo.cmd = NT_INFO_CMD_READ_STREAM;
1040 if ((status = NT_InfoRead(hInfo, &hStreamInfo)) != NT_SUCCESS) {
1045 char pktCntStr[4096];
1046 memset(pktCntStr, 0,
sizeof (pktCntStr));
1048 uint32_t stream_id = 0;
1049 uint32_t stream_cnt = 0;
1050 uint32_t num_streams = hStreamInfo.u.stream.data.count;
1052 for (stream_cnt = 0; stream_cnt < num_streams; ++stream_cnt) {
1057 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
1058 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
1060 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
1065 if (hStat.u.usageData_v0.data.numHostBufferUsed == 0) {
1069 }
while (hStat.u.usageData_v0.data.numHostBufferUsed == 0);
1071 if (RegisteredStream(stream_id, num_registered, registered_streams)) {
1073 #ifndef NAPATECH_ENABLE_BYPASS
1074 ave_OB_fill_level[stream_id] = 0;
1077 ave_HB_fill_level[stream_id] = 0;
1079 for (uint32_t hb_count = 0; hb_count < hStat.u.usageData_v0.data.numHostBufferUsed; hb_count++) {
1081 #ifndef NAPATECH_ENABLE_BYPASS
1082 OB_fill_level[hb_count] =
1083 ((100 * hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.used) /
1084 hStat.u.usageData_v0.data.hb[hb_count].onboardBuffering.size);
1086 if (OB_fill_level[hb_count] > 100) {
1087 OB_fill_level[hb_count] = 100;
1090 uint32_t bufSize = hStat.u.usageData_v0.data.hb[hb_count].enQueuedAdapter / 1024
1091 + hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024
1092 + hStat.u.usageData_v0.data.hb[hb_count].enQueued / 1024
1095 HB_fill_level[hb_count] = (uint32_t)
1096 ((100 * hStat.u.usageData_v0.data.hb[hb_count].deQueued / 1024) /
1099 #ifndef NAPATECH_ENABLE_BYPASS
1100 ave_OB_fill_level[stream_id] += OB_fill_level[hb_count];
1103 ave_HB_fill_level[stream_id] += HB_fill_level[hb_count];
1106 #ifndef NAPATECH_ENABLE_BYPASS
1107 ave_OB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
1110 ave_HB_fill_level[stream_id] /= hStat.u.usageData_v0.data.numHostBufferUsed;
1113 if (ave_HB_fill_level[stream_id] >= (HB_alert_level[stream_id] + alertInterval)) {
1115 while (ave_HB_fill_level[stream_id] >= HB_alert_level[stream_id] + alertInterval) {
1116 HB_alert_level[stream_id] += alertInterval;
1118 SCLogPerf(
"nt%d - Increasing Host Buffer Fill Level : %4d%%",
1119 stream_id, ave_HB_fill_level[stream_id] - 1);
1122 if (HB_alert_level[stream_id] > 0) {
1123 if ((ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval))) {
1124 SCLogPerf(
"nt%d - Decreasing Host Buffer Fill Level: %4d%%",
1125 stream_id, ave_HB_fill_level[stream_id]);
1127 while (ave_HB_fill_level[stream_id] <= (HB_alert_level[stream_id] - alertInterval)) {
1128 if ((HB_alert_level[stream_id]) > 0) {
1129 HB_alert_level[stream_id] -= alertInterval;
1135 #ifndef NAPATECH_ENABLE_BYPASS
1137 if (ave_OB_fill_level[stream_id] >= (OB_alert_level[stream_id] + alertInterval)) {
1138 while (ave_OB_fill_level[stream_id] >= OB_alert_level[stream_id] + alertInterval) {
1139 OB_alert_level[stream_id] += alertInterval;
1142 SCLogPerf(
"nt%d - Increasing Adapter SDRAM Fill Level: %4d%%",
1143 stream_id, ave_OB_fill_level[stream_id]);
1146 if (OB_alert_level[stream_id] > 0) {
1147 if ((ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval))) {
1148 SCLogPerf(
"nt%d - Decreasing Adapter SDRAM Fill Level : %4d%%",
1149 stream_id, ave_OB_fill_level[stream_id]);
1151 while (ave_OB_fill_level[stream_id] <= (OB_alert_level[stream_id] - alertInterval)) {
1152 if ((OB_alert_level[stream_id]) > 0) {
1153 OB_alert_level[stream_id] -= alertInterval;
1164 if ((status = NT_InfoClose(hInfo)) != NT_SUCCESS) {
1170 if ((status = NT_StatClose(hstat_stream)) != NT_SUCCESS) {
1190 "custom", NapatechStatsLoop, 0);
1192 if (stats_tv == NULL) {
1193 FatalError(
"Error creating a thread for NapatechStats - Killing engine.");
1197 FatalError(
"Failed to spawn thread for NapatechStats - Killing engine.");
1200 #ifdef NAPATECH_ENABLE_BYPASS
1201 if (bypass_supported) {
1202 SCLogInfo(
"Napatech bypass functionality enabled.");
1209 "custom", NapatechBufMonitorLoop, 0);
1211 if (buf_monitor_tv == NULL) {
1212 FatalError(
"Error creating a thread for NapatechBufMonitor - Killing engine.");
1216 FatalError(
"Failed to spawn thread for NapatechBufMonitor - Killing engine.");
1225 uint32_t status = 0;
1226 static NtConfigStream_t hconfig;
1229 snprintf(ntpl_cmd, 64,
"setup[numanode=%d] = streamid == %d", numa, stream);
1231 NtNtplInfo_t ntpl_info;
1233 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1238 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info, NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1239 status = ntpl_info.ntplId;
1249 static uint32_t NapatechSetHashmode(
void)
1251 uint32_t status = 0;
1252 const char *hash_mode;
1253 static NtConfigStream_t hconfig;
1255 NtNtplInfo_t ntpl_info;
1257 uint32_t filter_id = 0;
1260 ConfGet(
"napatech.hashmode", &hash_mode);
1262 snprintf(ntpl_cmd, 64,
"hashmode = %s", hash_mode);
1265 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1270 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1271 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1272 filter_id = ntpl_info.ntplId;
1273 SCLogConfig(
"Napatech hashmode: %s ID: %d", hash_mode, status);
1282 static uint32_t GetStreamNUMAs(uint32_t stream_id,
int stream_numas[])
1284 NtStatistics_t hStat;
1285 NtStatStream_t hstat_stream;
1289 stream_numas[i] = -1;
1291 if ((status = NT_StatOpen(&hstat_stream,
"StatsStream")) != NT_SUCCESS) {
1296 char pktCntStr[4096];
1297 memset(pktCntStr, 0,
sizeof (pktCntStr));
1301 hStat.cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0;
1302 hStat.u.usageData_v0.streamid = (uint8_t) stream_id;
1304 if ((status = NT_StatRead(hstat_stream, &hStat)) != NT_SUCCESS) {
1309 for (uint32_t hb_id = 0; hb_id < hStat.u.usageData_v0.data.numHostBufferUsed; ++hb_id) {
1310 stream_numas[hb_id] = hStat.u.usageData_v0.data.hb[hb_id].numaNode;
1313 return hStat.u.usageData_v0.data.numHostBufferUsed;
1316 static int NapatechSetFilter(NtConfigStream_t hconfig,
char *ntpl_cmd)
1319 int local_filter_id = 0;
1321 NtNtplInfo_t ntpl_info;
1322 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1323 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1324 SCLogConfig(
"NTPL filter assignment \"%s\" returned filter id %4d",
1325 ntpl_cmd, local_filter_id);
1331 return local_filter_id;
1336 uint32_t status = 0;
1337 static NtConfigStream_t hconfig;
1339 NtNtplInfo_t ntpl_info;
1341 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1346 snprintf(ntpl_cmd, 64,
"delete = all");
1347 if ((status = NT_NTPL(hconfig, ntpl_cmd, &ntpl_info,
1348 NT_NTPL_PARSER_VALIDATE_NORMAL)) == NT_SUCCESS) {
1349 status = ntpl_info.ntplId;
1355 NT_ConfigClose(hconfig);
1363 #define PORTS_SPEC_SIZE 64
1365 struct ports_spec_s {
1372 ports_spec.all =
false;
1377 NtConfigStream_t hconfig;
1380 #ifdef NAPATECH_ENABLE_BYPASS
1384 char span_ports[128];
1385 memset(span_ports, 0,
sizeof(span_ports));
1387 if (
ConfGetBool(
"napatech.inline", &is_inline) == 0) {
1391 NapatechSetHashmode();
1393 if ((status = NT_ConfigOpen(&hconfig,
"ConfigStream")) != NT_SUCCESS) {
1398 if (first_stream == last_stream) {
1399 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1400 "Setup[state=inactive] = StreamId == %d",
1403 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1404 "Setup[state=inactive] = StreamId == (%d..%d)",
1405 first_stream, last_stream);
1407 NapatechSetFilter(hconfig, ntpl_cmd);
1409 #ifdef NAPATECH_ENABLE_BYPASS
1411 SCLogInfo(
"Napatech Hardware Bypass enabled.");
1413 SCLogInfo(
"Napatech Hardware Bypass available but disabled.");
1417 SCLogInfo(
"Napatech Hardware Bypass requested in conf but is not available.");
1420 SCLogInfo(
"Napatech Hardware Bypass disabled.");
1425 SCLogInfo(
"Napatech configured for inline mode.");
1428 SCLogInfo(
"Napatech configured for passive (non-inline) mode.");
1434 if ((ntports =
ConfGetNode(
"napatech.ports")) == NULL) {
1435 FatalError(
"Failed retrieving napatech.ports from Conf");
1443 SCLogInfo(
"Listening on the following Napatech ports:");
1449 FatalError(
"Couldn't Parse Port Configuration");
1453 #ifdef NAPATECH_ENABLE_BYPASS
1454 if (strchr(port->
val,
'-')) {
1460 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1462 FatalError(
"Error with napatec.ports in conf file. When running in inline "
1463 "mode the two ports specifying a segment must be different.");
1466 is_span_port[ports_spec.first[iteration]] = 1;
1468 if (strlen(span_ports) == 0) {
1469 snprintf(span_ports,
sizeof (span_ports),
"%d", ports_spec.first[iteration]);
1472 snprintf(temp,
sizeof(temp),
",%d", ports_spec.first[iteration]);
1473 strlcat(span_ports, temp,
sizeof(span_ports));
1480 SCLogError(
"Invalid napatech.ports specification in conf file.");
1481 SCLogError(
"Two ports on a segment must reside on the same adapter. port %d "
1482 "is on adapter %d, port %d is on adapter %d.",
1483 ports_spec.first[iteration],
1485 ports_spec.second[iteration],
1491 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1492 SCLogInfo(
" span_port: %d", ports_spec.first[iteration]);
1494 SCLogInfo(
" %s: %d - %d", is_inline ?
"inline_ports" :
"tap_ports", ports_spec.first[iteration], ports_spec.second[iteration]);
1497 if (iteration == 0) {
1498 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1499 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%d", ports_spec.first[iteration]);
1501 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%d,%d", ports_spec.first[iteration], ports_spec.second[iteration]);
1505 if (ports_spec.first[iteration] == ports_spec.second[iteration]) {
1506 snprintf(temp,
sizeof(temp),
",%d", ports_spec.first[iteration]);
1508 snprintf(temp,
sizeof(temp),
",%d,%d", ports_spec.first[iteration], ports_spec.second[iteration]);
1510 strlcat(ports_spec.str, temp,
sizeof(ports_spec.str));
1513 FatalError(
"When using hardware flow bypass ports must be specified as segments. "
1514 "E.g. ports: [0-1, 0-2]");
1518 if (strncmp(port->
val,
"all", 3) == 0) {
1521 FatalError(
"Only one Napatech port specifier type is allowed.");
1525 ports_spec.all =
true;
1526 snprintf(ports_spec.str, sizeof (ports_spec.str),
"all");
1527 }
else if (strchr(port->
val,
'-')) {
1530 FatalError(
"Only one Napatech port specifier is allowed when hardware bypass "
1531 "is disabled. (E.g. ports: [0-4], NOT ports: [0-1,2-3])");
1537 snprintf(ports_spec.str, sizeof (ports_spec.str),
"(%d..%d)", ports_spec.first[iteration], ports_spec.second[iteration]);
1541 FatalError(
"Napatech port range specifiers cannot be combined with individual "
1542 "stream specifiers.");
1549 if (iteration == 0) {
1550 snprintf(ports_spec.str, sizeof (ports_spec.str),
"%s", port->
val);
1552 strlcat(ports_spec.str,
",",
sizeof(ports_spec.str));
1553 strlcat(ports_spec.str, port->
val,
sizeof(ports_spec.str));
1560 #ifdef NAPATECH_ENABLE_BYPASS
1561 if (bypass_supported) {
1563 char inline_setup_cmd[512];
1564 if (first_stream == last_stream) {
1565 snprintf(inline_setup_cmd,
sizeof (ntpl_cmd),
1566 "Setup[TxDescriptor=Dyn;TxPorts=%s;RxCRC=False;TxPortPos=112;UseWL=True] = StreamId == %d",
1567 ports_spec.str, first_stream);
1569 snprintf(inline_setup_cmd,
sizeof (ntpl_cmd),
1570 "Setup[TxDescriptor=Dyn;TxPorts=%s;RxCRC=False;TxPortPos=112;UseWL=True] = StreamId == (%d..%d)",
1571 ports_spec.str, first_stream, last_stream);
1573 NapatechSetFilter(hconfig, inline_setup_cmd);
1576 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1577 "assign[priority=3;streamid=(%d..%d);colormask=0x10000000;"
1578 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s",
1579 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1580 NapatechSetFilter(hconfig, ntpl_cmd);
1583 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1584 "assign[priority=2;streamid=(%d..%d);colormask=0x11000000;"
1585 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1586 "]= %s%s and (Layer3Protocol==IPV4)",
1587 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1588 NapatechSetFilter(hconfig, ntpl_cmd);
1591 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1592 "assign[priority=2;streamid=(%d..%d);colormask=0x14000000;"
1593 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s and (Layer3Protocol==IPV6)",
1594 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1595 NapatechSetFilter(hconfig, ntpl_cmd);
1597 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1598 "assign[priority=2;streamid=(%d..%d);colormask=0x10100000;"
1599 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]]= %s%s and (Layer4Protocol==TCP)",
1600 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1601 NapatechSetFilter(hconfig, ntpl_cmd);
1603 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1604 "assign[priority=2;streamid=(%d..%d);colormask=0x10200000;"
1605 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1606 "]= %s%s and (Layer4Protocol==UDP)",
1607 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1608 NapatechSetFilter(hconfig, ntpl_cmd);
1610 if (strlen(span_ports) > 0) {
1611 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1612 "assign[priority=2;streamid=(%d..%d);colormask=0x00001000;"
1613 "Descriptor=DYN3,length=24,colorbits=32,Offset0=Layer3Header[0],Offset1=Layer4Header[0]"
1615 first_stream, last_stream, span_ports);
1616 NapatechSetFilter(hconfig, ntpl_cmd);
1619 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1620 "KeyType[name=KT%u]={sw_32_32,sw_16_16}",
1621 NAPATECH_KEYTYPE_IPV4);
1622 NapatechSetFilter(hconfig, ntpl_cmd);
1624 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1625 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER]=(Layer3Header[12]/32/32,Layer4Header[0]/16/16)",
1626 NAPATECH_KEYTYPE_IPV4, NAPATECH_KEYTYPE_IPV4);
1627 NapatechSetFilter(hconfig, ntpl_cmd);
1629 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1630 "KeyType[name=KT%u]={32,32,16,16}",
1631 NAPATECH_KEYTYPE_IPV4_SPAN);
1632 NapatechSetFilter(hconfig, ntpl_cmd);
1634 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1635 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER;keysort=sorted]=(Layer3Header[12]/32,Layer3Header[16]/32,Layer4Header[0]/16,Layer4Header[2]/16)",
1636 NAPATECH_KEYTYPE_IPV4_SPAN, NAPATECH_KEYTYPE_IPV4_SPAN);
1637 NapatechSetFilter(hconfig, ntpl_cmd);
1640 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1641 "KeyType[name=KT%u]={sw_128_128,sw_16_16}",
1642 NAPATECH_KEYTYPE_IPV6);
1643 NapatechSetFilter(hconfig, ntpl_cmd);
1645 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1646 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER]=(Layer3Header[8]/128/128,Layer4Header[0]/16/16)",
1647 NAPATECH_KEYTYPE_IPV6, NAPATECH_KEYTYPE_IPV6);
1648 NapatechSetFilter(hconfig, ntpl_cmd);
1651 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1652 "KeyType[name=KT%u]={128,128,16,16}",
1653 NAPATECH_KEYTYPE_IPV6_SPAN);
1654 NapatechSetFilter(hconfig, ntpl_cmd);
1656 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1657 "KeyDef[name=KDEF%u;KeyType=KT%u;ipprotocolfield=OUTER;keysort=sorted]=(Layer3Header[8]/128,Layer3Header[24]/128,Layer4Header[0]/16,Layer4Header[2]/16)",
1658 NAPATECH_KEYTYPE_IPV6_SPAN, NAPATECH_KEYTYPE_IPV6_SPAN);
1659 NapatechSetFilter(hconfig, ntpl_cmd);
1663 char ports_ntpl_a[64];
1664 char ports_ntpl_b[64];
1665 memset(ports_ntpl_a, 0,
sizeof(ports_ntpl_a));
1666 memset(ports_ntpl_b, 0,
sizeof(ports_ntpl_b));
1668 for (pair = 0; pair < iteration; ++pair) {
1671 if (!is_span_port[ports_spec.first[pair]]) {
1672 snprintf(port_str,
sizeof(port_str),
"%s%u ", strlen(ports_ntpl_a) == 0 ?
"" :
",", ports_spec.first[pair]);
1673 strlcat(ports_ntpl_a, port_str,
sizeof(ports_ntpl_a));
1675 snprintf(port_str,
sizeof(port_str),
"%s%u ", strlen(ports_ntpl_b) == 0 ?
"" :
",", ports_spec.second[pair]);
1676 strlcat(ports_ntpl_b, port_str,
sizeof(ports_ntpl_b));
1680 if (strlen(ports_ntpl_a) > 0) {
1682 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1683 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1685 NAPATECH_KEYTYPE_IPV4,
1686 NAPATECH_KEYTYPE_IPV4,
1687 NAPATECH_FLOWTYPE_DROP);
1688 NapatechSetFilter(hconfig, ntpl_cmd);
1691 if (strlen(ports_ntpl_b) > 0) {
1693 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1694 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1696 NAPATECH_KEYTYPE_IPV4,
1697 NAPATECH_KEYTYPE_IPV4,
1698 NAPATECH_FLOWTYPE_DROP);
1699 NapatechSetFilter(hconfig, ntpl_cmd);
1702 if (strlen(span_ports) > 0) {
1704 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1705 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV4)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1707 NAPATECH_KEYTYPE_IPV4_SPAN,
1708 NAPATECH_KEYTYPE_IPV4_SPAN,
1709 NAPATECH_FLOWTYPE_DROP);
1710 NapatechSetFilter(hconfig, ntpl_cmd);
1714 for (pair = 0; pair < iteration; ++pair) {
1716 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1717 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x2]=(Layer3Protocol==IPV4)and(port == %d)and(Key(KDEF%u,KeyID=%u)==%u)",
1718 ports_spec.second[pair],
1719 ports_spec.first[pair],
1720 NAPATECH_KEYTYPE_IPV4,
1721 NAPATECH_KEYTYPE_IPV4,
1722 NAPATECH_FLOWTYPE_PASS);
1723 NapatechSetFilter(hconfig, ntpl_cmd);
1725 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1726 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x2]=(Layer3Protocol==IPV4)and(port == %d)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1727 ports_spec.first[pair],
1728 ports_spec.second[pair],
1729 NAPATECH_KEYTYPE_IPV4,
1730 NAPATECH_KEYTYPE_IPV4,
1731 NAPATECH_FLOWTYPE_PASS);
1732 NapatechSetFilter(hconfig, ntpl_cmd);
1736 if (strlen(ports_ntpl_a) > 0) {
1738 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1739 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1741 NAPATECH_KEYTYPE_IPV6,
1742 NAPATECH_KEYTYPE_IPV6,
1743 NAPATECH_FLOWTYPE_DROP);
1744 NapatechSetFilter(hconfig, ntpl_cmd);
1747 if (strlen(ports_ntpl_b) > 0) {
1749 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1750 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1752 NAPATECH_KEYTYPE_IPV6,
1753 NAPATECH_KEYTYPE_IPV6,
1754 NAPATECH_FLOWTYPE_DROP);
1755 NapatechSetFilter(hconfig, ntpl_cmd);
1758 if (strlen(span_ports) > 0) {
1760 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1761 "assign[priority=1;streamid=drop;colormask=0x1]=(Layer3Protocol==IPV6)and(port == %s)and(Key(KDEF%u,KeyID=%u)==%u)",
1763 NAPATECH_KEYTYPE_IPV6_SPAN,
1764 NAPATECH_KEYTYPE_IPV6_SPAN,
1765 NAPATECH_FLOWTYPE_DROP);
1766 NapatechSetFilter(hconfig, ntpl_cmd);
1770 for (pair = 0; pair < iteration; ++pair) {
1771 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1772 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x4]=(Layer3Protocol==IPV6)and(port==%d)and(Key(KDEF%u,KeyID=%u)==%u)",
1773 ports_spec.second[pair],
1774 ports_spec.first[pair],
1775 NAPATECH_KEYTYPE_IPV6,
1776 NAPATECH_KEYTYPE_IPV6,
1777 NAPATECH_FLOWTYPE_PASS);
1778 NapatechSetFilter(hconfig, ntpl_cmd);
1780 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1781 "assign[priority=1;streamid=drop;DestinationPort=%d;colormask=0x4]=(Layer3Protocol==IPV6)and(port==%d)and(Key(KDEF%u,KeyID=%u,fieldaction=swap)==%u)",
1782 ports_spec.first[pair],
1783 ports_spec.second[pair],
1784 NAPATECH_KEYTYPE_IPV6,
1785 NAPATECH_KEYTYPE_IPV6,
1786 NAPATECH_FLOWTYPE_PASS);
1787 NapatechSetFilter(hconfig, ntpl_cmd);
1792 FatalError(
"Napatech Inline operation not supported by this FPGA version.");
1796 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
"assign[streamid=(%d..%d);colormask=0x0] = %s%s",
1797 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1798 NapatechSetFilter(hconfig, ntpl_cmd);
1803 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
"assign[streamid=(%d..%d)] = %s%s",
1804 first_stream, last_stream, ports_spec.all ?
"" :
"port==", ports_spec.str);
1805 NapatechSetFilter(hconfig, ntpl_cmd);
1812 for (stream_id = first_stream; stream_id < last_stream; ++stream_id) {
1816 uint32_t num_host_buffers = GetStreamNUMAs(stream_id, numa_nodes);
1818 snprintf(temp1, 256,
" stream %d: ", stream_id);
1820 for (uint32_t hb_id = 0; hb_id < num_host_buffers; ++hb_id) {
1821 snprintf(temp2, 256,
"%d ", numa_nodes[hb_id]);
1822 strlcat(temp1, temp2,
sizeof(temp1));
1828 if (first_stream == last_stream) {
1829 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1830 "Setup[state=active] = StreamId == %d",
1833 snprintf(ntpl_cmd,
sizeof (ntpl_cmd),
1834 "Setup[state=active] = StreamId == (%d..%d)",
1835 first_stream, last_stream);
1837 NapatechSetFilter(hconfig, ntpl_cmd);
1839 NT_ConfigClose(hconfig);
1844 #endif // HAVE_NAPATECH