93 #include <unordered_map> 96 #define STR_INNER(A) #A 97 #define STR(A) STR_INNER(A) 112 if (status != NT_SUCCESS) {
115 std::cerr << message <<
": " << error_buffer << std::endl;
116 std::exit(EXIT_FAILURE);
129 status =
NT_ConfigOpen(&config_stream,
"flow_learn_span NT_ConfigOpen");
132 for (
const auto& ntpl : ntpls) {
149 const uint64_t* ptr =
reinterpret_cast<const uint64_t*
>(flow->
keyData);
153 return (ptr[0] * 45684803) ^
154 (ptr[1] * 198138211) ^
157 (ptr[4] * 3294876479) ^
158 (meta * 663664226587);
168 void rx_task(std::atomic<int>* ready, std::atomic<bool>* end_task,
169 uint32_t stream_id, std::function<
void(
const NtNetBuf_t&)> handle)
182 while (!end_task->load()) {
185 if (status == NT_STATUS_TIMEOUT || status == NT_STATUS_TRYAGAIN)
continue;
213 std::unordered_multimap<uint64_t, std::unique_ptr<NtFlow_t>>
flow_map;
233 while (!end_task->load()) {
240 int status =
NT_FlowWrite(flow_stream, flow_raw_ptr, -1);
260 static uint32_t flow_id = 0;
267 const uint8_t* packet =
reinterpret_cast<const uint8_t*
>(dyn4) + dyn4->
descrLength;
269 auto flow = std::unique_ptr<NtFlow_t>(
new NtFlow_t);
270 std::memset(flow.get(), 0x0,
sizeof(
NtFlow_t));
272 const uint8_t* ipv4_src = packet + dyn4->
offset0;
273 const uint8_t* ipv4_dst = packet + dyn4->
offset0 + 4;
275 const uint8_t* udp_src = packet + dyn4->
offset1;
276 const uint8_t* udp_dst = packet + dyn4->
offset1 + 2;
282 if (std::lexicographical_compare(ipv4_src, ipv4_src + 4, ipv4_dst, ipv4_dst + 4) ||
283 (std::equal(ipv4_src, ipv4_src + 4, ipv4_dst) &&
284 std::lexicographical_compare(udp_src, udp_src + 2, udp_dst, udp_dst + 2))) {
286 std::memcpy(flow->keyData, ipv4_src, 4);
287 std::memcpy(flow->keyData + 4, ipv4_dst, 4);
288 std::memcpy(flow->keyData + 8, udp_src, 2);
289 std::memcpy(flow->keyData + 10, udp_dst, 2);
292 std::memcpy(flow->keyData, ipv4_dst, 4);
293 std::memcpy(flow->keyData + 4, ipv4_src, 4);
294 std::memcpy(flow->keyData + 8, udp_dst, 2);
295 std::memcpy(flow->keyData + 10, udp_src, 2);
304 flow->ipProtocolField = 0x11;
306 flow->keySetId = key_set_id;
308 flow->gfi = 0x1 &
gGfi;
314 auto flow_raw_ptr = flow.get();
320 auto range = flow_map.equal_range(hash_key);
321 for (
auto it = range.first; it != range.second; ++it) {
322 if (std::equal(flow->keyData, flow->keyData + 40, it->second->keyData) &&
323 flow->ipProtocolField == it->second->ipProtocolField &&
324 flow->keyId == it->second->keyId && flow->keySetId == it->second->keySetId) {
329 flow->id = flow_id++;
330 flow_map.insert(std::pair<uint64_t, std::unique_ptr<NtFlow_t>>{hash_key, std::move(flow)});
366 int main(
int argc,
char* argv[])
368 constexpr uint8_t adapter_no = 0;
370 if (argc == 2 && strcmp(argv[1],
"gfi") == 0)
372 std::cout <<
"Flow information will be generated" << std::endl;
377 std::cout <<
"Flow information will not be generated" << std::endl;
381 int status =
NT_Init(NTAPI_VERSION);
390 "DefineMacro(\"FilterCheck\", \"Port==$1 and Layer3Protocol==IPv4 and Layer4Protocol==UDP\")",
391 "DefineMacro(\"KeyTypeProtoSpecs\", \"(layer3header[12]/32, layer3header[16]/32, layer4header[0]/16,layer4header[2]/16)\")",
397 "KeyType[Name=kt] = {32, 32, 16, 16}",
398 "KeyDef[Name=kd; KeyType=kt; IpProtocolField=Outer; KeySort=Sorted] = KeyTypeProtoSpecs",
401 "Assign[StreamId=0; Descriptor=DYN4, Offset0=Layer3Header[12], Offset1=Layer4Header[0]] = FilterCheck(0) and Key(kd, KeyID=1) == MISS",
402 "Assign[StreamId=1; Descriptor=DYN4, Offset0=Layer3Header[12], Offset1=Layer4Header[0]] = FilterCheck(0) and Key(kd, KeyID=1) == " STR(
BLACKLIST),
403 "Assign[StreamId=2; Descriptor=DYN4, Offset0=Layer3Header[12], Offset1=Layer4Header[0]] = FilterCheck(0) and Key(kd, KeyID=1) == " STR(
WHITELIST),
407 "Assign[StreamId=Drop; Priority=10]=All" 411 NtFlowAttr_t flow_attr;
420 std::cout <<
"Detected Flow Stream API verion " << FlowStreamVersion << std::endl;
423 std::atomic<bool> end_task {
false};
424 std::atomic<int> ready {0};
432 while(ready.load() < 4) std::this_thread::yield();
434 std::cout <<
"Press enter to end application..." << std::endl;
438 end_task.store(
true);
440 if (flow_program_task0.joinable()) flow_program_task0.join();
441 if (rx_task2.joinable()) rx_task2.join();
442 if (rx_task1.joinable()) rx_task1.join();
443 if (rx_task0.joinable()) rx_task0.join();