├── tools ├── ft-fast-analyzer │ ├── README.md │ └── CMakeLists.txt ├── ft-orchestration │ ├── src │ │ ├── __init__.py │ │ ├── collector │ │ │ └── __init__.py │ │ ├── common │ │ │ └── __init__.py │ │ ├── config │ │ │ ├── __init__.py │ │ │ └── common.py │ │ ├── generator │ │ │ └── __init__.py │ │ ├── probe │ │ │ └── __init__.py │ │ └── topology │ │ │ └── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── dev │ │ │ ├── __init__.py │ │ │ ├── config │ │ │ │ ├── __init__.py │ │ │ │ └── files │ │ │ │ │ ├── cesnet-general.pem │ │ │ │ │ ├── collectors-invalid-1.yml │ │ │ │ │ ├── probes-invalid-1.yml │ │ │ │ │ ├── collectors-invalid-2.yml │ │ │ │ │ ├── generators-invalid-2.yml │ │ │ │ │ ├── generators-invalid-1.yml │ │ │ │ │ ├── probes-invalid-2.yml │ │ │ │ │ ├── authentication-invalid-2.yml │ │ │ │ │ ├── authentication.yml │ │ │ │ │ ├── authentication-invalid-3.yml │ │ │ │ │ ├── collectors.yml │ │ │ │ │ ├── probes-invalid-3.yml │ │ │ │ │ ├── probes-invalid-4.yml │ │ │ │ │ ├── authentication-invalid-1.yml │ │ │ │ │ ├── generators.yml │ │ │ │ │ ├── whitelists.yml │ │ │ │ │ ├── whitelists-invalid-include.yml │ │ │ │ │ ├── whitelists-invalid-circular.yml │ │ │ │ │ ├── probes.yml │ │ │ │ │ └── probes-invalid-bad-whitelist.yml │ │ │ ├── probe │ │ │ │ └── __init__.py │ │ │ ├── collector │ │ │ │ ├── __init__.py │ │ │ │ └── files │ │ │ │ │ ├── http_get.pcap │ │ │ │ │ └── ipv6-neighbor-discovery.pcap │ │ │ └── generator │ │ │ │ ├── __init__.py │ │ │ │ ├── input │ │ │ │ ├── dummy.pcap │ │ │ │ └── csv_basic_profile.csv │ │ │ │ ├── NTP_sync.pcap │ │ │ │ ├── ipv6-routing-header.pcap │ │ │ │ └── ref │ │ │ │ ├── ipv6-routing-header-vlan.pcap │ │ │ │ ├── ipv6-routing-header-dst-mac.pcap │ │ │ │ └── ipv6-routing-header-dst-mac-vlan.pcap │ │ └── validation │ │ │ └── conf │ │ │ ├── authentication.yml │ │ │ ├── collectors.yml │ │ │ ├── generators.yml │ │ │ └── probes.yml │ └── tox.ini ├── ft-analyzer │ ├── ftanalyzer │ │ ├── __init__.py │ │ ├── common │ │ │ └── __init__.py │ │ ├── replicator │ │ │ └── __init__.py │ │ ├── normalizer │ │ │ └── __init__.py │ │ ├── fields │ │ │ └── __init__.py │ │ ├── flow │ │ │ └── __init__.py │ │ ├── reports │ │ │ └── __init__.py │ │ └── models │ │ │ └── __init__.py │ ├── tests │ │ ├── validation │ │ │ ├── flows │ │ │ │ ├── empty.yml │ │ │ │ ├── alternative-wrong.yml │ │ │ │ ├── alternative-ok.yml │ │ │ │ ├── single-annotation.yml │ │ │ │ ├── any-direction-none.yml │ │ │ │ ├── mac-single.yml │ │ │ │ ├── fixed-direction-biflow-ok.yml │ │ │ │ ├── fixed-direction-ok.yml │ │ │ │ ├── any-direction-single.yml │ │ │ │ ├── fixed-direction-wrong.yml │ │ │ │ ├── subfields-missing.yml │ │ │ │ ├── subfields-one-wrong.yml │ │ │ │ ├── subfields-one-ok.yml │ │ │ │ ├── basic-biflow-reverse-ok.yml │ │ │ │ ├── custom-key-wrong.yml │ │ │ │ ├── subfields-wrong.yml │ │ │ │ ├── any-direction-both.yml │ │ │ │ ├── subfields-ok.yml │ │ │ │ ├── custom-key-ok.yml │ │ │ │ ├── basic-wrong-unsupported.yml │ │ │ │ └── subfields-unexpected.yml │ │ │ └── references │ │ │ │ ├── single-annotation.yml │ │ │ │ ├── mac.yml │ │ │ │ ├── alternative.yml │ │ │ │ ├── any-direction.yml │ │ │ │ ├── fixed-direction.yml │ │ │ │ └── basic.yml │ │ ├── statistical │ │ │ ├── flows │ │ │ │ ├── malformed.csv │ │ │ │ ├── relative_time.csv │ │ │ │ ├── long_flows_missing.csv │ │ │ │ └── long_flows_split.csv │ │ │ └── references │ │ │ │ ├── long_flows.csv │ │ │ │ └── relative_time.csv │ │ ├── replicator │ │ │ ├── ref │ │ │ │ ├── merge_across_simple.csv │ │ │ │ ├── ipv6.csv │ │ │ │ ├── merge_across_timeout.csv │ │ │ │ ├── merge_across_headache.csv │ │ │ │ ├── merge.csv │ │ │ │ ├── basic_ignore_loop.csv │ │ │ │ └── basic_time_0.8.csv │ │ │ └── source │ │ │ │ ├── merge_across_simple.csv │ │ │ │ ├── merge_across_timeout.csv │ │ │ │ ├── ipv6.csv │ │ │ │ ├── merge_across_headache.csv │ │ │ │ └── basic.csv │ │ └── precise │ │ │ ├── references │ │ │ ├── ip_version_compare.csv │ │ │ ├── biflows_split.csv │ │ │ ├── split.csv │ │ │ └── small.csv │ │ │ └── flows │ │ │ ├── ip_version_compare.csv │ │ │ ├── small_missing.csv │ │ │ ├── biflows_split.csv │ │ │ ├── small_incorrect.csv │ │ │ ├── timestamps.csv │ │ │ ├── small_unexpected.csv │ │ │ └── split.csv │ ├── pyproject.toml │ └── setup.py ├── ft-profiler │ ├── src │ │ ├── ftprofiler │ │ │ ├── __init__.py │ │ │ └── readers │ │ │ │ └── __init__.py │ │ └── ftprofiler.py │ ├── doc │ │ └── architecture.png │ ├── pyproject.toml │ └── tests │ │ └── ftprofiler │ │ └── integration │ │ └── data │ │ └── csv_basic_profile.csv ├── ft-replay │ ├── CMakeLists.txt │ └── src │ │ ├── protocol │ │ ├── ipFragmentType.hpp │ │ ├── icmp6.hpp │ │ ├── vlan.hpp │ │ ├── ipv6HopByHop.hpp │ │ ├── ipv6DestOptions.hpp │ │ ├── ipv6Routing.hpp │ │ └── udp.hpp │ │ ├── dissector │ │ ├── linkType.hpp │ │ ├── payloadType.hpp │ │ ├── etherType.hpp │ │ └── protocolType.hpp │ │ ├── outputQueue.cpp │ │ ├── CStringArray │ │ ├── cStringArray.cpp │ │ └── cStringArray.hpp │ │ ├── timeDuration.cpp │ │ ├── outputPluginFactoryRegistrator.hpp │ │ ├── nfbReplicatorCore.cpp │ │ └── replicator-core │ │ └── ipAddress.hpp ├── ft-generator │ ├── CMakeLists.txt │ ├── tests │ │ ├── ftgeneratortests │ │ │ ├── __init__.py │ │ │ ├── README.md │ │ │ ├── profiles │ │ │ │ └── profiles_all.csv │ │ │ └── src │ │ │ │ ├── constants.py │ │ │ │ └── __init__.py │ │ └── pytest.ini │ └── src │ │ ├── packet.cpp │ │ ├── generators │ │ ├── multirangegenerator.cpp │ │ ├── ipv4addressgenerator.cpp │ │ ├── ipv6addressgenerator.cpp │ │ ├── ipv4addressgenerator.h │ │ ├── ipv6addressgenerator.h │ │ ├── macaddressgenerator.h │ │ └── prefixedgenerator.cpp │ │ ├── data │ │ ├── words.h │ │ └── tlskeys.h │ │ ├── pcppethlayer.cpp │ │ ├── utils.cpp │ │ ├── tests │ │ ├── main.cpp │ │ └── domainnamegenerator.cpp │ │ ├── pcppethlayer.h │ │ ├── layers │ │ ├── payload.h │ │ ├── http.h │ │ └── icmprandom.h │ │ ├── config │ │ ├── tlsencryption.cpp │ │ └── timestamps.cpp │ │ ├── calendar.cpp │ │ └── domainnamegenerator.h ├── ft-profile-sampler │ ├── CMakeLists.txt │ └── src │ │ └── CMakeLists.txt ├── CMakeLists.txt ├── ft-profile-trimmer │ ├── src │ │ ├── fttrimmer │ │ │ └── __init__.py │ │ └── fttrimmer.py │ └── pyproject.toml └── common │ ├── external │ ├── CMakeLists.txt │ ├── spdlog.cmake │ ├── doctest.cmake │ └── yaml-cpp.cmake │ ├── src │ ├── timestamp.cpp │ ├── handlers.cpp │ └── logger.cpp │ ├── CMakeLists.txt │ └── include │ ├── logger.h │ ├── handlers.h │ └── converters.h ├── .mailmap ├── ansible ├── roles │ ├── probe_flowmon_driver │ │ ├── defaults │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── hugepages │ │ ├── meta │ │ │ └── main.yaml │ │ ├── defaults │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── nfb_kernel_module │ │ ├── meta │ │ │ └── main.yaml │ │ ├── files │ │ │ └── nfb.conf │ │ └── defaults │ │ │ └── main.yaml │ ├── probe_ipfixprobe │ │ ├── meta │ │ │ └── main.yaml │ │ ├── defaults │ │ │ └── main.yaml │ │ ├── vars │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── collector_ipfixcol │ │ ├── meta │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── nfb_tsu │ │ ├── meta │ │ │ └── main.yaml │ │ ├── files │ │ │ └── flowtest-nfb-tsu@.service │ │ ├── defaults │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── cpp_dependencies │ │ └── meta │ │ │ └── main.yaml │ ├── cpp_development │ │ ├── meta │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── dpdk_tools │ │ └── tasks │ │ │ └── main.yaml │ ├── nfb_framework │ │ ├── meta │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── orchestration_dependencies │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_epel │ │ └── tasks │ │ │ └── main.yaml │ ├── python_upgrade │ │ ├── defaults │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── flowtest_tools │ │ ├── meta │ │ │ └── main.yaml │ │ └── tasks │ │ │ └── main.yaml │ ├── ndk_fw_nic │ │ ├── meta │ │ │ └── main.yaml │ │ ├── vars │ │ │ └── main.yaml │ │ └── defaults │ │ │ └── main.yaml │ ├── common_tools │ │ └── tasks │ │ │ └── main.yaml │ ├── ndk_fw_replicator │ │ ├── meta │ │ │ └── main.yaml │ │ ├── vars │ │ │ └── main.yaml │ │ └── defaults │ │ │ └── main.yaml │ ├── python_tools │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_nemea │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_ipfixcol │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_nfb │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_flowtest │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_ndk │ │ └── tasks │ │ │ └── main.yaml │ ├── repository_crb │ │ └── tasks │ │ │ └── main.yaml │ └── firewall │ │ └── defaults │ │ └── main.yaml ├── flowtest_tools.yaml ├── flowmon_dpdk.yaml ├── flowmon_rawnetcap.yaml ├── flowtest_tools_nfb.yaml ├── ipfixprobe.yaml ├── dev_machine_nfb.yaml ├── ipfixprobe_dpdk.yaml ├── ipfixprobe_ndp.yaml ├── ipfixcol2.yaml ├── ci_controller.yaml ├── python_machine.yaml ├── dev_machine.yaml └── ci_docker.yaml ├── pcap ├── gre.pcap ├── dns_a.pcap ├── dns_mx.pcap ├── icmp.pcap ├── ovpn.pcap ├── ssl-v2.pcap ├── tls10.pcap ├── tls11.pcap ├── tls12.pcap ├── tls13.pcap ├── vxlan.pcap ├── dns_aaaa.pcap ├── dns_soa.pcap ├── dns_srv.pcap ├── dns_tcp.pcap ├── http_400.pcap ├── http_401.pcap ├── http_404.pcap ├── http_500.pcap ├── http_get.pcap ├── http_put.pcap ├── ipv6-esp.pcap ├── dns_cname.pcap ├── dns_refused.pcap ├── http_delete.pcap ├── http_post.pcap ├── ipv6-mobile.pcap ├── ipv6-smtp.pcap ├── tls12_alpn.pcap ├── tls13_0rtt.pcap ├── tls_ssl30.pcap ├── dns_nx_domain.pcap ├── http2_switch.pcap ├── ipv6-dst-opts.pcap ├── wg_udp_stream.pcap ├── 802.1Q_tunneling.pcap ├── dns_zone_change.pcap ├── ipv6-auth-header.pcap ├── ipv6-hop-by-hop.pcap ├── tls_cipher_error.pcap ├── tls_invalid_cert.pcap ├── ICMP_across_dot1q.pcap ├── dns_server_failure.pcap ├── tls_malformed_cert.pcap ├── tls_version_error.pcap ├── http_crlf_in_header.pcap ├── http_invalid_method.pcap ├── ipv4-udp-fragmented.pcap ├── ipv6-routing-header.pcap ├── ipv6-udp-fragmented.pcap ├── ipv6-neighbor-discovery.pcap └── mpls-vpn-transport-vpn-labels.pcap ├── .gitignore ├── cmake ├── modules │ └── try_run │ │ └── pcap_version.c └── build_type.cmake ├── pkg ├── CMakeLists.txt └── tgz │ └── CMakeLists.txt ├── testing └── validation │ ├── udp.yml │ ├── ipv6_esp.yml │ ├── ipv6_auth_header.yml │ ├── ipv6_mobile.yml │ ├── ipv4.yml │ ├── vlan.yml │ ├── gre.yml │ ├── ipv6.yml │ ├── vlan_qinq.yml │ ├── mac.yml │ ├── ipv4_fragmented.yml │ ├── ipv6_routing_header.yml │ ├── ipv6_fragmented.yml │ ├── mpls_single.yml │ ├── http_400.yml │ ├── mpls_double.yml │ ├── ipv6_hop_by_hop.yml │ ├── tcp.yml │ ├── icmp.yml │ ├── vxlan.yml │ ├── ipv6_dst_opts.yml │ ├── tls_version_error.yml │ ├── tls_cipher_error.yml │ ├── tls13.yml │ ├── http_crlf_in_header.yml │ ├── http_401.yml │ ├── tls_malformed_cert.yml │ ├── tls_invalid_cert.yml │ ├── http2_switch.yml │ ├── http_put.yml │ ├── http_post.yml │ ├── http_delete.yml │ ├── dns_refused.yml │ ├── http_get.yml │ ├── dns_nx_domain.yml │ ├── dns_server_failure.yml │ ├── http_invalid_method.yml │ ├── http_404.yml │ ├── tls_ssl30.yml │ ├── tls_ssl20.yml │ ├── tls11.yml │ ├── tls10.yml │ ├── icmpv6.yml │ ├── ovpn.yml │ ├── tls12.yml │ ├── http_500.yml │ ├── dns_zone_change.yml │ └── dns_cname.yml ├── .editorconfig ├── docker └── Dockerfile.gitlab-ci ├── .gitlab-ci.yml ├── conftest.py ├── Pipfile ├── pyproject.toml ├── .clang-format ├── .clang-tidy └── ci ├── test.gitlab-ci.yaml ├── upload.gitlab-ci.yaml └── prepare.gitlab-ci.yaml /tools/ft-fast-analyzer/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/collector/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/generator/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/probe/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/topology/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-profiler/src/ftprofiler/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/probe/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/collector/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/ft-replay/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(src) 2 | -------------------------------------------------------------------------------- /tools/ft-generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(src) 2 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/input/dummy.pcap: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Lukas Hutak 2 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/empty.yml: -------------------------------------------------------------------------------- 1 | flows: [] 2 | -------------------------------------------------------------------------------- /tools/ft-profile-sampler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(src) 2 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tox.ini: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | -------------------------------------------------------------------------------- /ansible/roles/probe_flowmon_driver/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: dpdk 3 | -------------------------------------------------------------------------------- /pcap/gre.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/gre.pcap -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/flows/malformed.csv: -------------------------------------------------------------------------------- 1 | oish gosdasj isdos 2 | -------------------------------------------------------------------------------- /tools/ft-generator/tests/ftgeneratortests/__init__.py: -------------------------------------------------------------------------------- 1 | # Python module file 2 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem: -------------------------------------------------------------------------------- 1 | test file 2 | -------------------------------------------------------------------------------- /pcap/dns_a.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_a.pcap -------------------------------------------------------------------------------- /pcap/dns_mx.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_mx.pcap -------------------------------------------------------------------------------- /pcap/icmp.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/icmp.pcap -------------------------------------------------------------------------------- /pcap/ovpn.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ovpn.pcap -------------------------------------------------------------------------------- /pcap/ssl-v2.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ssl-v2.pcap -------------------------------------------------------------------------------- /pcap/tls10.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls10.pcap -------------------------------------------------------------------------------- /pcap/tls11.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls11.pcap -------------------------------------------------------------------------------- /pcap/tls12.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls12.pcap -------------------------------------------------------------------------------- /pcap/tls13.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls13.pcap -------------------------------------------------------------------------------- /pcap/vxlan.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/vxlan.pcap -------------------------------------------------------------------------------- /pcap/dns_aaaa.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_aaaa.pcap -------------------------------------------------------------------------------- /pcap/dns_soa.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_soa.pcap -------------------------------------------------------------------------------- /pcap/dns_srv.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_srv.pcap -------------------------------------------------------------------------------- /pcap/dns_tcp.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_tcp.pcap -------------------------------------------------------------------------------- /pcap/http_400.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_400.pcap -------------------------------------------------------------------------------- /pcap/http_401.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_401.pcap -------------------------------------------------------------------------------- /pcap/http_404.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_404.pcap -------------------------------------------------------------------------------- /pcap/http_500.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_500.pcap -------------------------------------------------------------------------------- /pcap/http_get.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_get.pcap -------------------------------------------------------------------------------- /pcap/http_put.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_put.pcap -------------------------------------------------------------------------------- /pcap/ipv6-esp.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-esp.pcap -------------------------------------------------------------------------------- /ansible/roles/hugepages/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: dpdk_tools 4 | -------------------------------------------------------------------------------- /pcap/dns_cname.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_cname.pcap -------------------------------------------------------------------------------- /pcap/dns_refused.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_refused.pcap -------------------------------------------------------------------------------- /pcap/http_delete.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_delete.pcap -------------------------------------------------------------------------------- /pcap/http_post.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_post.pcap -------------------------------------------------------------------------------- /pcap/ipv6-mobile.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-mobile.pcap -------------------------------------------------------------------------------- /pcap/ipv6-smtp.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-smtp.pcap -------------------------------------------------------------------------------- /pcap/tls12_alpn.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls12_alpn.pcap -------------------------------------------------------------------------------- /pcap/tls13_0rtt.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls13_0rtt.pcap -------------------------------------------------------------------------------- /pcap/tls_ssl30.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls_ssl30.pcap -------------------------------------------------------------------------------- /tools/ft-generator/tests/ftgeneratortests/README.md: -------------------------------------------------------------------------------- 1 | ## ft generator tests 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /pcap/dns_nx_domain.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_nx_domain.pcap -------------------------------------------------------------------------------- /pcap/http2_switch.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http2_switch.pcap -------------------------------------------------------------------------------- /pcap/ipv6-dst-opts.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-dst-opts.pcap -------------------------------------------------------------------------------- /pcap/wg_udp_stream.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/wg_udp_stream.pcap -------------------------------------------------------------------------------- /ansible/roles/hugepages/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | hugepages_type: 2M 3 | hugepages_total_size: 2G 4 | -------------------------------------------------------------------------------- /ansible/roles/nfb_kernel_module/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: nfb_framework 4 | -------------------------------------------------------------------------------- /ansible/roles/probe_ipfixprobe/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_nemea 4 | -------------------------------------------------------------------------------- /pcap/802.1Q_tunneling.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/802.1Q_tunneling.pcap -------------------------------------------------------------------------------- /pcap/dns_zone_change.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_zone_change.pcap -------------------------------------------------------------------------------- /pcap/ipv6-auth-header.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-auth-header.pcap -------------------------------------------------------------------------------- /pcap/ipv6-hop-by-hop.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-hop-by-hop.pcap -------------------------------------------------------------------------------- /pcap/tls_cipher_error.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls_cipher_error.pcap -------------------------------------------------------------------------------- /pcap/tls_invalid_cert.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls_invalid_cert.pcap -------------------------------------------------------------------------------- /ansible/roles/collector_ipfixcol/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_ipfixcol 4 | -------------------------------------------------------------------------------- /pcap/ICMP_across_dot1q.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ICMP_across_dot1q.pcap -------------------------------------------------------------------------------- /pcap/dns_server_failure.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/dns_server_failure.pcap -------------------------------------------------------------------------------- /pcap/tls_malformed_cert.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls_malformed_cert.pcap -------------------------------------------------------------------------------- /pcap/tls_version_error.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/tls_version_error.pcap -------------------------------------------------------------------------------- /pcap/http_crlf_in_header.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_crlf_in_header.pcap -------------------------------------------------------------------------------- /pcap/http_invalid_method.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/http_invalid_method.pcap -------------------------------------------------------------------------------- /pcap/ipv4-udp-fragmented.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv4-udp-fragmented.pcap -------------------------------------------------------------------------------- /pcap/ipv6-routing-header.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-routing-header.pcap -------------------------------------------------------------------------------- /pcap/ipv6-udp-fragmented.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-udp-fragmented.pcap -------------------------------------------------------------------------------- /pcap/ipv6-neighbor-discovery.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/ipv6-neighbor-discovery.pcap -------------------------------------------------------------------------------- /ansible/roles/nfb_tsu/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_nfb 4 | - role: nfb_kernel_module 5 | -------------------------------------------------------------------------------- /tools/ft-profiler/doc/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-profiler/doc/architecture.png -------------------------------------------------------------------------------- /ansible/roles/cpp_dependencies/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_crb 4 | - role: repository_epel 5 | -------------------------------------------------------------------------------- /ansible/roles/cpp_development/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_epel 4 | - role: repository_crb 5 | -------------------------------------------------------------------------------- /pcap/mpls-vpn-transport-vpn-labels.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/pcap/mpls-vpn-transport-vpn-labels.pcap -------------------------------------------------------------------------------- /ansible/roles/probe_ipfixprobe/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Name of ipfixprobe package to install 3 | ipfixprobe_package: ipfixprobe 4 | -------------------------------------------------------------------------------- /ansible/flowtest_tools.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - flowtest_tools 7 | -------------------------------------------------------------------------------- /tools/ft-analyzer/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel>=0.34"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /tools/ft-profiler/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel>=0.34"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /ansible/flowmon_dpdk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Flowmon DPDK Probe 3 | hosts: all 4 | roles: 5 | - role: probe_flowmon_driver 6 | driver: dpdk 7 | -------------------------------------------------------------------------------- /ansible/roles/dpdk_tools/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: dpdk-tools is installed 3 | ansible.builtin.dnf: 4 | name: dpdk-tools 5 | state: latest 6 | -------------------------------------------------------------------------------- /ansible/roles/nfb_framework/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_nfb 4 | - role: repository_epel 5 | - role: repository_crb 6 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/collectors-invalid-1.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfixcol-1 2 | name: cesnet-collector-1.liberouter.org 3 | type2: Ipfixcol2 4 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/NTP_sync.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/generator/NTP_sync.pcap -------------------------------------------------------------------------------- /ansible/roles/collector_ipfixcol/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ipfixcol2 is installed 3 | ansible.builtin.dnf: 4 | name: ipfixcol2 5 | state: latest 6 | -------------------------------------------------------------------------------- /ansible/roles/nfb_framework/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: NFB framework is installed 3 | ansible.builtin.dnf: 4 | name: nfb-framework 5 | state: latest 6 | -------------------------------------------------------------------------------- /ansible/roles/orchestration_dependencies/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: rsync is installed 3 | ansible.builtin.dnf: 4 | name: rsync 5 | state: latest 6 | -------------------------------------------------------------------------------- /ansible/flowmon_rawnetcap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Flowmon Rawnetcap Probe 3 | hosts: all 4 | roles: 5 | - role: probe_flowmon_driver 6 | driver: rawnetcap 7 | -------------------------------------------------------------------------------- /ansible/roles/repository_epel/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: EPEL repository is installed 3 | ansible.builtin.dnf: 4 | name: epel-release 5 | state: latest 6 | -------------------------------------------------------------------------------- /ansible/flowtest_tools_nfb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - flowtest_tools 7 | - ndk_fw_replicator 8 | -------------------------------------------------------------------------------- /ansible/roles/python_upgrade/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: "{{ version_major }}.{{ version_minor }}" 3 | version_major: 3 4 | version_minor: 9 5 | set_as_default: true 6 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/collector/files/http_get.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/collector/files/http_get.pcap -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/ipv6-routing-header.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/generator/ipv6-routing-header.pcap -------------------------------------------------------------------------------- /ansible/ipfixprobe.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - role: probe_ipfixprobe 7 | ipfixprobe_package: ipfixprobe 8 | -------------------------------------------------------------------------------- /ansible/roles/flowtest_tools/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_crb 4 | - role: repository_epel 5 | - role: repository_nfb 6 | - role: repository_flowtest 7 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(common) 2 | add_subdirectory(ft-replay) 3 | add_subdirectory(ft-generator) 4 | add_subdirectory(ft-profile-sampler) 5 | add_subdirectory(ft-fast-analyzer) 6 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/merge_across_simple.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 0,28,17,192.168.128.124,81.2.248.189,60426,123,16,1216 3 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/source/merge_across_simple.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 0,7,17,192.168.128.124,81.2.248.189,60426,123,4,304 3 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes-invalid-1.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-vlan.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-vlan.pcap -------------------------------------------------------------------------------- /ansible/roles/probe_ipfixprobe/vars/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # List of ipfixprobe packages that are in collision 3 | ipfixprobe_package_list: 4 | - ipfixprobe 5 | - ipfixprobe-dpdk 6 | - ipfixprobe-ndp 7 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/collector/files/ipv6-neighbor-discovery.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/collector/files/ipv6-neighbor-discovery.pcap -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/collectors-invalid-2.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfixcol-1 2 | name: cesnet-collector-1.liberouter.org 3 | type: Ipfixcol2 4 | authentication: cesnet-general-invalid 5 | -------------------------------------------------------------------------------- /tools/ft-profile-trimmer/src/fttrimmer/__init__.py: -------------------------------------------------------------------------------- 1 | """Module for trimming network profiles from ft-profiler tool.""" 2 | 3 | from .fttrimmer import ProfileTrimmer, ProfileTrimmerException, PTStatistics 4 | -------------------------------------------------------------------------------- /ansible/dev_machine_nfb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Include dev_machine playbook 3 | ansible.builtin.import_playbook: dev_machine.yaml 4 | 5 | - hosts: all 6 | become: yes 7 | roles: 8 | - nfb_framework 9 | -------------------------------------------------------------------------------- /tools/ft-generator/tests/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | log_cli = true 3 | addopts = -s 4 | 5 | pythonpath = 6 | "." 7 | "../../ft-orchestration" 8 | 9 | testpaths = 10 | ftgeneratortests/tests 11 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-dst-mac.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-dst-mac.pcap -------------------------------------------------------------------------------- /ansible/ipfixprobe_dpdk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - hugepages 7 | - role: probe_ipfixprobe 8 | ipfixprobe_package: ipfixprobe-dpdk 9 | -------------------------------------------------------------------------------- /ansible/ipfixprobe_ndp.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - ndk_fw_nic 7 | - role: probe_ipfixprobe 8 | ipfixprobe_package: ipfixprobe-ndp 9 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-dst-mac-vlan.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CESNET/FlowTest/HEAD/tools/ft-orchestration/tests/dev/generator/ref/ipv6-routing-header-dst-mac-vlan.pcap -------------------------------------------------------------------------------- /ansible/ipfixcol2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - orchestration_dependencies 6 | - collector_ipfixcol 7 | - firewall 8 | vars: 9 | - firewall_ports: 10 | - [4739, tcp] 11 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/replicator/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Jan Sobol 3 | 4 | Copyright: (C) 2023 CESNET, z.s.p.o. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .flow_replicator import FlowReplicator 9 | -------------------------------------------------------------------------------- /ansible/ci_controller.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - role: python_upgrade 6 | when: ansible_distribution_major_version | int == 8 7 | - common_tools 8 | - python_tools 9 | - flowtest_tools 10 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_nic/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_ndk 4 | - role: nfb_kernel_module 5 | - role: nfb_tsu 6 | # Make sure nfb-tsu daemon is not running as we need to reboot firmware 7 | nfb_tsu_enable: false 8 | -------------------------------------------------------------------------------- /tools/common/external/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | include(ExternalProject) 3 | 4 | set(FETCHCONTENT_QUIET OFF) 5 | 6 | include(spdlog.cmake) 7 | include(pcapplusplus.cmake) 8 | include(yaml-cpp.cmake) 9 | include(doctest.cmake) 10 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/source/merge_across_timeout.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 2000,7000,17,192.168.128.124,81.2.248.189,60426,123,4,304 3 | 0,35000,17,10.0.0.1,10.0.0.2,50421,321,4,304 4 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/generators-invalid-2.yml: -------------------------------------------------------------------------------- 1 | - alias: hw-gen-100G 2 | name: cesnet-generator-1.liberouter.org 3 | type: Replicator 4 | interfaces: 5 | name: eth4 6 | speed: 100 7 | authentication: cesnet-general 8 | -------------------------------------------------------------------------------- /ansible/roles/common_tools/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Sudo is installed 3 | ansible.builtin.dnf: 4 | name: sudo 5 | state: latest 6 | 7 | - name: Git is installed 8 | ansible.builtin.dnf: 9 | name: git 10 | state: latest 11 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/normalizer/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .normalizer import Normalizer 9 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/references/ip_version_compare.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 24,24,6,13.68.218.189,134.162.109.94,49822,443,1,40 3 | 25,95001,6,13.68.218.189,134.162.109.95,49822,443,8,574 4 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/validation/conf/authentication.yml: -------------------------------------------------------------------------------- 1 | # Example of authentication methods 2 | 3 | - name: cesnet-general 4 | key-path: /home/user/cesnet-general.pem 5 | 6 | - name: flowmon-probes 7 | username: flowmon 8 | password: manyStars 9 | -------------------------------------------------------------------------------- /ansible/roles/nfb_kernel_module/files/nfb.conf: -------------------------------------------------------------------------------- 1 | # This file has been generated by Ansible and it is part of 2 | # FlowTest role called "nfb_kernel_module". 3 | 4 | {% for key, value in nfb_options.items() %} 5 | options nfb {{ key }}={{ value }} 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/generators-invalid-1.yml: -------------------------------------------------------------------------------- 1 | - alias: sw-gen-10G 2 | name: cesnet-generator-1.liberouter.org 3 | type: TcpReplay 4 | interfaces: 5 | authentication: cesnet-general 6 | ansible-playbook-role: generator-software 7 | -------------------------------------------------------------------------------- /ansible/python_machine.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - role: python_upgrade 6 | when: ansible_distribution_major_version | int == 8 7 | - common_tools 8 | - orchestration_dependencies 9 | - python_tools 10 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_replicator/meta/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - role: repository_flowtest 4 | - role: nfb_kernel_module 5 | - role: nfb_tsu 6 | # Make sure nfb-tsu daemon is not running as we need to reboot firmware 7 | nfb_tsu_enable: false 8 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/references/biflows_split.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 84080,383790,6,207.102.73.43,103.179.36.149,61674,443,40,2249 3 | 84080,383790,6,103.179.36.149,207.102.73.43,443,61674,21,2776 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Default build directory 2 | build/ 3 | 4 | # Visual Studio files 5 | .vscode/ 6 | 7 | # JetBrains files 8 | .idea/ 9 | 10 | # Compiled Python Files 11 | *.pyc 12 | 13 | # Clangd cache files 14 | .clang/ 15 | 16 | # Python virtual enviroment 17 | venv/ 18 | -------------------------------------------------------------------------------- /ansible/dev_machine.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: yes 4 | roles: 5 | - role: python_upgrade 6 | when: ansible_distribution_major_version | int == 8 7 | - common_tools 8 | - cpp_dependencies 9 | - cpp_development 10 | - python_tools 11 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/fields/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .field_database import FieldDatabase, FieldDirection 9 | -------------------------------------------------------------------------------- /cmake/modules/try_run/pcap_version.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | const char* ver_str = pcap_lib_version(); 6 | if (!ver_str) { 7 | return 1; 8 | } 9 | 10 | printf("%s", ver_str); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /ansible/roles/flowtest_tools/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: FlowTest tools are installed 3 | ansible.builtin.dnf: 4 | name: flowtest 5 | state: latest 6 | 7 | - name: tcpreplay is installed 8 | ansible.builtin.dnf: 9 | name: tcpreplay 10 | state: latest 11 | -------------------------------------------------------------------------------- /tools/common/src/timestamp.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief A wrapper around timeval 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "timestamp.h" 10 | 11 | namespace ft { 12 | 13 | } // namespace ft 14 | -------------------------------------------------------------------------------- /pkg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (NOT RELEASE) 2 | string(TIMESTAMP RELEASE "%Y%m%d%H%M%S") 3 | endif() 4 | 5 | set(TGZ_FILE "${CMAKE_CURRENT_BINARY_DIR}/flowtest-${VERSION}-${RELEASE}.tar.gz") 6 | 7 | add_subdirectory(tgz) 8 | 9 | if (ENABLE_RPMBUILD) 10 | add_subdirectory(rpm) 11 | endif() 12 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/ip_version_compare.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1692691223236,1692691223236,6,13.68.218.189,134.162.109.94,49822,443,1,40 3 | 1692691224863,1692691224863,58,fe80::e29:efff:fee4:5a00,ff02::1,0,32768,1,104 4 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/ipv6.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312160780,1678312166780,17,8000::1,2001:dba:3333:4444:5555:6666:7777:8888,60426,123,4,304 3 | 1678312160780,1678312166780,17,4000::1234:5678,2001:dba::1234:5678,60426,123,4,304 4 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/source/ipv6.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312160780,1678312166780,17,4000::1,2001:db8:3333:4444:5555:6666:7777:8888,60426,123,4,304 3 | 1678312160780,1678312166780,17,::1234:5678,2001:db8::1234:5678,60426,123,4,304 4 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/source/merge_across_headache.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 0,40000,17,10.0.0.1,81.2.248.189,60426,321,4,304 3 | 20000,40000,17,10.0.0.2,81.2.248.189,60426,321,5,305 4 | 0,30000,17,10.0.0.3,81.2.248.189,60426,321,6,306 5 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes-invalid-2.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | - name: eth3 8 | speed: 10 9 | authentication: cesnet-general-invalid 10 | -------------------------------------------------------------------------------- /pkg/tgz/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Git REQUIRED) 2 | 3 | add_custom_target(tgz 4 | COMMENT "Generating tar.gz package..." 5 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" 6 | COMMAND 7 | "${GIT_EXECUTABLE}" "archive" 8 | "--prefix=flowtest-${VERSION}/" 9 | "--output=${TGZ_FILE}" 10 | "HEAD" 11 | ) 12 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/authentication-invalid-2.yml: -------------------------------------------------------------------------------- 1 | - name: invalid2 2 | username: slowmon 3 | 4 | - name: cesnet-general 5 | key-path: tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem 6 | 7 | - name: flowmon-probes 8 | username: slowmon 9 | password: manyStars 10 | -------------------------------------------------------------------------------- /ansible/ci_docker.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | become: yes 5 | roles: 6 | - role: python_upgrade 7 | when: ansible_distribution_major_version | int == 8 8 | - common_tools 9 | - cpp_dependencies 10 | - cpp_development 11 | - python_tools 12 | - nfb_framework 13 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/alternative-wrong.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.0.113" 3 | dst_ip: "209.31.22.39" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 931 7 | packets: 6 8 | src_port: 3541 9 | dst_port: 80 10 | http_content_type: "image/png" 11 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/authentication.yml: -------------------------------------------------------------------------------- 1 | - name: cesnet-general 2 | key-path: tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem 3 | 4 | - name: flowmon-probes 5 | username: slowmon 6 | password: manyStars 7 | 8 | - name: cesnet-agent 9 | username: xcesne00 10 | ssh_agent: true 11 | -------------------------------------------------------------------------------- /tools/ft-generator/src/packet.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @author Michal Sedlak 5 | * @brief Packet interface 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #include "packet.h" 11 | 12 | namespace generator { 13 | 14 | } // namespace generator 15 | -------------------------------------------------------------------------------- /ansible/roles/hugepages/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Unmount hugepages 3 | ansible.builtin.command: "{{ item }}" 4 | with_items: 5 | - 'dpdk-hugepages.py --unmount' 6 | 7 | - name: Allocate hugepages ({{ hugepages_total_size }}) 8 | ansible.builtin.command: dpdk-hugepages.py -p {{ hugepages_type }} --setup {{ hugepages_total_size }} 9 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/alternative-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.0.113" 3 | dst_ip: "209.31.22.39" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 931 7 | packets: 6 8 | src_port: 3541 9 | dst_port: 80 10 | http_content_type: "text/html;charset=UTF-8" 11 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/multirangegenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief LFSR generator implementation 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "multirangegenerator.h" 10 | 11 | namespace generator { 12 | 13 | } // namespace generator 14 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/authentication-invalid-3.yml: -------------------------------------------------------------------------------- 1 | - name: invalid3 2 | password: manyStars 3 | ssh_agent: true 4 | 5 | - name: cesnet-general 6 | key-path: tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem 7 | 8 | - name: flowmon-probes 9 | username: slowmon 10 | password: manyStars 11 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/small_missing.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312182316,1678312188315,17,10.100.40.140,37.185.104.44,42088,123,4,304 3 | 1678312182317,1678312188316,17,10.100.40.140,37.186.104.44,42088,123,4,304 4 | 1678312192320,1678312198319,17,10.100.40.140,37.189.104.44,42088,123,6,708 5 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/source/basic.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312160780,1678312166780,17,192.168.128.124,81.2.248.189,60426,123,4,304 3 | 1678312157497,1678312163497,17,192.168.128.50,147.251.48.140,38626,123,4,304 4 | 1678312161962,1678312167962,17,192.168.4.225,147.251.48.140,35133,123,4,304 5 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/single-annotation.yml: -------------------------------------------------------------------------------- 1 | key: [src_ip, dst_ip, protocol] 2 | 3 | flows: 4 | - src_ip: "fe80::21e:7aff:fe79:3f10" 5 | dst_ip: "ff02::5" 6 | ip_version: 6 7 | protocol: 89 8 | bytes: 108 9 | packets: 1 10 | tos: 0xe0 11 | ttl: 1 12 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/biflows_split.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1700571636717,1700571926180,6,207.102.73.43,103.179.36.149,61674,443,39,2209 3 | 1700571636717,1700571926180,6,103.179.36.149,207.102.73.43,443,61674,21,2776 4 | 1700571936427,1700571936427,6,207.102.73.43,103.179.36.149,61674,443,1,40 5 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/single-annotation.yml: -------------------------------------------------------------------------------- 1 | key: [src_ip, dst_ip, protocol] 2 | 3 | flows: 4 | - src_ip: "fe80::21e:7aff:fe79:3f10" 5 | dst_ip: "ff02::5" 6 | ip_version: 6 7 | protocol: 89 8 | bytes: 108 9 | packets: 1 10 | tos: 0xe0 11 | ttl: 1 12 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/collectors.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfixcol-1 2 | name: cesnet-collector-1.liberouter.org 3 | type: Ipfixcol2 4 | authentication: cesnet-general 5 | 6 | - alias: flowsen-1 7 | name: cesnet-collector-1.liberouter.org 8 | type: Flowsen 9 | authentication: flowmon-probes 10 | ansible-playbook-role: collector-flowsen 11 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes-invalid-3.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | mac: 00:00:00:00:00:00 8 | - name: eth3 9 | speed: 10 10 | authentication: cesnet-general 11 | protocols: [ http, tls, dns, trill ] 12 | -------------------------------------------------------------------------------- /ansible/roles/nfb_tsu/files/flowtest-nfb-tsu@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=NFB TimeStamp Unit service for %f (started by FlowTest) 3 | Wants=network.target network-online.target 4 | After=network.target network-online.target 5 | 6 | [Service] 7 | Type=forking 8 | ExecStart=/usr/bin/nfb-tsu -d %f 9 | Restart=on-failure 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/flow/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .flow import FieldsDict, Flow 9 | from .validation_flow import ValidationFlow 10 | from .validation_result import ValidationField, ValidationResult, ValidationStats 11 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/reports/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .precise_report import PreciseReport 9 | from .statistical_report import StatisticalReport 10 | from .validation_report import ValidationReport, ValidationReportSummary 11 | -------------------------------------------------------------------------------- /tools/ft-generator/src/data/words.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Word list 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace generator { 15 | 16 | extern const std::vector WORDS; 17 | 18 | } // namespace generator 19 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes-invalid-4.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | mac: "" 8 | - name: eth3 9 | speed: 10 10 | mac: 00:00:00:00:00:00 11 | authentication: cesnet-general 12 | protocols: [ http, tls, dns, trill ] 13 | -------------------------------------------------------------------------------- /tools/ft-profile-sampler/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(ft-profile-sampler 2 | biflow.cpp 3 | common.hpp 4 | evolution.cpp 5 | main.cpp 6 | metrics.cpp 7 | profile.cpp 8 | ) 9 | 10 | target_compile_options(ft-profile-sampler PUBLIC -pthread) 11 | target_link_libraries(ft-profile-sampler PRIVATE pthread common) 12 | install(TARGETS ft-profile-sampler DESTINATION ${INSTALL_DIR_BIN}) 13 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/mac.yml: -------------------------------------------------------------------------------- 1 | key: [src_ip, dst_ip, protocol] 2 | 3 | flows: 4 | - src_ip: "192.168.56.101" 5 | dst_ip: "192.168.56.102" 6 | ip_version: 4 7 | protocol: 6 8 | bytes: 751 9 | bytes@rev: 1900 10 | packets: 6 11 | packets@rev: 4 12 | src_mac: "08:00:27:D8:CA:49" 13 | dst_mac: "08:00:27:36:24:D6" 14 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/validation/conf/collectors.yml: -------------------------------------------------------------------------------- 1 | # Collector config example file 2 | 3 | - alias: ipfixcol-1 4 | name: cesnet-collector-1.liberouter.org 5 | type: Ipfixcol2 6 | authentication: cesnet-general 7 | 8 | - alias: flowsen-1 9 | name: cesnet-collector-1.liberouter.org 10 | type: Flowsen 11 | authentication: flowmon-probes 12 | ansible-playbook-role: collector-flowsen 13 | -------------------------------------------------------------------------------- /tools/ft-generator/src/pcppethlayer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief A wrapper class around pcpp::EthLayer 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "pcppethlayer.h" 10 | 11 | namespace generator { 12 | 13 | void PcppEthLayer::computeCalculateFields() 14 | { 15 | // do nothing 16 | } 17 | 18 | } // namespace generator 19 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/authentication-invalid-1.yml: -------------------------------------------------------------------------------- 1 | - name: cesnet-general 2 | key-path: tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem 3 | 4 | - name: flowmon-probes 5 | username: slowmon 6 | password: manyStars 7 | 8 | - name: invalid1 9 | username: slowmon 10 | password: manyStars 11 | key-path: tools/ft-orchestration/tests/dev/config/files/cesnet-general.pem 12 | -------------------------------------------------------------------------------- /tools/ft-profiler/src/ftprofiler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author(s): Tomas Jansky 6 | 7 | Copyright: (C) 2022 Flowmon Networks a.s. 8 | SPDX-License-Identifier: BSD-3-Clause 9 | 10 | Script entry-point. 11 | """ 12 | 13 | import sys 14 | 15 | if __name__ == "__main__": 16 | from ftprofiler.core import main 17 | 18 | sys.exit(main()) 19 | -------------------------------------------------------------------------------- /testing/validation/udp.yml: -------------------------------------------------------------------------------- 1 | name: UDP Traffic 2 | description: Check that UDP header is properly parsed. 3 | marks: [udp] 4 | pcap: dns_mx.pcap 5 | probe: 6 | protocols: [] 7 | 8 | flows: 9 | - src_ip: 192.168.170.8 10 | dst_ip: 192.168.170.20 11 | ip_version: 4 12 | protocol: 17 13 | bytes: 56 14 | bytes@rev: 284 15 | packets: 1 16 | packets@rev: 1 17 | src_port: 32795 18 | dst_port: 53 19 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/merge_across_timeout.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 0,140000,17,10.0.0.1,10.0.0.2,50421,321,16,1216 3 | 2000,7000,17,192.168.128.124,81.2.248.189,60426,123,4,304 4 | 37000,42000,17,192.168.128.124,81.2.248.189,60426,123,4,304 5 | 72000,77000,17,192.168.128.124,81.2.248.189,60426,123,4,304 6 | 107000,112000,17,192.168.128.124,81.2.248.189,60426,123,4,304 7 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/references/long_flows.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1653637200311,1653638040871,17,192.168.187.28,212.24.128.196,5060,5060,15,6973 3 | 1653637200339,1653638092007,17,212.24.128.196,192.168.187.28,5060,5060,75,7228 4 | 1653637200281,1653638111095,1,5.180.196.2,5.180.196.6,0,0,1800,55020 5 | 1653637200281,1653638111095,1,5.180.196.6,5.180.196.2,0,0,1800,55020 6 | -------------------------------------------------------------------------------- /tools/ft-profile-trimmer/src/fttrimmer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author(s): Vaclav Seidler 6 | 7 | Copyright: (C) 2023 Flowmon Networks a.s. 8 | SPDX-License-Identifier: BSD-3-Clause 9 | 10 | Script entry-point. 11 | """ 12 | 13 | import sys 14 | 15 | if __name__ == "__main__": 16 | from fttrimmer.fttrimmer import main 17 | 18 | sys.exit(main()) 19 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/alternative.yml: -------------------------------------------------------------------------------- 1 | test: 2 | name: HTTP Error 500 3 | pcaps: ["http_500.pcap"] 4 | required_protocols: ["http"] 5 | 6 | flows: 7 | - src_ip: "192.168.0.113" 8 | dst_ip: "209.31.22.39" 9 | ip_version: 4 10 | protocol: 6 11 | bytes: 931 12 | packets: 6 13 | src_port: 3541 14 | dst_port: 80 15 | http_content_type: ["text/html", "text/html;charset=UTF-8"] 16 | -------------------------------------------------------------------------------- /ansible/roles/python_tools/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Python3 is installed 3 | ansible.builtin.dnf: 4 | name: 5 | - python3 6 | - python3-pip 7 | state: latest 8 | 9 | - name: Pipx is installed (over pip) 10 | ansible.builtin.command: pip3 install pipx 11 | 12 | # Pipx may not be in PATH, run with python3 -m 13 | - name: Python pipenv is installed (over pipx, globally) 14 | ansible.builtin.command: python3 -m pipx install pipenv --global 15 | -------------------------------------------------------------------------------- /cmake/build_type.cmake: -------------------------------------------------------------------------------- 1 | # Define default build type and supported options. 2 | set(DEFAULT_BUILD_TYPE "Release") 3 | 4 | if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 5 | message(STATUS 6 | "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.") 7 | set(CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} 8 | CACHE STRING "build type" FORCE) 9 | set_property(CACHE CMAKE_BUILD_TYPE 10 | PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") 11 | endif() 12 | -------------------------------------------------------------------------------- /testing/validation/ipv6_esp.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 with ESP 2 | description: Check that probes identify ESP header correctly after IPv6 header. 3 | marks: [ipv6] 4 | pcap: ipv6-esp.pcap 5 | probe: 6 | protocols: [ipv6] 7 | key: [src_ip, dst_ip, protocol] 8 | 9 | flows: 10 | - src_ip: 2001:470:e5bf:1001:8519:2d1f:c57d:fc4f 11 | dst_ip: 2001:470:e5bf:dead:7db0:921:a2e9:1c21 12 | ip_version: 6 13 | protocol: 50 14 | bytes: 48 15 | packets: 1 16 | tos: 0x00 17 | ttl: 63 18 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/references/split.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 43744,123155,58,75dc:b024:c91a:9cac:e1f3:6816:fee0:df5e,baee:5812:648d:4e56:70f9:b40b:7f70:6faf,0,0,4,288 3 | 23385,321801,6,158.251.62.121,61.246.124.243,443,56259,18,2368 4 | 21259,323294,6,61.246.124.243,158.251.62.121,56259,443,33,2193 5 | 14221,320979,17,132.37.167.45,66.18.211.150,35145,443,492,325734 6 | 14221,320979,17,132.37.168.46,66.18.212.151,32358,443,492,325734 7 | -------------------------------------------------------------------------------- /testing/validation/ipv6_auth_header.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Option Authentication Header 2 | description: Check that packets with IPv6 header option Authentication Header are 3 | parsed properly. 4 | marks: [ipv6] 5 | pcap: ipv6-auth-header.pcap 6 | probe: 7 | protocols: [ipv6] 8 | key: [src_ip, dst_ip, protocol] 9 | 10 | flows: 11 | - src_ip: fe80::21e:7aff:fe79:3f10 12 | dst_ip: ff02::5 13 | ip_version: 6 14 | protocol: 89 15 | bytes: 108 16 | packets: 1 17 | tos: 0xe0 18 | ttl: 1 19 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/references/small.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312182316,1678312188315,17,10.100.40.140,37.185.104.44,42088,123,4,304 3 | 1678312182317,1678312188316,17,10.100.40.140,37.186.104.44,42088,123,4,304 4 | 1678312192318,1678312198317,17,10.100.40.140,37.187.104.44,42088,123,6,708 5 | 1678312182319,1678312188318,17,10.100.40.140,37.188.104.44,42088,123,4,304 6 | 1678312192320,1678312198319,17,10.100.40.140,37.189.104.44,42088,123,6,708 7 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/small_incorrect.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312182316,1678312188315,17,10.100.40.140,37.185.104.44,42088,123,4,304 3 | 1678312182317,1678312188316,17,10.100.40.140,37.186.104.44,42088,123,4,305 4 | 1678312192318,1678312198317,17,10.100.40.140,37.187.104.44,42088,123,7,708 5 | 1678312182319,1678312188318,17,10.100.40.140,37.188.104.44,42088,123,3,303 6 | 1678312192320,1678312198319,17,10.100.40.140,37.189.104.44,42088,123,12,100 7 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/timestamps.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312182366,1678312188275,17,10.100.40.140,37.185.104.44,42088,123,4,304 3 | 1678312182467,1678312188316,17,10.100.40.140,37.186.104.44,42088,123,4,304 4 | 1678312192318,1678312199467,17,10.100.40.140,37.187.104.44,42088,123,6,708 5 | 1678312183069,1678312188318,17,10.100.40.140,37.188.104.44,42088,123,4,304 6 | 1678312197320,1678312193319,17,10.100.40.140,37.189.104.44,42088,123,6,708 7 | 8 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_replicator/vars/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Dictionary of supported firmwares based on the card name. 3 | # Each entry contains design name. 4 | # Design name is without "ndp-fw-" prefix and ".nfw" suffix 5 | ndk_nic_firmwares: 6 | N6010: # card name 7 | design: n6010-replicator-100g2 8 | NFB-200G2QL: 9 | design: nfb-200g2ql-replicator-100g2 10 | AGI-FH400G-REV1: 11 | design: agi-fh400g-replicator-400g1_rev1_gen5 12 | AGI-FH400G-REV0: 13 | design: agi-fh400g-replicator-400g1_rev0 14 | -------------------------------------------------------------------------------- /testing/validation/ipv6_mobile.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Option Mobile IPv6 2 | description: Check that packets with IPv6 header option Mobile IPv6 are parsed properly. 3 | marks: [ipv6] 4 | pcap: ipv6-mobile.pcap 5 | probe: 6 | protocols: [ipv6] 7 | key: [src_ip, dst_ip, protocol] 8 | 9 | flows: 10 | - src_ip: 6ea1:86f8:169:115f:76a0:c016:3074:6f95 11 | dst_ip: 2d8e:be9b:c3f:83bd:32a1:b5dd:aac6:353e 12 | ip_version: 6 13 | protocol: 59 14 | bytes: 72 15 | packets: 1 16 | tos: 0x88 17 | ttl: 150 18 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/merge_across_headache.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 0,40000,17,10.0.0.1,81.2.248.189,60426,321,4,304 3 | 20000,80000,17,10.0.0.2,81.2.248.189,60426,321,9,609 4 | 0,30000,17,10.0.0.3,81.2.248.189,60426,321,6,306 5 | 60000,120000,17,10.0.0.3,81.2.248.189,60426,321,9,609 6 | 40000,70000,17,10.0.0.4,81.2.248.189,60426,321,6,306 7 | 100000,120000,17,10.0.0.4,81.2.248.189,60426,321,5,305 8 | 80000,110000,17,10.0.0.5,81.2.248.189,60426,321,6,306 9 | -------------------------------------------------------------------------------- /testing/validation/ipv4.yml: -------------------------------------------------------------------------------- 1 | name: IPv4 Traffic 2 | description: Check that regular IPv4 header is parsed properly. 3 | marks: [ipv4] 4 | pcap: tls12.pcap 5 | probe: 6 | protocols: [ipv4] 7 | 8 | flows: 9 | - src_ip: 10.100.50.48 10 | dst_ip: 10.100.50.139 11 | ip_version: 4 12 | protocol: 6 13 | bytes: 3218 14 | bytes@rev: 3798 15 | packets: 15 16 | packets@rev: 11 17 | src_port: 46588 18 | dst_port: 7001 19 | tos: 0x00 20 | tos@rev: 0x00 21 | ttl: 64 22 | ttl@rev: 64 23 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/any-direction-none.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.1.140" 3 | dst_ip: "174.143.213.184" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 1234 7 | packets: 21 8 | src_port: 57678 9 | dst_port: 80 10 | - src_ip: "174.143.213.184" 11 | dst_ip: "192.168.1.140" 12 | ip_version: 4 13 | protocol: 6 14 | bytes: 23041 15 | packets: 19 16 | src_port: 80 17 | dst_port: 57678 18 | -------------------------------------------------------------------------------- /tools/ft-analyzer/ftanalyzer/models/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | from .precise_model import PreciseModel 9 | from .sm_data_types import ( 10 | SMException, 11 | SMMetric, 12 | SMMetricType, 13 | SMRule, 14 | SMSubnetSegment, 15 | SMTimeSegment, 16 | ) 17 | from .statistical_model import StatisticalModel 18 | from .validation_model import ValidationModel 19 | -------------------------------------------------------------------------------- /testing/validation/vlan.yml: -------------------------------------------------------------------------------- 1 | name: VLAN Single 2 | description: Check that VLAN header is correctly parsed and skipped. 3 | requirements: 4 | protocols: [vlan] 5 | marks: [vlan] 6 | pcap: ICMP_across_dot1q.pcap 7 | probe: 8 | protocols: [vlan] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [vlan_id] 11 | 12 | flows: 13 | - src_ip: 192.168.123.2 14 | dst_ip: 192.168.123.1 15 | ip_version: 4 16 | protocol: 1 17 | bytes: 500 18 | bytes@rev: 400 19 | packets: 5 20 | packets@rev: 4 21 | vlan_id: 123 22 | -------------------------------------------------------------------------------- /ansible/roles/nfb_tsu/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # FPGA card to configure 3 | # System path to the card. Usually contains "/dev/nfb/{by-pci-slot,by-serial-no}/". 4 | # For example: 5 | # "/dev/nfb0" # Specified by card index 6 | # "/dev/nfb/by-serial-no/NFB-200G2QL/86" # Specified by card type and serial number. 7 | # "/dev/nfb/by-pci-slot/0000:ca:00.0" # Specified by PCI endpoint 8 | nfb_card: "/dev/nfb0" 9 | 10 | # Determine whether nfb-tsu service should be running for the given card. 11 | nfb_tsu_enable: true 12 | -------------------------------------------------------------------------------- /tools/ft-orchestration/src/config/common.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Jakub Rimek 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | 7 | Common classes used by the orchestration configuration""" 8 | 9 | from dataclasses import dataclass 10 | from typing import Optional 11 | 12 | 13 | @dataclass 14 | class InterfaceCfg: 15 | """Network interface class, used by the GeneratorCfg and ProbeCfg classes""" 16 | 17 | name: str 18 | speed: int 19 | mac: Optional[str] = None 20 | -------------------------------------------------------------------------------- /testing/validation/gre.yml: -------------------------------------------------------------------------------- 1 | name: GRE Tunnel 2 | description: Parse GRE tunnel and check whether IP fields contain information from 3 | the inner IP header. 4 | requirements: 5 | protocols: [gre] 6 | marks: [gre] 7 | pcap: gre.pcap 8 | probe: 9 | protocols: [gre] 10 | key: [src_ip, dst_ip, protocol] 11 | 12 | flows: 13 | - src_ip: 1.1.1.1 14 | dst_ip: 2.2.2.2 15 | ip_version: 4 16 | protocol: 1 17 | bytes: 500 18 | bytes@rev: 500 19 | bytes_outer: 620 20 | bytes_outer@rev: 620 21 | packets: 5 22 | packets@rev: 5 23 | -------------------------------------------------------------------------------- /testing/validation/ipv6.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Traffic 2 | description: Check that regular IPv6 header is parsed properly. 3 | marks: [ipv6] 4 | pcap: ipv6-smtp.pcap 5 | probe: 6 | protocols: [ipv6] 7 | 8 | flows: 9 | - src_ip: 2001:470:e5bf:dead:4957:2174:e82c:4887 10 | dst_ip: 2607:f8b0:400c:c03::1a 11 | ip_version: 6 12 | protocol: 6 13 | bytes: 558 14 | bytes@rev: 736 15 | packets: 9 16 | packets@rev: 8 17 | src_port: 63943 18 | dst_port: 25 19 | tos: 0x00 20 | tos@rev: 0x00 21 | ttl: 64 22 | ttl@rev: 56 23 | -------------------------------------------------------------------------------- /tools/ft-generator/tests/ftgeneratortests/profiles/profiles_all.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,L3_PROTO,L4_PROTO,SRC_PORT,DST_PORT,PACKETS,BYTES,PACKETS_REV,BYTES_REV 2 | 0,28354,4,1,58428,1443,318,427066,100,134222 3 | 0,28354,4,1,58428,1443,318,427066,0,0 4 | 0,28354,4,6,58428,1443,318,427066,100,20000 5 | 0,28354,6,17,58428,1443,318,427066,100,20000 6 | 191855,191880,4,6,63172,81,4,454,3,403 7 | 191855,191880,6,6,63172,81,4,454,3,403 8 | 191855,191880,4,17,63172,81,4,454,3,403 9 | 191855,191880,6,17,63172,81,4,454,3,403 10 | 190838,211996,4,1,1443,44210,6,420,0,0 11 | -------------------------------------------------------------------------------- /ansible/roles/repository_nemea/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Nemea repository is installed 3 | ansible.builtin.yum_repository: 4 | name: copr:copr.fedorainfracloud.org:group_CESNET:NEMEA 5 | description: Copr repo for NEMEA owned by @CESNET 6 | baseurl: "{{ url }}/epel-{{ ansible_distribution_major_version }}-$basearch/" 7 | skip_if_unavailable: yes 8 | gpgcheck: yes 9 | gpgkey: "{{ url }}/pubkey.gpg" 10 | repo_gpgcheck: no 11 | enabled: yes 12 | vars: 13 | url: https://download.copr.fedorainfracloud.org/results/@CESNET/NEMEA 14 | -------------------------------------------------------------------------------- /ansible/roles/probe_ipfixprobe/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get list of installed packages 3 | ansible.builtin.package_facts: 4 | manager: auto 5 | 6 | - name: Remove ipfixprobe packages that are in collision 7 | ansible.builtin.dnf: 8 | name: "{{ item }}" 9 | state: absent 10 | with_items: "{{ ipfixprobe_package_list | difference([ipfixprobe_package]) }}" 11 | when: "item in ansible_facts.packages" 12 | 13 | - name: "{{ ipfixprobe_package }} is installed" 14 | ansible.builtin.dnf: 15 | name: "{{ ipfixprobe_package }}" 16 | state: latest 17 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/mac-single.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.56.101" 3 | dst_ip: "192.168.56.102" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 751 7 | packets: 6 8 | src_mac: "08:00:27:D8:CA:49" 9 | dst_mac: "08:00:27:36:24:D6" 10 | - src_ip: "192.168.56.102" 11 | dst_ip: "192.168.56.101" 12 | ip_version: 4 13 | protocol: 6 14 | bytes: 1900 15 | packets: 4 16 | src_mac: "08:00:27:36:24:D6" 17 | dst_mac: "08:00:27:D8:CA:49" 18 | 19 | -------------------------------------------------------------------------------- /ansible/roles/repository_ipfixcol/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: IPFIXcol repository is installed 3 | ansible.builtin.yum_repository: 4 | name: copr:copr.fedorainfracloud.org:group_CESNET:IPFIXcol 5 | description: Copr repo for IPFIXcol owned by @CESNET 6 | baseurl: "{{ url }}/epel-{{ ansible_distribution_major_version }}-$basearch/" 7 | skip_if_unavailable: yes 8 | gpgcheck: yes 9 | gpgkey: "{{ url }}/pubkey.gpg" 10 | repo_gpgcheck: no 11 | enabled: yes 12 | vars: 13 | url: https://download.copr.fedorainfracloud.org/results/@CESNET/IPFIXcol 14 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/fixed-direction-biflow-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.236.146" 3 | dst_ip: "192.168.93.24" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 67 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 60643 11 | dst_port: 53 12 | dns_id: 313 13 | dns_flags: 0x0100 14 | dns_req_query_type: 1 15 | dns_req_query_class: 1 16 | dns_req_query_name: "ia-dns.net" 17 | dns_flags@rev: 0x8182 18 | dns_resp_rcode: 2 19 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/generators.yml: -------------------------------------------------------------------------------- 1 | - alias: sw-gen-10G 2 | name: cesnet-generator-1.liberouter.org 3 | type: TcpReplay 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | - name: eth3 8 | speed: 10 9 | authentication: cesnet-general 10 | ansible-playbook-role: generator-software 11 | 12 | 13 | - alias: hw-gen-100G 14 | name: cesnet-generator-1.liberouter.org 15 | type: Replicator 16 | interfaces: 17 | - name: eth4 18 | speed: 100 19 | - name: eth5 20 | speed: 100 21 | authentication: cesnet-general 22 | -------------------------------------------------------------------------------- /testing/validation/vlan_qinq.yml: -------------------------------------------------------------------------------- 1 | name: VLAN QinQ 2 | description: Check that both VLAN headers are correctly parsed and skipped. 3 | requirements: 4 | protocols: [vlan] 5 | marks: [vlan] 6 | pcap: 802.1Q_tunneling.pcap 7 | probe: 8 | protocols: [vlan] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [vlan_id, vlan_id_inner] 11 | 12 | flows: 13 | - src_ip: 10.118.10.1 14 | dst_ip: 10.118.10.2 15 | ip_version: 4 16 | protocol: 1 17 | bytes: 500 18 | bytes@rev: 500 19 | packets: 5 20 | packets@rev: 5 21 | vlan_id: 118 22 | vlan_id_inner: 10 23 | -------------------------------------------------------------------------------- /testing/validation/mac.yml: -------------------------------------------------------------------------------- 1 | name: MAC Addresses 2 | description: Check that MAC addresses are correctly parsed. 3 | requirements: 4 | protocols: [eth] 5 | marks: [eth] 6 | pcap: tls12.pcap 7 | probe: 8 | protocols: [eth] 9 | at_least_one: [src_mac, dst_mac] 10 | 11 | flows: 12 | - src_ip: 10.100.50.48 13 | dst_ip: 10.100.50.139 14 | ip_version: 4 15 | protocol: 6 16 | bytes: 3218 17 | bytes@rev: 3798 18 | packets: 15 19 | packets@rev: 11 20 | src_port: 46588 21 | dst_port: 7001 22 | src_mac: 00:50:56:bf:fb:74 23 | dst_mac: 00:50:56:bf:c3:9e 24 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/merge.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312160780,1678312166780,17,192.168.128.124,81.2.248.189,60426,123,8,608 3 | 1678312157497,1678312163497,17,192.168.128.50,147.251.48.140,38626,123,8,608 4 | 1678312161962,1678312167962,17,192.168.4.225,147.251.48.140,35133,123,8,608 5 | 1678312171245,1678312177245,17,192.168.128.124,81.2.248.189,60426,123,8,608 6 | 1678312167962,1678312173962,17,192.168.128.50,147.251.48.140,38626,123,8,608 7 | 1678312172427,1678312178427,17,192.168.4.225,147.251.48.140,35133,123,8,608 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | 9 | [*.py] 10 | indent_style = space 11 | indent_size = 4 12 | 13 | [*.sh] 14 | indent_style = tab 15 | indent_size = 4 16 | 17 | [Makefile] 18 | indent_style = tab 19 | 20 | [*.{yaml,yml}] 21 | indent_style = space 22 | indent_size = 2 23 | 24 | [{CMakeLists.txt,*.cmake}] 25 | indent_style = tab 26 | 27 | [*.{pcap,pcapng}] 28 | end_of_line = unset 29 | insert_final_newline = unset 30 | trim_trailing_whitespace = unset 31 | charset = unset 32 | -------------------------------------------------------------------------------- /ansible/roles/repository_nfb/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: nfb-framework repository is installed 3 | ansible.builtin.yum_repository: 4 | name: copr:copr.fedorainfracloud.org:group_CESNET:nfb-framework 5 | description: Copr repo for nfb-framework owned by @CESNET 6 | baseurl: "{{ url }}/epel-{{ ansible_distribution_major_version }}-$basearch/" 7 | skip_if_unavailable: yes 8 | gpgcheck: yes 9 | gpgkey: "{{ url }}/pubkey.gpg" 10 | repo_gpgcheck: no 11 | enabled: yes 12 | vars: 13 | url: https://download.copr.fedorainfracloud.org/results/@CESNET/nfb-framework 14 | -------------------------------------------------------------------------------- /testing/validation/ipv4_fragmented.yml: -------------------------------------------------------------------------------- 1 | name: IPv4 Traffic Fragmented 2 | description: Check that fragmented IPv4 packets are not split into multiple separate 3 | flows. 4 | marks: [ipv4] 5 | pcap: ipv4-udp-fragmented.pcap 6 | probe: 7 | protocols: [ipv4] 8 | 9 | flows: 10 | - src_ip: 131.179.196.46 11 | dst_ip: 131.179.196.220 12 | ip_version: 4 13 | protocol: 17 14 | bytes: 504 15 | bytes@rev: 5467 16 | packets: 4 17 | packets@rev: 4 18 | src_port: 6363 19 | dst_port: 6363 20 | tos: 0x00 21 | tos@rev: 0x00 22 | ttl: 64 23 | ttl@rev: 64 24 | -------------------------------------------------------------------------------- /testing/validation/ipv6_routing_header.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Option Routing Header 2 | description: Check that packets with IPv6 header option Routing Header are parsed 3 | properly. 4 | marks: [ipv6] 5 | pcap: ipv6-routing-header.pcap 6 | probe: 7 | protocols: [ipv6] 8 | 9 | flows: 10 | - src_ip: fc00:2:0:2::1 11 | dst_ip: fc00:2:0:1::1 12 | ip_version: 6 13 | protocol: 6 14 | bytes: 533 15 | bytes@rev: 767 16 | packets: 6 17 | packets@rev: 4 18 | tos: 0x00 19 | tos@rev: 0x00 20 | ttl: 64 21 | ttl@rev: 63 22 | src_port: 43424 23 | dst_port: 8080 24 | -------------------------------------------------------------------------------- /tools/ft-fast-analyzer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(fast-analyzer STATIC 2 | src/ipaddr.cpp 3 | src/flow.cpp 4 | src/flowtable.cpp 5 | src/statisticalmodel.cpp 6 | ) 7 | 8 | # To use ft-analyzer library (statically linked) in shared libraries (e.g. in python module ft-fast-analyzer) 9 | # is needed to set position-independent code on. 10 | set_property(TARGET fast-analyzer PROPERTY POSITION_INDEPENDENT_CODE ON) 11 | 12 | target_include_directories(fast-analyzer PUBLIC src) 13 | 14 | target_link_libraries(fast-analyzer PUBLIC pthread) 15 | target_link_libraries(fast-analyzer PUBLIC common) 16 | -------------------------------------------------------------------------------- /docker/Dockerfile.gitlab-ci: -------------------------------------------------------------------------------- 1 | ARG OS_DISTRO=oraclelinux 2 | ARG OS_RELEASE=8 3 | 4 | FROM $OS_DISTRO:$OS_RELEASE as default 5 | 6 | COPY ansible /ansible 7 | 8 | RUN < 4 | * @brief General utility functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "utils.h" 10 | 11 | #include 12 | 13 | namespace generator { 14 | 15 | void SetBit(unsigned int position, bool bitValue, uint8_t* bytes) 16 | { 17 | unsigned int byteIdx = position / 8; 18 | unsigned int bitIdx = 7 - (position % 8); 19 | bytes[byteIdx] &= ~(uint8_t(1) << bitIdx); 20 | bytes[byteIdx] |= uint8_t(bitValue) << bitIdx; 21 | } 22 | 23 | } // namespace generator 24 | -------------------------------------------------------------------------------- /testing/validation/ipv6_fragmented.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Traffic Fragmented 2 | description: Check that fragmented IPv6 packets are not split into multiple separate 3 | flows. 4 | marks: [ipv6] 5 | pcap: ipv6-udp-fragmented.pcap 6 | probe: 7 | protocols: [ipv6] 8 | 9 | flows: 10 | - src_ip: 2607:f010:3f9::11:0 11 | dst_ip: 2607:f010:3f9::1001 12 | ip_version: 6 13 | protocol: 17 14 | bytes: 245 15 | bytes@rev: 5579 16 | packets: 2 17 | packets@rev: 4 18 | src_port: 6363 19 | dst_port: 6363 20 | tos: 0x00 21 | tos@rev: 0x00 22 | ttl: 64 23 | ttl@rev: 64 24 | -------------------------------------------------------------------------------- /testing/validation/mpls_single.yml: -------------------------------------------------------------------------------- 1 | name: MPLS (Single Label) 2 | description: Check that MPLS header is correctly parsed and skipped. 3 | requirements: 4 | protocols: [mpls] 5 | marks: [mpls] 6 | pcap: mpls-vpn-transport-vpn-labels.pcap 7 | probe: 8 | protocols: [mpls] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [mpls_label_1, mpls_label_1@rev] 11 | 12 | flows: 13 | - src_ip: 1.1.1.1 14 | dst_ip: 5.5.5.5 15 | ip_version: 4 16 | protocol: 1 17 | bytes: 500 18 | bytes@rev: 500 19 | packets: 5 20 | packets@rev: 5 21 | mpls_label_1: 272 22 | mpls_label_1@rev: 305 23 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/whitelists.yml: -------------------------------------------------------------------------------- 1 | - name: flowmon-whitelist 2 | items: 3 | validation: 4 | - test1.yml 5 | - test2.yml 6 | - test3.yml 7 | simulation: 8 | - test4.yml 9 | - test5.yml 10 | 11 | - name: flowmon-whitelist-via-switch 12 | include: flowmon-whitelist 13 | items: 14 | validation: 15 | - vlan.yml 16 | - mac.yml: "Mac addresses are changed when testing via switch." 17 | 18 | - name: inherited 19 | include: flowmon-whitelist-via-switch 20 | items: 21 | validation: 22 | - last_inherited.yml: "Because" 23 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_nic/vars/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Dictionary of firmwares based on the card name and number of PCIe endpoints. 3 | # Each entry contains design name and number of application cores to configure. 4 | # Design name is without "ndp-fw-" prefix and ".nfw" suffix 5 | ndk_nic_firmwares: 6 | N6010: # card name 7 | "1": # number of endpoints 8 | design: n6010-nic-pcie1xgen4x16-100g2 9 | cores: 2 10 | NFB-200G2QL: 11 | "1": 12 | design: nfb-200g2ql-nic-pcie1xgen3x16-100g2 13 | cores: 2 14 | "2": 15 | design: nfb-200g2ql-nic-pcie2xgen3x16-100g2 16 | cores: 2 17 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/ipFragmentType.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief IP Fragment type 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | namespace replay::protocol { 12 | 13 | /** 14 | * @brief Type of IPv4/IPv6 fragment. 15 | */ 16 | enum class IPFragmentType { 17 | None, /**< Not fragmented */ 18 | First, /**< Fragmented, the first fragment */ 19 | Middle, /**< Fragmented, neither the first nor the last fragment */ 20 | Last, /**< Fragmented, the last fragment */ 21 | }; 22 | 23 | } // namespace replay::protocol 24 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/whitelists-invalid-include.yml: -------------------------------------------------------------------------------- 1 | - name: flowmon-whitelist 2 | items: 3 | validation: 4 | - test1.yml 5 | - test2.yml 6 | - test3.yml 7 | simulation: 8 | - test4.yml 9 | - test5.yml 10 | 11 | - name: flowmon-whitelist-via-switch 12 | include: flowmon-whitelist 13 | items: 14 | validation: 15 | - vlan.yml 16 | - mac.yml: "Mac addresses are changed when testing via switch." 17 | 18 | - name: inherited 19 | include: not-existing-whitelist 20 | items: 21 | validation: 22 | - last_inherited.yml: "Because" 23 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/validation/conf/generators.yml: -------------------------------------------------------------------------------- 1 | # Generators config example file 2 | 3 | - alias: sw-gen-10G 4 | name: cesnet-generator-1.liberouter.org 5 | type: TcpReplay 6 | interfaces: 7 | - name: eth2 8 | speed: 10 9 | - name: eth3 10 | speed: 10 11 | authentication: cesnet-general 12 | ansible-playbook-role: generator-software 13 | 14 | - alias: hw-gen-100G 15 | name: cesnet-generator-1.liberouter.org 16 | type: Replicator 17 | interfaces: 18 | - name: eth4 19 | speed: 100 20 | - name: eth5 21 | speed: 100 22 | authentication: cesnet-general 23 | -------------------------------------------------------------------------------- /tools/ft-replay/src/dissector/linkType.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file 3 | * @brief Link type 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::dissector { 14 | 15 | /** 16 | * @brief Auxiliary link type specific for PCAP capture. 17 | * 18 | * The list contains only relevant layers of non-zero length. 19 | * @see https://www.tcpdump.org/linktypes.html 20 | */ 21 | enum class LinkType : uint8_t { 22 | Ethernet = 1, /**< Standard Ethernet layer */ 23 | }; 24 | 25 | } // namespace replay::dissector 26 | -------------------------------------------------------------------------------- /tools/ft-replay/src/outputQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @brief Output plugin implementation 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "outputQueue.hpp" 10 | 11 | namespace replay { 12 | 13 | void OutputQueueStats::UpdateTime() noexcept 14 | { 15 | timespec now; 16 | 17 | clock_gettime(CLOCK_MONOTONIC_COARSE, &now); 18 | transmitEndTime = now; 19 | 20 | if (!transmitStartTime.tv_sec && !transmitStartTime.tv_nsec) { 21 | transmitStartTime = now; 22 | } 23 | } 24 | 25 | void OutputQueue::Flush() {} 26 | 27 | } // namespace replay 28 | -------------------------------------------------------------------------------- /ansible/roles/cpp_development/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Make/CMake/rpmbuild is installed 3 | ansible.builtin.dnf: 4 | name: 5 | - cmake 6 | - make 7 | - rpm-build 8 | state: latest 9 | 10 | - name: GCC is installed 11 | ansible.builtin.dnf: 12 | name: 13 | - gcc 14 | - gcc-c++ 15 | state: latest 16 | 17 | - name: Clang is installed 18 | ansible.builtin.dnf: 19 | name: 20 | - clang 21 | state: latest 22 | 23 | - name: Static analysis tools are installed 24 | ansible.builtin.dnf: 25 | name: 26 | - cppcheck 27 | - clang-tools-extra 28 | state: latest 29 | -------------------------------------------------------------------------------- /tools/ft-generator/src/tests/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Main entry point for doctest test runner 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #define DOCTEST_CONFIG_IMPLEMENT 10 | 11 | #include "../randomgenerator.h" 12 | #include "logger.h" 13 | 14 | #include 15 | 16 | int main(int argc, char** argv) 17 | { 18 | ft::LoggerInit(); 19 | 20 | uint64_t seed = std::time(nullptr); 21 | generator::RandomGenerator::InitInstance(seed); 22 | 23 | doctest::Context context; 24 | context.applyCommandLine(argc, argv); 25 | return context.run(); 26 | } 27 | -------------------------------------------------------------------------------- /testing/validation/http_400.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Error 400 2 | description: Check that HTTP 400 error response code is parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_400.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_status_code, http_content_type] 10 | 11 | flows: 12 | - src_ip: 192.168.1.36 13 | dst_ip: 192.168.1.25 14 | ip_version: 4 15 | protocol: 6 16 | bytes: 518 17 | bytes@rev: 996 18 | packets: 7 19 | packets@rev: 5 20 | src_port: 55020 21 | dst_port: 8080 22 | http_status_code: 400 23 | http_content_type: [text/html, text/html;charset=utf-8] 24 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/whitelists-invalid-circular.yml: -------------------------------------------------------------------------------- 1 | - name: flowmon-whitelist 2 | include: inherited 3 | items: 4 | validation: 5 | - test1.yml 6 | - test2.yml 7 | - test3.yml 8 | simulation: 9 | - test4.yml 10 | - test5.yml 11 | 12 | - name: flowmon-whitelist-via-switch 13 | include: flowmon-whitelist 14 | items: 15 | validation: 16 | - vlan.yml 17 | - mac.yml: "Mac addresses are changed when testing via switch." 18 | 19 | - name: inherited 20 | include: flowmon-whitelist-via-switch 21 | items: 22 | validation: 23 | - last_inherited.yml: "Because" 24 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - prepare 3 | - check 4 | - build 5 | - test 6 | - upload 7 | 8 | default: 9 | image: $DOCKER_IMAGE:ol8 10 | tags: [$DOCKER_IMAGE_TAG] 11 | interruptible: true 12 | 13 | include: 14 | - local: 'ci/prepare.gitlab-ci.yaml' 15 | - local: 'ci/check.gitlab-ci.yaml' 16 | - local: 'ci/build.gitlab-ci.yaml' 17 | - local: 'ci/test.gitlab-ci.yaml' 18 | - local: 'ci/upload.gitlab-ci.yaml' 19 | 20 | variables: 21 | GIT_STRATEGY: clone 22 | DOCKER_SHELL_TAG: docker-ci-shell 23 | DOCKER_IMAGE_TAG: docker-ci-image 24 | DOCKER_IMAGE: $CI_PROJECT_PATH_SLUG/$CI_COMMIT_REF_SLUG 25 | FF_SCRIPT_SECTIONS: true 26 | -------------------------------------------------------------------------------- /tools/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(external) 2 | 3 | # Create a common "object" library 4 | set(COMMON_SRC 5 | src/logger.cpp 6 | src/handlers.cpp 7 | src/timestamp.cpp 8 | ) 9 | 10 | add_library(common OBJECT ${COMMON_SRC}) 11 | 12 | target_link_libraries(common 13 | PUBLIC 14 | spdlog::spdlog 15 | ) 16 | 17 | target_include_directories(common 18 | PUBLIC 19 | include 20 | spdlog::spdlog 21 | ) 22 | 23 | # To use common library (statically linked) in shared libraries (e.g. in python module ft-fast-analyzer) 24 | # is needed to set position-independent code on. 25 | set_property(TARGET common PROPERTY POSITION_INDEPENDENT_CODE ON) 26 | -------------------------------------------------------------------------------- /tools/ft-replay/src/dissector/payloadType.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file 3 | * @brief Payload type 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::dissector { 14 | 15 | /** 16 | * @brief Auxiliary identification of packet payload. 17 | */ 18 | enum class PayloadType : uint8_t { 19 | Unknown, /**< Unknown, unsupported or invalid payload */ 20 | IPFragment, /**< Non-first fragment of IPv4/IPv6 payload */ 21 | AppData, /**< Payload suitable for application protocol parsers */ 22 | }; 23 | 24 | } // namespace replay::dissector 25 | -------------------------------------------------------------------------------- /testing/validation/mpls_double.yml: -------------------------------------------------------------------------------- 1 | name: MPLS (Multiple Labels) 2 | description: Check that both MPLS headers are correctly parsed and skipped. 3 | requirements: 4 | protocols: [mpls] 5 | marks: [mpls] 6 | pcap: mpls-vpn-transport-vpn-labels.pcap 7 | probe: 8 | protocols: [mpls] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [mpls_label_1, mpls_label_1@rev, mpls_label_2] 11 | 12 | flows: 13 | - src_ip: 1.1.1.1 14 | dst_ip: 5.5.5.5 15 | ip_version: 4 16 | protocol: 1 17 | bytes: 500 18 | bytes@rev: 500 19 | packets: 5 20 | packets@rev: 5 21 | mpls_label_1: 272 22 | mpls_label_1@rev: 305 23 | mpls_label_2: 305 24 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Jan Sobol 3 | 4 | Copyright: (C) 2023 CESNET, z.s.p.o. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | 7 | Pytest conftest file. 8 | """ 9 | 10 | import os 11 | import sys 12 | 13 | sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "tools/ft-orchestration")) 14 | sys.setrecursionlimit(5000) 15 | 16 | # Include fixtures from components. Plugin registration must be defined in the top-level conftest. 17 | pytest_plugins = [ 18 | "src.common.fixtures", 19 | "src.common.html_report_plugin", 20 | "src.topology.common", 21 | "src.topology.pcap_player", 22 | "src.topology.replicator", 23 | ] 24 | -------------------------------------------------------------------------------- /tools/ft-generator/tests/ftgeneratortests/src/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Matej Hulák 3 | 4 | Copyright: (C) 2023 CESNET, z.s.p.o. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | 7 | File defines project constants. 8 | """ 9 | 10 | L3_PROTOCOL_IPV4 = 4 11 | L3_PROTOCOL_IPV6 = 6 12 | L4_PROTOCOL_TCP = 6 13 | L4_PROTOCOL_UDP = 17 14 | L4_PROTOCOL_ICMP = 1 15 | L4_PROTOCOL_ICMPV6 = 58 16 | L4_PROTOCOL_NONE = 0 17 | 18 | MAC_MASK_SIZE = 48 19 | MTU_SIZE = 1514 20 | 21 | ENCAPSULATION_ABS_TOLERANCE = 0.1 22 | FRAGMENTATION_ABS_TOLERANCE = 0.2 23 | REPORT_REL_TOLERANCE = 0.2 24 | TIMING_ABS_TOLERANCE = 100 # milliseconds 25 | 26 | GENERATOR_ERROR_RET_CODE = 1 27 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/small_unexpected.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312182316,1678312188315,17,10.100.40.140,37.185.104.44,42088,123,4,304 3 | 1678312182317,1678312188316,17,10.100.40.140,37.186.104.44,42088,123,4,304 4 | 1678312192318,1678312198317,17,10.100.40.140,37.187.104.44,42088,123,6,708 5 | 1678312192318,1678312198317,17,10.100.40.140,37.187.104.45,42088,123,6,708 6 | 1678312182319,1678312188318,17,10.100.40.140,37.188.104.44,42088,123,4,304 7 | 1678312192320,1678312198319,17,10.100.40.140,37.189.104.44,42088,123,6,708 8 | 1678312192320,1678312198319,17,10.100.40.140,37.189.104.45,42088,123,6,708 9 | 10 | -------------------------------------------------------------------------------- /testing/validation/ipv6_hop_by_hop.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Option Hop-by-Hop 2 | description: Check that packets with IPv6 header option Hop-by-Hop are parsed properly. 3 | requirements: 4 | protocols: [icmpv6] 5 | marks: [ipv6, icmpv6] 6 | pcap: ipv6-hop-by-hop.pcap 7 | probe: 8 | protocols: [ipv6, icmpv6] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [icmp_type, icmp_code, icmp_type_code] 11 | 12 | flows: 13 | - src_ip: fe80::a6cf:65f:272a:9453 14 | dst_ip: ff02::a129:5423:7adf:769b 15 | ip_version: 6 16 | protocol: 58 17 | bytes: 192 18 | packets: 2 19 | tos: 0x00 20 | ttl: 1 21 | icmp_type: 143 22 | icmp_code: 0 23 | icmp_type_code: 36608 24 | -------------------------------------------------------------------------------- /testing/validation/tcp.yml: -------------------------------------------------------------------------------- 1 | name: TCP Traffic 2 | description: Check that TCP Flags and TCP Options are properly parsed from TCP header. 3 | marks: [tcp] 4 | pcap: tls12.pcap 5 | probe: 6 | protocols: [tcp] 7 | at_least_one: [tcp_flags, tcp_flags@rev, tcp_options, tcp_options@rev, tcp_syn_size] 8 | 9 | flows: 10 | - src_ip: 10.100.50.48 11 | dst_ip: 10.100.50.139 12 | ip_version: 4 13 | protocol: 6 14 | bytes: 3218 15 | bytes@rev: 3798 16 | packets: 15 17 | packets@rev: 11 18 | src_port: 46588 19 | dst_port: 7001 20 | tcp_flags: 0x1f 21 | tcp_flags@rev: 0x1b 22 | tcp_options: 0x78 23 | tcp_options@rev: 0x7c 24 | tcp_syn_size: 52 25 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | ansible-core = "<2.17.0" 8 | cppcheck-junit = "*" 9 | fabric = "*" 10 | pyaml = "*" 11 | pyopenssl = "*" 12 | dataclass_wizard = "*" 13 | pandas = "<2.2" 14 | numpy = "*" 15 | pyarrow = "*" 16 | pytest = "<8.0" 17 | pytest-cases = "*" 18 | pytest-html = "==3.2.0" 19 | py = "*" 20 | lbr-testsuite = "<5.4" 21 | scapy = "*" 22 | matplotlib = "*" 23 | netaddr = "*" 24 | 25 | [dev-packages] 26 | pylint = "*" 27 | black = "*" 28 | build = "*" 29 | twine = "*" 30 | hypothesis = "*" 31 | docker = "*" 32 | isort = "*" 33 | packaging = "*" 34 | 35 | [requires] 36 | python_version = "3.9" 37 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/icmp6.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief ICMPv6 layer 4 | * @author Pavel Siska 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::protocol { 14 | 15 | /** 16 | * @brief ICMPv6 header. 17 | */ 18 | struct ICMPv6 { 19 | uint8_t _type; 20 | uint8_t _code; 21 | uint16_t _checksum; 22 | // ... data ... 23 | 24 | /** @brief Exact size of ICMPv6 header */ 25 | static constexpr uint16_t HEADER_SIZE = 4; 26 | 27 | } __attribute__((packed)); 28 | 29 | static_assert(sizeof(ICMPv6) == ICMPv6::HEADER_SIZE, "Unexpected header size"); 30 | 31 | } // namespace replay::protocol 32 | -------------------------------------------------------------------------------- /ansible/roles/nfb_kernel_module/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # NFB kernel module parameters 3 | # 4 | # Each key/value entry in this dictionary will be passed to the kernel 5 | # module during module loading. 6 | # See `lsmod nfb` for list of all possible options. 7 | nfb_options: 8 | # Size of buffer for one packet in NDP ring [bytes] 9 | # In other words, this parameter determines what is the maximum packet size 10 | # that can be transferred to the software and thus indirectly limits the MTU. 11 | ndp_ctrl_buffer_size: 16k 12 | # Size of each NDP ring [bytes] 13 | # Note: Each ring requires at least 1024 descriptors, so the value must be at 14 | # least >= 1024 * ndp_ctrl_buffer_size. 15 | ndp_ring_size: 16M 16 | -------------------------------------------------------------------------------- /ansible/roles/python_upgrade/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Python {{ version }} is installed 3 | ansible.builtin.dnf: 4 | name: 5 | - "{{ python }}" 6 | - "{{ python }}-pip" 7 | - "{{ python }}-setuptools" 8 | state: latest 9 | vars: 10 | python: "python{{ version_major }}{{ version_minor }}" 11 | when: 12 | - ansible_os_family == 'RedHat' 13 | 14 | - name: Set Python {{ version }} as default interpreter 15 | ansible.builtin.command: "alternatives --set {{ python }} {{ bin }}" 16 | vars: 17 | python: "python{{ version_major }}" 18 | bin: "/usr/bin/python{{ version_major }}.{{ version_minor }}" 19 | when: 20 | - ansible_os_family == 'RedHat' 21 | - set_as_default 22 | -------------------------------------------------------------------------------- /testing/validation/icmp.yml: -------------------------------------------------------------------------------- 1 | name: ICMPv4 Traffic 2 | description: Check that ICMPv4 is properly parsed. 3 | requirements: 4 | protocols: [icmp] 5 | marks: [icmp] 6 | pcap: icmp.pcap 7 | probe: 8 | protocols: [icmp] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [icmp_type, icmp_type@rev, icmp_code, icmp_code@rev, icmp_type_code, 11 | icmp_type_code@rev] 12 | 13 | flows: 14 | - src_ip: 192.168.158.139 15 | dst_ip: 174.137.42.77 16 | ip_version: 4 17 | protocol: 1 18 | bytes: 240 19 | bytes@rev: 240 20 | packets: 4 21 | packets@rev: 4 22 | icmp_type: 8 23 | icmp_type@rev: 0 24 | icmp_code: 0 25 | icmp_code@rev: 0 26 | icmp_type_code: 2048 27 | icmp_type_code@rev: 0 28 | -------------------------------------------------------------------------------- /testing/validation/vxlan.yml: -------------------------------------------------------------------------------- 1 | name: VXLAN Tunnel 2 | description: Parse VXLAN tunnel and check whether MAC resp. IP fields contain information 3 | from the inner ethernet resp. IP header. 4 | requirements: 5 | protocols: [eth, vxlan] 6 | marks: [eth, vxlan] 7 | pcap: vxlan.pcap 8 | probe: 9 | protocols: [eth, vxlan] 10 | key: [src_ip, dst_ip, protocol] 11 | at_least_one: [vxlan_id] 12 | 13 | flows: 14 | - src_ip: 10.0.0.1 15 | dst_ip: 10.0.0.2 16 | ip_version: 4 17 | protocol: 1 18 | bytes: 336 19 | bytes@rev: 336 20 | bytes_outer: 536 21 | bytes_outer@rev: 536 22 | packets: 4 23 | packets@rev: 4 24 | src_mac: ba:09:2b:6e:f8:be 25 | dst_mac: 4a:7f:01:3b:a2:71 26 | vxlan_id: 123 27 | -------------------------------------------------------------------------------- /testing/validation/ipv6_dst_opts.yml: -------------------------------------------------------------------------------- 1 | name: IPv6 Option Destination Options 2 | description: Check that packets with IPv6 header option Destination Options are parsed 3 | properly. 4 | requirements: 5 | protocols: [icmpv6] 6 | marks: [ipv6, icmpv6] 7 | pcap: ipv6-dst-opts.pcap 8 | probe: 9 | protocols: [ipv6, icmpv6] 10 | key: [src_ip, dst_ip, protocol] 11 | at_least_one: [icmp_type, icmp_code, icmp_type_code] 12 | 13 | flows: 14 | - src_ip: 6ea1:86f8:169:115f:76a0:c016:3074:6f95 15 | dst_ip: 2d8e:be9b:c3f:83bd:32a1:b5dd:aac6:353e 16 | ip_version: 6 17 | protocol: 58 18 | bytes: 288 19 | packets: 1 20 | tos: 0x88 21 | ttl: 150 22 | icmp_type: 128 23 | icmp_code: 0 24 | icmp_type_code: 32768 25 | -------------------------------------------------------------------------------- /testing/validation/tls_version_error.yml: -------------------------------------------------------------------------------- 1 | name: TLS Version Error 2 | description: Check that TLS communication resulting in a version error is properly 3 | parsed. 4 | requirements: 5 | protocols: [tls] 6 | marks: [tls] 7 | pcap: tls_version_error.pcap 8 | probe: 9 | protocols: [tls] 10 | at_least_one: [tls_server_version, tls_client_version, tls_ja3] 11 | 12 | flows: 13 | - src_ip: 192.168.1.29 14 | dst_ip: 192.168.1.25 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 535 18 | bytes@rev: 275 19 | packets: 6 20 | packets@rev: 5 21 | src_port: 44282 22 | dst_port: 8443 23 | tls_server_version: 0x0303 24 | tls_client_version: 0x0304 25 | tls_ja3: '0xea217b0edcd93778471552ba0b796f81' 26 | -------------------------------------------------------------------------------- /testing/validation/tls_cipher_error.yml: -------------------------------------------------------------------------------- 1 | name: TLS Cipher Error 2 | description: Check that TLS communication resulting in incompatible cipher suites 3 | is properly parsed. 4 | requirements: 5 | protocols: [tls] 6 | marks: [tls] 7 | pcap: tls_cipher_error.pcap 8 | probe: 9 | protocols: [tls] 10 | at_least_one: [tls_server_version, tls_client_version, tls_ja3] 11 | 12 | flows: 13 | - src_ip: 192.168.1.29 14 | dst_ip: 192.168.1.25 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 432 18 | bytes@rev: 275 19 | packets: 6 20 | packets@rev: 5 21 | src_port: 44328 22 | dst_port: 8443 23 | tls_server_version: 0x0303 24 | tls_client_version: 0x0303 25 | tls_ja3: '0x1d99b35397a2e20c43b933aa64e8356e' 26 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/any-direction.yml: -------------------------------------------------------------------------------- 1 | # Check that HTTP Get method is properly parsed from HTTP request 2 | test: 3 | name: HTTP Get Method 4 | pcaps: ["http_get.pcap"] 5 | 6 | flows: 7 | - src_ip: "192.168.1.140" 8 | dst_ip: "174.143.213.184" 9 | ip_version: 4 10 | protocol: 6 11 | bytes: 1234 12 | bytes@rev: 23041 13 | packets: 21 14 | packets@rev: 19 15 | src_port: 57678 16 | dst_port: 80 17 | http_host: "packetlife.net" 18 | http_url: "/images/layout/logo.png" 19 | http_method: "GET" 20 | http_status_code: 200 21 | http_agent: "Wget/1.12 (linux-gnu)" 22 | http_content_type: "image/png" 23 | 24 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/references/relative_time.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 3283,9283,17,192.168.128.124,81.2.248.189,60426,123,4,304 3 | 0,6000,17,192.168.128.50,147.251.48.140,38626,123,4,304 4 | 4465,10465,17,192.168.4.225,147.251.48.140,35133,123,4,304 5 | 4559,10558,17,192.168.51.36,37.187.104.44,41461,123,4,304 6 | 4769,10769,17,192.168.51.21,81.2.248.189,59749,123,4,304 7 | 5741,11741,17,192.168.50.66,162.159.200.1,59137,123,4,304 8 | 4778,4986,6,192.168.128.125,192.168.128.120,2210,34668,4,284 9 | 4778,4990,6,192.168.128.120,192.168.128.125,34668,2210,6,357 10 | 8708,8712,6,192.168.4.71,192.168.60.90,389,10366,3,150 11 | 3796,9797,17,192.168.4.225,81.2.248.189,35133,123,4,304 12 | -------------------------------------------------------------------------------- /testing/validation/tls13.yml: -------------------------------------------------------------------------------- 1 | name: TLS 1.3 Traffic 2 | description: Check that TLS 1.3 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls13.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_sni, tls_client_version, 10 | tls_ja3] 11 | 12 | flows: 13 | - src_ip: 172.16.1.117 14 | dst_ip: 172.16.1.130 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 745 18 | bytes@rev: 1903 19 | packets: 7 20 | packets@rev: 6 21 | src_port: 34152 22 | dst_port: 4433 23 | tls_server_version: 0x7f1c 24 | tls_cipher_suite: 0x1302 25 | tls_sni: dogfish 26 | tls_client_version: 0x7f1c 27 | tls_ja3: '0xa66e498c488aa0523759691248cdfb01' 28 | -------------------------------------------------------------------------------- /testing/validation/http_crlf_in_header.yml: -------------------------------------------------------------------------------- 1 | name: HTTP CR LF in Header 2 | description: Check that packets with CR LF in HTTP header are parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_crlf_in_header.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_method, http_method_id, http_url, http_status_code, http_content_type] 10 | 11 | flows: 12 | - src_ip: 192.168.1.36 13 | dst_ip: 192.168.1.25 14 | ip_version: 4 15 | protocol: 6 16 | bytes: 480 17 | bytes@rev: 405 18 | packets: 6 19 | packets@rev: 4 20 | src_port: 55028 21 | dst_port: 8080 22 | http_url: / 23 | http_method: GET 24 | http_method_id: 1 25 | http_status_code: 200 26 | http_content_type: text/html 27 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/ipv4addressgenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief IPv4 address generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "ipv4addressgenerator.h" 10 | 11 | namespace generator { 12 | 13 | IPv4AddressGenerator::IPv4AddressGenerator(IPv4Address netIp, uint8_t prefixLen) 14 | : _gen(PrefixedGenerator(std::vector(netIp.toBytes(), netIp.toBytes() + 4), prefixLen)) 15 | { 16 | if (prefixLen > 0 && !netIp.isValid()) { 17 | throw std::invalid_argument("invalid net address"); 18 | } 19 | } 20 | 21 | IPv4Address IPv4AddressGenerator::Generate() 22 | { 23 | return IPv4Address(_gen.Generate().data()); 24 | } 25 | 26 | } // namespace generator 27 | -------------------------------------------------------------------------------- /tools/ft-replay/src/dissector/etherType.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file 3 | * @brief Ethernet type 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::dissector { 14 | 15 | /** 16 | * @brief EtherType values. 17 | * @see https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml 18 | */ 19 | enum class EtherType : uint16_t { 20 | IPv4 = 0x0800, 21 | VLAN = 0x8100, /**< IEEE Std 802.1Q - Customer VLAN Tag Type (C-Tag) */ 22 | IPv6 = 0x86DD, 23 | MPLS = 0x8847, 24 | MPLSUpstream = 0x8848, 25 | VLANSTag = 0x88A8, /**< IEEE Std 802.1Q - Service VLAN tag identifier (S-Tag) */ 26 | }; 27 | 28 | } // namespace replay::dissector 29 | -------------------------------------------------------------------------------- /tools/common/external/spdlog.cmake: -------------------------------------------------------------------------------- 1 | # spdlog library (modern C++ logger) 2 | # 3 | # Since we don't want to depend on usually outdated system-provided 4 | # library, we use statically linked library. 5 | # 6 | # Following options must be used to override rpmbuild parameters that 7 | # are passed to the library when building. 8 | set(BUILD_SHARED_LIBS OFF) 9 | set(SPDLOG_BUILD_SHARED OFF) 10 | 11 | # To use logger (statically linked) in shared libraries (e.g. in python module ft-fast-analyzer) 12 | # is needed to set position-independent code on. 13 | set(SPDLOG_BUILD_PIC ON) 14 | 15 | FetchContent_Declare( 16 | spdlog 17 | GIT_REPOSITORY "https://github.com/gabime/spdlog.git" 18 | GIT_TAG "v1.15.1" 19 | GIT_SHALLOW 1 20 | ) 21 | 22 | FetchContent_MakeAvailable(spdlog) 23 | -------------------------------------------------------------------------------- /testing/validation/http_401.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Error 401 2 | description: Check that HTTP 401 error response code is parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_401.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method_id, http_url, http_method, http_status_code, 10 | http_agent] 11 | 12 | flows: 13 | - src_ip: 202.254.1.2 14 | dst_ip: 6.0.0.1 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 2374 18 | bytes@rev: 457 19 | packets: 8 20 | packets@rev: 6 21 | src_port: 43281 22 | dst_port: 80 23 | http_host: acs1.broadband-forum.org 24 | http_method_id: 2 25 | http_url: / 26 | http_method: POST 27 | http_status_code: 401 28 | http_agent: MikroTik 29 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/fixed-direction-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.236.146" 3 | dst_ip: "192.168.93.24" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | packets: 1 8 | src_port: 60643 9 | dst_port: 53 10 | dns_id: 313 11 | dns_flags: 0x0100 12 | dns_req_query_type: 1 13 | dns_req_query_class: 1 14 | dns_req_query_name: "ia-dns.net" 15 | - src_ip: "192.168.93.24" 16 | dst_ip: "192.168.236.146" 17 | ip_version: 4 18 | protocol: 17 19 | bytes: 67 20 | packets: 1 21 | src_port: 53 22 | dst_port: 60643 23 | dns_id: 313 24 | dns_flags: 0x8182 25 | dns_resp_rcode: 2 26 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/any-direction-single.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.1.140" 3 | dst_ip: "174.143.213.184" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 1234 7 | packets: 21 8 | src_port: 57678 9 | dst_port: 80 10 | http_host: "packetlife.net" 11 | http_url: "/images/layout/logo.png" 12 | http_method: "GET" 13 | http_status_code: 200 14 | http_agent: "Wget/1.12 (linux-gnu)" 15 | http_content_type: "image/png" 16 | - src_ip: "174.143.213.184" 17 | dst_ip: "192.168.1.140" 18 | ip_version: 4 19 | protocol: 6 20 | bytes: 23041 21 | packets: 19 22 | src_port: 80 23 | dst_port: 57678 24 | 25 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/fixed-direction-wrong.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.236.146" 3 | dst_ip: "192.168.93.24" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | packets: 1 8 | src_port: 60643 9 | dst_port: 53 10 | dns_id: 313 11 | dns_flags: 0x8182 12 | dns_resp_rcode: 2 13 | - src_ip: "192.168.93.24" 14 | dst_ip: "192.168.236.146" 15 | ip_version: 4 16 | protocol: 17 17 | bytes: 67 18 | packets: 1 19 | src_port: 53 20 | dst_port: 60643 21 | dns_id: 313 22 | dns_flags: 0x0100 23 | dns_req_query_type: 1 24 | dns_req_query_class: 1 25 | dns_req_query_name: "ia-dns.net" 26 | 27 | -------------------------------------------------------------------------------- /ansible/roles/repository_flowtest/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: FlowTest repository is installed 3 | ansible.builtin.yum_repository: 4 | name: flowtest 5 | file: flowtest 6 | description: FlowTest repository 7 | baseurl: "https://www.liberouter.org/repo/flowtest/$releasever/" 8 | skip_if_unavailable: yes 9 | gpgcheck: no 10 | repo_gpgcheck: no 11 | enabled: yes 12 | 13 | - name: FlowTest FPGA Firmware repository is installed 14 | ansible.builtin.yum_repository: 15 | name: flowtest-firmware 16 | file: flowtest 17 | description: FlowTest repository for FPGA firmwares 18 | baseurl: "https://www.liberouter.org/repo/flowtest/firmware/" 19 | skip_if_unavailable: yes 20 | gpgcheck: no 21 | repo_gpgcheck: no 22 | enabled: yes 23 | -------------------------------------------------------------------------------- /testing/validation/tls_malformed_cert.yml: -------------------------------------------------------------------------------- 1 | name: TLS Malformed Certificate 2 | description: Check that TLS traffic with a malformed certificate is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls_malformed_cert.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3] 10 | 11 | flows: 12 | - src_ip: 192.168.1.25 13 | dst_ip: 192.168.1.44 14 | ip_version: 4 15 | protocol: 6 16 | bytes: 352 17 | bytes@rev: 6762 18 | packets: 3 19 | packets@rev: 7 20 | src_port: 60002 21 | dst_port: 8443 22 | tls_server_version: 0x0303 23 | tls_cipher_suite: 0xc030 24 | tls_client_version: 0x0303 25 | tls_ja3: '0xfbe7e189e37a07ee33706f86bc746344' 26 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/fixed-direction.yml: -------------------------------------------------------------------------------- 1 | # Check that DNS response code Server Failure is parsed properly 2 | test: 3 | name: DNS Server Failure 4 | pcaps: ["dns_server_failure.pcap"] 5 | 6 | flows: 7 | - src_ip: "192.168.236.146" 8 | dst_ip: "192.168.93.24" 9 | ip_version: 4 10 | protocol: 17 11 | bytes: 67 12 | bytes@rev: 67 13 | packets: 1 14 | packets@rev: 1 15 | src_port: 60643 16 | dst_port: 53 17 | dns_id: 313 18 | _forward: 19 | dns_flags: 0x0100 20 | dns_req_query_type: 1 21 | dns_req_query_class: 1 22 | dns_req_query_name: "ia-dns.net" 23 | _reverse: 24 | dns_flags: 0x8182 25 | dns_resp_rcode: 2 26 | 27 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/ipv6addressgenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief IPv6 address generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "ipv6addressgenerator.h" 10 | 11 | namespace generator { 12 | 13 | IPv6AddressGenerator::IPv6AddressGenerator(IPv6Address netIp, uint8_t prefixLen) 14 | : _gen( 15 | PrefixedGenerator(std::vector(netIp.toBytes(), netIp.toBytes() + 16), prefixLen)) 16 | { 17 | if (prefixLen > 0 && !netIp.isValid()) { 18 | throw std::invalid_argument("invalid IPv6AddressGenerator net address"); 19 | } 20 | } 21 | 22 | IPv6Address IPv6AddressGenerator::Generate() 23 | { 24 | return IPv6Address(_gen.Generate().data()); 25 | } 26 | 27 | } // namespace generator 28 | -------------------------------------------------------------------------------- /testing/validation/tls_invalid_cert.yml: -------------------------------------------------------------------------------- 1 | name: TLS Invalid Certificate 2 | description: Check that TLS communication resulting in invalid certificate error is 3 | properly parsed. 4 | requirements: 5 | protocols: [tls] 6 | marks: [tls] 7 | pcap: tls_invalid_cert.pcap 8 | probe: 9 | protocols: [tls] 10 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3] 11 | 12 | flows: 13 | - src_ip: 192.168.1.29 14 | dst_ip: 192.168.1.25 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 919 18 | bytes@rev: 1561 19 | packets: 7 20 | packets@rev: 4 21 | src_port: 44300 22 | dst_port: 8443 23 | tls_server_version: 0x0304 24 | tls_cipher_suite: 0x1302 25 | tls_client_version: 0xeaea 26 | tls_ja3: '0xbcfedf9f1709891a892b5bb1571df55c' 27 | -------------------------------------------------------------------------------- /tools/common/external/doctest.cmake: -------------------------------------------------------------------------------- 1 | # doctest - a C++ testing framework 2 | # 3 | # To use, add DOCTEST_INCLUDE_DIR to your target includes: 4 | # target_include_directories(tests PRIVATE ${DOCTEST_INCLUDE_DIR}) 5 | 6 | find_package(Git REQUIRED) 7 | 8 | ExternalProject_Add( 9 | doctest 10 | PREFIX ${CMAKE_BINARY_DIR}/doctest 11 | 12 | GIT_REPOSITORY https://github.com/doctest/doctest.git 13 | GIT_TAG "v2.4.11" 14 | GIT_SHALLOW ON 15 | 16 | UPDATE_COMMAND "" 17 | CONFIGURE_COMMAND "" 18 | BUILD_COMMAND "" 19 | INSTALL_COMMAND "" 20 | LOG_DOWNLOAD ON 21 | ) 22 | 23 | # Expose required variable (DOCTEST_INCLUDE_DIR) to parent scope 24 | ExternalProject_Get_Property(doctest source_dir) 25 | set(DOCTEST_INCLUDE_DIR ${source_dir}/doctest CACHE INTERNAL "Path to include folder for doctest") 26 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-missing.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | dns_flags: 0x0100 14 | dns_req_query_type: 1 15 | dns_req_query_class: 1 16 | dns_req_query_name: "newportconceptsla.com" 17 | dns_flags@rev: 0x8180 18 | dns_resp_rcode: 0 19 | dns_resp_rr: 20 | - name: "newportconceptsla.com" 21 | type: 1 22 | class: 1 23 | ttl: 136 24 | data: "192.168.215.181" 25 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-one-wrong.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | dns_flags: 0x0100 14 | dns_req_query_type: 1 15 | dns_req_query_class: 1 16 | dns_req_query_name: "newportconceptsla.com" 17 | dns_flags@rev: 0x8180 18 | dns_resp_rcode: 0 19 | dns_resp_rr: 20 | - name: "unexpected.com" 21 | type: 5 22 | class: 2 23 | ttl: 136 24 | data: "192.168.215.1" 25 | 26 | -------------------------------------------------------------------------------- /testing/validation/http2_switch.yml: -------------------------------------------------------------------------------- 1 | name: HTTP 2.0 2 | description: Check that HTTP version 2.0 is parsed properly after switching from HTTP 3 | 1.1. 4 | requirements: 5 | protocols: [http] 6 | marks: [http] 7 | pcap: http2_switch.pcap 8 | probe: 9 | protocols: [http] 10 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 11 | http_agent] 12 | 13 | flows: 14 | - src_ip: 10.9.0.2 15 | dst_ip: 139.162.123.134 16 | ip_version: 4 17 | protocol: 6 18 | bytes: 446 19 | bytes@rev: 478 20 | packets: 4 21 | packets@rev: 2 22 | src_port: 58038 23 | dst_port: 80 24 | http_host: nghttp2.org 25 | http_url: /robots.txt 26 | http_method: GET 27 | http_method_id: 1 28 | http_status_code: 200 29 | http_agent: curl/7.61.0 30 | -------------------------------------------------------------------------------- /ansible/roles/probe_flowmon_driver/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - name: Switch Driver Without Rebooting 2 | ansible.builtin.command: sudo /home/flowmon/switch-nic-driver.sh {{ driver }} 3 | ignore_errors: True 4 | register: switch_result 5 | 6 | - name: Reboot Flowmon Probe 7 | ansible.builtin.reboot: 8 | reboot_command: sudo reboot 9 | reboot_timeout: 300 10 | when: switch_result.rc != 0 11 | 12 | - name: Ensure SCM service is running 13 | ansible.builtin.service: 14 | name: scm 15 | state: started 16 | register: scm_service 17 | until: scm_service.status.ActiveState == "active" 18 | retries: 6 19 | delay: 5 20 | when: switch_result.rc != 0 21 | 22 | - name: Switch Driver After Reboot 23 | ansible.builtin.command: sudo /home/flowmon/switch-nic-driver.sh {{ driver }} 24 | when: switch_result.rc != 0 25 | -------------------------------------------------------------------------------- /testing/validation/http_put.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Put Method 2 | description: Check that HTTP Put method is properly parsed from HTTP request. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_put.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_content_type] 11 | 12 | flows: 13 | - src_ip: 10.100.52.22 14 | dst_ip: 77.75.79.222 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 447 18 | bytes@rev: 369 19 | packets: 6 20 | packets@rev: 4 21 | src_port: 60250 22 | dst_port: 80 23 | http_host: seznam.cz 24 | http_url: / 25 | http_method: PUT 26 | http_method_id: 8 27 | http_status_code: 302 28 | http_agent: curl/7.29.0 29 | http_content_type: [application/json] 30 | -------------------------------------------------------------------------------- /ansible/roles/repository_ndk/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Liberouter NDK SmartNic SW repository is installed 3 | ansible.builtin.yum_repository: 4 | name: liberouter-ndk-app-nic-sw 5 | file: ndk-app-nic 6 | description: Liberouter NDK SmartNIC SW repository 7 | baseurl: "https://www.liberouter.org/repo/ndk-app/nic/sw/$releasever" 8 | skip_if_unavailable: yes 9 | gpgcheck: no 10 | repo_gpgcheck: no 11 | enabled: yes 12 | 13 | - name: Liberouter NDK SmartNic FW repository is installed 14 | ansible.builtin.yum_repository: 15 | name: liberouter-ndk-app-nic-fw 16 | file: ndk-app-nic 17 | description: Liberouter NDK SmartNIC FW repository 18 | baseurl: "https://www.liberouter.org/repo/ndk-app/nic/fw" 19 | skip_if_unavailable: yes 20 | gpgcheck: no 21 | repo_gpgcheck: no 22 | enabled: yes 23 | -------------------------------------------------------------------------------- /testing/validation/http_post.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Post Method 2 | description: Check that HTTP Post method is properly parsed from HTTP request. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_post.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_content_type] 11 | 12 | flows: 13 | - src_ip: 192.168.158.139 14 | dst_ip: 162.159.241.165 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 429 18 | bytes@rev: 2033 19 | packets: 6 20 | packets@rev: 6 21 | src_port: 4769 22 | dst_port: 80 23 | http_host: ask.wireshark.org 24 | http_url: / 25 | http_method: POST 26 | http_method_id: 2 27 | http_status_code: 403 28 | http_agent: curl/7.26.0 29 | http_content_type: text/html 30 | -------------------------------------------------------------------------------- /testing/validation/http_delete.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Delete Method 2 | description: Check that HTTP Delete method is properly parsed from HTTP request. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_delete.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_content_type] 11 | 12 | flows: 13 | - src_ip: 10.100.52.22 14 | dst_ip: 77.75.79.222 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 450 18 | bytes@rev: 369 19 | packets: 6 20 | packets@rev: 4 21 | src_port: 60278 22 | dst_port: 80 23 | http_host: seznam.cz 24 | http_url: / 25 | http_method: DELETE 26 | http_method_id: 32 27 | http_status_code: 302 28 | http_agent: curl/7.29.0 29 | http_content_type: [application/json] 30 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-one-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | _forward: 14 | dns_flags: 0x0100 15 | dns_req_query_type: 1 16 | dns_req_query_class: 1 17 | dns_req_query_name: "newportconceptsla.com" 18 | _reverse: 19 | dns_flags: 0x8180 20 | dns_resp_rcode: 0 21 | dns_resp_rr: 22 | - name: "newportconceptsla.com" 23 | type: 1 24 | class: 1 25 | ttl: 136 26 | data: "192.168.73.162" 27 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/generator/input/csv_basic_profile.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,L3_PROTO,L4_PROTO,SRC_PORT,DST_PORT,PACKETS,BYTES,PACKETS_REV,BYTES_REV 2 | 64230,66230,4,1,0,0,3,252,0,0 3 | 124244,126244,4,1,0,0,3,252,0,0 4 | -1,0,4,6,445,51572,2,316,2,281 5 | -3662,-3662,4,17,53,38176,1,84,1,68 6 | -126506,-1514,4,6,16386,443,28,10122,27,11019 7 | -7601,-1592,4,17,11179,123,4,304,4,304 8 | 642995,688834,4,6,49154,59075,396,578494,49,10646 9 | 670507,688487,4,6,53593,443,6,1158,4,903 10 | -4729,24,6,58,0,0,1,72,1,64 11 | 76917,76917,4,17,37683,53,2,128,2,144 12 | -273164,618532,4,17,5060,5060,15,6973,75,7228 13 | -273194,627120,4,1,0,0,1785,51765,1785,51765 14 | 184257,186258,4,1,0,0,3,252,0,0 15 | 681492,681492,6,58,0,0,1,72,0,0 16 | 680119,680535,6,17,58918,5355,2,140,0,0 17 | 622215,685944,6,6,993,59594,12,960,0,0 18 | 622218,685945,6,6,993,59596,12,960,0,0 19 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | 4 | [tool.pylint.messages_control] 5 | max-line-length = 120 6 | disable = "E0401, R0801" 7 | 8 | [tool.pylint.design] 9 | max-attributes=10 10 | max-args=10 11 | 12 | [tool.pylint.imports] 13 | known-third-party = ["docker"] 14 | 15 | [tool.pytest.ini_options] 16 | pythonpath = [ 17 | "tools/ft-profiler/src", 18 | "tools/ft-analyzer", 19 | "tools/ft-generator/tests", 20 | ] 21 | markers = [ 22 | "dev: development tests", 23 | "dev_docker: development tests using docker", 24 | "validation: probe validation tests", 25 | ] 26 | log_cli = "true" 27 | log_cli_level = "INFO" 28 | log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" 29 | log_cli_date_format = "%Y-%m-%d %H:%M:%S" 30 | addopts = "-s" 31 | 32 | [tool.isort] 33 | profile = "black" 34 | known_third_party = ["docker"] 35 | -------------------------------------------------------------------------------- /testing/validation/dns_refused.yml: -------------------------------------------------------------------------------- 1 | name: DNS Refused 2 | description: Check that DNS response code Refused is parsed properly. 3 | requirements: 4 | protocols: [dns] 5 | marks: [dns] 6 | pcap: dns_refused.pcap 7 | probe: 8 | protocols: [dns] 9 | at_least_one: [dns_id, dns_flags, dns_req_query_type, dns_req_query_class, dns_req_query_name, 10 | dns_resp_rcode] 11 | 12 | flows: 13 | - src_ip: 192.168.97.51 14 | dst_ip: 192.168.221.236 15 | ip_version: 4 16 | protocol: 17 17 | bytes: 67 18 | bytes@rev: 67 19 | packets: 1 20 | packets@rev: 1 21 | src_port: 54710 22 | dst_port: 53 23 | dns_id: 35371 24 | _forward: 25 | dns_flags: 0x0000 26 | dns_req_query_type: 28 27 | dns_req_query_class: 1 28 | dns_req_query_name: egebil.com 29 | _reverse: 30 | dns_flags: 0x8005 31 | dns_resp_rcode: 5 32 | -------------------------------------------------------------------------------- /testing/validation/http_get.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Get Method 2 | description: Check that HTTP Get method is properly parsed from HTTP request. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_get.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_content_type] 11 | 12 | flows: 13 | - src_ip: 192.168.1.140 14 | dst_ip: 174.143.213.184 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 1234 18 | bytes@rev: 23041 19 | packets: 21 20 | packets@rev: 19 21 | src_port: 57678 22 | dst_port: 80 23 | http_host: packetlife.net 24 | http_url: /images/layout/logo.png 25 | http_method: GET 26 | http_method_id: 1 27 | http_status_code: 200 28 | http_agent: Wget/1.12 (linux-gnu) 29 | http_content_type: image/png 30 | -------------------------------------------------------------------------------- /tools/ft-profiler/tests/ftprofiler/integration/data/csv_basic_profile.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,L3_PROTO,L4_PROTO,SRC_PORT,DST_PORT,PACKETS,BYTES,PACKETS_REV,BYTES_REV 2 | 64230,66230,4,1,0,0,3,252,0,0 3 | 124244,126244,4,1,0,0,3,252,0,0 4 | -1,0,4,6,445,51572,2,316,2,281 5 | -3662,-3662,4,17,53,38176,1,84,1,68 6 | -126506,-1514,4,6,16386,443,28,10122,27,11019 7 | -7601,-1592,4,17,11179,123,4,304,4,304 8 | 642995,688834,4,6,49154,59075,396,578494,49,10646 9 | 670507,688487,4,6,53593,443,6,1158,4,903 10 | -4729,24,6,58,0,0,1,72,1,64 11 | 76917,76917,4,17,37683,53,2,128,2,144 12 | -273164,618532,4,17,5060,5060,15,6973,75,7228 13 | -273194,627120,4,1,0,0,1785,51765,1785,51765 14 | 184257,186258,4,1,0,0,3,252,0,0 15 | 681492,681492,6,58,0,0,1,72,0,0 16 | 680119,680535,6,17,58918,5355,2,140,0,0 17 | 622215,685944,6,6,993,59594,12,960,0,0 18 | 622218,685945,6,6,993,59596,12,960,0,0 19 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_replicator/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Directory where FPGA firmwares are installed 3 | nfb_firmware_dir: /usr/share/ndk-fw 4 | 5 | # FPGA card to configure 6 | # System path to the card. Usually contains "/dev/nfb/{by-pci-slot,by-serial-no}/". 7 | # For example: 8 | # "/dev/nfb0" # Specified by card index 9 | # "/dev/nfb/by-serial-no/NFB-200G2QL/86" # Specified by card type and serial number. 10 | # "/dev/nfb/by-pci-slot/0000:ca:00.0" # Specified by PCI endpoint 11 | nfb_card: "/dev/nfb0" 12 | 13 | # Set MTU (Maximum transmission unit) of Ethernet interfaces 14 | # If empty, no configuration is performed. 15 | nfb_mtu: 9020 16 | 17 | # Set PMA (Physical Medium Attachment) of the Ethernet interface (e.g. LR, SR). 18 | # For possible option see output of `nfb-eth -Pv`. 19 | # If empty, no configuration is performed. 20 | nfb_pma: 21 | -------------------------------------------------------------------------------- /testing/validation/dns_nx_domain.yml: -------------------------------------------------------------------------------- 1 | name: DNS NX Domain 2 | description: Check that DNS response code NX domain is parsed properly. 3 | requirements: 4 | protocols: [dns] 5 | marks: [dns] 6 | pcap: dns_nx_domain.pcap 7 | probe: 8 | protocols: [dns] 9 | at_least_one: [dns_id, dns_flags, dns_req_query_type, dns_req_query_class, dns_req_query_name, 10 | dns_resp_rcode] 11 | 12 | flows: 13 | - src_ip: 192.168.170.56 14 | dst_ip: 217.13.4.24 15 | ip_version: 4 16 | protocol: 17 17 | bytes: 69 18 | bytes@rev: 69 19 | packets: 1 20 | packets@rev: 1 21 | src_port: 1711 22 | dst_port: 53 23 | dns_id: 30307 24 | _forward: 25 | dns_flags: 0x0100 26 | dns_req_query_type: 1 27 | dns_req_query_class: 1 28 | dns_req_query_name: GRIMM.utelsystems.local 29 | _reverse: 30 | dns_flags: 0x8583 31 | dns_resp_rcode: 3 32 | -------------------------------------------------------------------------------- /tools/ft-replay/src/CStringArray/cStringArray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Samuel Luptak 4 | * @brief CStringArray class implementation (used in dpdk plugins) 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "cStringArray.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void CStringArray::Push(const std::string& s) 17 | { 18 | std::unique_ptr chArray = std::make_unique(s.size() + 1); 19 | char* argPtr = chArray.get(); 20 | std::copy_n(s.c_str(), s.size() + 1, argPtr); 21 | 22 | _storage.emplace_back(std::move(chArray)); 23 | _chars.push_back(argPtr); 24 | } 25 | 26 | char** CStringArray::GetData() 27 | { 28 | return _chars.data(); 29 | } 30 | 31 | int CStringArray::GetSize() 32 | { 33 | return _chars.size(); 34 | } 35 | -------------------------------------------------------------------------------- /testing/validation/dns_server_failure.yml: -------------------------------------------------------------------------------- 1 | name: DNS Server Failure 2 | description: Check that DNS response code Server Failure is parsed properly. 3 | requirements: 4 | protocols: [dns] 5 | marks: [dns] 6 | pcap: dns_server_failure.pcap 7 | probe: 8 | protocols: [dns] 9 | at_least_one: [dns_id, dns_flags, dns_req_query_type, dns_req_query_class, dns_req_query_name, 10 | dns_resp_rcode] 11 | 12 | flows: 13 | - src_ip: 192.168.236.146 14 | dst_ip: 192.168.93.24 15 | ip_version: 4 16 | protocol: 17 17 | bytes: 67 18 | bytes@rev: 67 19 | packets: 1 20 | packets@rev: 1 21 | src_port: 60643 22 | dst_port: 53 23 | dns_id: 313 24 | _forward: 25 | dns_flags: 0x0100 26 | dns_req_query_type: 1 27 | dns_req_query_class: 1 28 | dns_req_query_name: ia-dns.net 29 | _reverse: 30 | dns_flags: 0x8182 31 | dns_resp_rcode: 2 32 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/validation/conf/probes.yml: -------------------------------------------------------------------------------- 1 | # Probes config example file 2 | 3 | - alias: ipfix-probe-10G 4 | name: cesnet-probe-1.liberouter.org 5 | type: IpfixprobeRaw 6 | interfaces: 7 | - name: eth2 8 | speed: 10 9 | mac: 00:00:00:00:00:00 10 | - name: eth3 11 | speed: 10 12 | mac: 01:01:01:01:01:01 13 | authentication: cesnet-general 14 | protocols: [ http, tls, dns, trill ] 15 | ansible-playbook-role: probe-ipfixprobe 16 | 17 | - alias: flowmonexp-10G 18 | name: cesnet-probe-2.liberouter.org 19 | type: FlowmonProbe 20 | interfaces: 21 | - name: eth2 22 | speed: 10 23 | mac: 00:00:00:00:00:00 24 | - name: eth3 25 | speed: 10 26 | mac: 01:01:01:01:01:01 27 | authentication: flowmon-probes 28 | protocols: [ http, tls, dns, vxlan, gre ] 29 | connector: 30 | input-plugin-type: [ dpdk, rawnetcap ] 31 | -------------------------------------------------------------------------------- /tools/ft-profile-trimmer/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel>=0.34"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "fttrimmer" 7 | version = "1.0.0" 8 | description = "Library for trimming network profiles from ft-profiler tool." 9 | authors = [ 10 | {name = " Vaclav Seidler", email = "Vaclav.Seidler@progress.com"}, 11 | ] 12 | maintainers = [ 13 | {name = " Vaclav Seidler", email = "Vaclav.Seidler@progress.com"} 14 | ] 15 | readme = {file = "README.md", content-type = "text/markdown"} 16 | 17 | classifiers = [ 18 | "Programming Language :: Python :: 3", 19 | "License :: OSI Approved :: BSD-3-Clause", 20 | "Operating System :: OS Independent", 21 | ] 22 | requires-python = ">=3.8" 23 | 24 | dependencies = [ 25 | "numpy", 26 | "pandas", 27 | ] 28 | 29 | [project.scripts] 30 | fttrimmer = "fttrimmer.fttrimmer:main" 31 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | mac: 00:00:00:00:00:00 8 | - name: eth3 9 | speed: 10 10 | mac: 01:01:01:01:01:01 11 | authentication: cesnet-general 12 | protocols: [ http, tls, dns, trill ] 13 | ansible-playbook-role: probe-ipfixprobe 14 | 15 | - alias: flowmonexp-10G 16 | name: cesnet-probe-2.liberouter.org 17 | type: FlowmonProbe 18 | interfaces: 19 | - name: eth2 20 | speed: 10 21 | mac: 00:00:00:00:00:00 22 | - name: eth3 23 | speed: 10 24 | mac: 01:01:01:01:01:01 25 | authentication: flowmon-probes 26 | protocols: [ http, tls, dns, vxlan, gre ] 27 | connector: 28 | input-plugin-type: [ dpdk, rawnetcap ] 29 | tests_whitelist: flowmon-whitelist 30 | -------------------------------------------------------------------------------- /tools/common/include/logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Lukas Hutak 4 | * @brief Auxiliary logger functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace ft { 16 | 17 | /** 18 | * @brief Perform default initialization of spdlog library. 19 | * 20 | * The function loads logger configuration from environment and modifies 21 | * default output message format. 22 | */ 23 | void LoggerInit(); 24 | 25 | /** 26 | * @brief Get a logger of the given name 27 | * 28 | * If the logger doesn't exist in spdlog registry, a new logger of default 29 | * type is created. Otherwise the existing one is returned. 30 | * 31 | * @param[in] name Name of the logger 32 | */ 33 | std::shared_ptr LoggerGet(std::string_view name); 34 | 35 | } // namespace ft 36 | -------------------------------------------------------------------------------- /tools/common/src/handlers.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Lukas Hutak 4 | * @brief Auxiliary logger functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "handlers.h" 10 | 11 | #include 12 | #include 13 | 14 | namespace ft { 15 | 16 | void CliHandleInvalidOption(std::string_view opt) 17 | { 18 | std::string err = "Invalid command line option '" + std::string(opt) + "'"; 19 | throw std::invalid_argument(err); 20 | } 21 | 22 | void CliHandleMissingArgument(std::string_view opt) 23 | { 24 | std::string err = "Missing required argument of '" + std::string(opt) + "'"; 25 | throw std::invalid_argument(err); 26 | } 27 | 28 | void CliHandleUnimplementedOption(std::string_view opt) 29 | { 30 | std::string err = "Unimplemented option '" + std::string(opt) + "'"; 31 | throw std::runtime_error(err); 32 | } 33 | 34 | } // namespace ft 35 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: WebKit 4 | 5 | AlwaysBreakBeforeMultilineStrings: true 6 | AlignAfterOpenBracket: AlwaysBreak 7 | AllowAllArgumentsOnNextLine: false 8 | AllowAllParametersOfDeclarationOnNextLine: false 9 | AllowShortIfStatementsOnASingleLine: Never 10 | AllowShortFunctionsOnASingleLine: Inline 11 | AlwaysBreakTemplateDeclarations: Yes 12 | BinPackArguments: false 13 | BinPackParameters: false 14 | BreakInheritanceList: BeforeComma 15 | ColumnLimit: 100 16 | Cpp11BracedListStyle: true 17 | FixNamespaceComments: true 18 | IndentGotoLabels: false 19 | KeepEmptyLinesAtTheStartOfBlocks: false 20 | NamespaceIndentation: None 21 | ShortNamespaceLines: 0 22 | SpaceAfterCStyleCast: true 23 | SpaceAfterTemplateKeyword: true 24 | SpaceInEmptyBlock: false 25 | SpacesInContainerLiterals: false 26 | PointerAlignment: Left 27 | TabWidth: '4' 28 | UseTab: ForContinuationAndIndentation 29 | ... 30 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/flows/relative_time.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312160780,1678312166780,17,192.168.128.124,81.2.248.189,60426,123,4,304 3 | 1678312157497,1678312163497,17,192.168.128.50,147.251.48.140,38626,123,4,304 4 | 1678312161962,1678312167962,17,192.168.4.225,147.251.48.140,35133,123,4,304 5 | 1678312162056,1678312168055,17,192.168.51.36,37.187.104.44,41461,123,4,304 6 | 1678312162266,1678312168266,17,192.168.51.21,81.2.248.189,59749,123,4,304 7 | 1678312163238,1678312169238,17,192.168.50.66,162.159.200.1,59137,123,4,304 8 | 1678312162275,1678312162483,6,192.168.128.125,192.168.128.120,2210,34668,4,284 9 | 1678312162275,1678312162487,6,192.168.128.120,192.168.128.125,34668,2210,6,357 10 | 1678312166205,1678312166209,6,192.168.4.71,192.168.60.90,389,10366,3,150 11 | 1678312161293,1678312167294,17,192.168.4.225,81.2.248.189,35133,123,4,304 12 | -------------------------------------------------------------------------------- /tools/ft-orchestration/tests/dev/config/files/probes-invalid-bad-whitelist.yml: -------------------------------------------------------------------------------- 1 | - alias: ipfix-probe-10G 2 | name: cesnet-probe-1.liberouter.org 3 | type: IpfixprobeRaw 4 | interfaces: 5 | - name: eth2 6 | speed: 10 7 | mac: 00:00:00:00:00:00 8 | - name: eth3 9 | speed: 10 10 | mac: 01:01:01:01:01:01 11 | authentication: cesnet-general 12 | protocols: [ http, tls, dns, trill ] 13 | ansible-playbook-role: probe-ipfixprobe 14 | 15 | - alias: flowmonexp-10G 16 | name: cesnet-probe-2.liberouter.org 17 | type: FlowmonProbe 18 | interfaces: 19 | - name: eth2 20 | speed: 10 21 | mac: 00:00:00:00:00:00 22 | - name: eth3 23 | speed: 10 24 | mac: 01:01:01:01:01:01 25 | authentication: flowmon-probes 26 | protocols: [ http, tls, dns, vxlan, gre ] 27 | connector: 28 | input-plugin-type: [ dpdk, rawnetcap ] 29 | tests_whitelist: not-existing-whitelist 30 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/vlan.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief VLAN layer 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::protocol { 14 | 15 | /** 16 | * @brief IEEE 802.1Q VLAN. 17 | * @note 18 | * Compared to the usual definition, the structure is modified to 19 | * contain only the VLAN ID and the following Ethernet type, i.e. 20 | * it does not contain its own identifier at the beginning. 21 | */ 22 | struct VLAN { 23 | uint16_t _VlanId; /**< Flags and VLAN ID */ 24 | uint16_t _Ethertype; /**< Next header type */ 25 | 26 | /** @brief Exact size of the header */ 27 | static constexpr uint16_t HEADER_SIZE = 4; 28 | } __attribute__((packed)); 29 | 30 | static_assert(sizeof(VLAN) == VLAN::HEADER_SIZE, "Unexpected header size"); 31 | 32 | } // namespace replay::protocol 33 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/basic-biflow-reverse-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.56.102" 3 | dst_ip: "192.168.56.101" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 1900 7 | bytes@rev: 751 8 | packets: 4 9 | packets@rev: 6 10 | ttl: 64 11 | ttl@rev: 64 12 | tcp_flags: 0x1a 13 | tcp_flags@rev: 0x1a 14 | src_port: 443 15 | dst_port: 45422 16 | - src_ip: "192.168.56.102" 17 | dst_ip: "192.168.56.101" 18 | ip_version: 4 19 | protocol: 6 20 | bytes: 1520 21 | bytes@rev: 625 22 | packets: 3 23 | packets@rev: 5 24 | ttl: 64 25 | ttl@rev: 128 26 | tcp_flags: 0x1a 27 | tcp_flags@rev: 0x1a 28 | src_port: 443 29 | dst_port: 45422 30 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/ipv6HopByHop.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief IPv6 Hop-by-Hop layer 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::protocol { 14 | 15 | /** 16 | * @brief IPv6 Hop-by-Hop header. 17 | */ 18 | struct IPv6HopByHop { 19 | uint8_t _nextProtoId; 20 | uint8_t _extensionLen; /**< Not including first 8 octets */ 21 | // ... data ... 22 | 23 | /** @brief Minimum size of the header to be casted and interpreted. */ 24 | static constexpr uint16_t HEADER_SIZE_MIN = 2; 25 | 26 | /** @brief Get the real length of the header */ 27 | uint16_t GetHdrLength() const noexcept { return (_extensionLen + 1U) * 8U; } 28 | } __attribute__((packed)); 29 | 30 | static_assert(sizeof(IPv6HopByHop) == IPv6HopByHop::HEADER_SIZE_MIN, "Unexpected header size"); 31 | 32 | } // namespace replay::protocol 33 | -------------------------------------------------------------------------------- /testing/validation/http_invalid_method.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Invalid Method 2 | description: Check that packets with invalid HTTP method are parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_invalid_method.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_url, http_status_code, http_agent, http_content_type] 10 | 11 | flows: 12 | - src_ip: 192.168.1.36 13 | dst_ip: 192.168.1.25 14 | ip_version: 4 15 | protocol: 6 16 | bytes: 520 17 | bytes@rev: 980 18 | packets: 7 19 | packets@rev: 5 20 | src_port: 55022 21 | dst_port: 8080 22 | http_host: 192.168.1.25:8000 23 | http_url: / 24 | http_method: INVALIDMETHOD 25 | http_status_code: 501 26 | http_agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) 27 | Chrome/98.0.4758.102 Safari/537.36 28 | http_content_type: [text/html, text/html;charset=utf-8] 29 | -------------------------------------------------------------------------------- /tools/common/src/logger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Lukas Hutak 4 | * @brief Auxiliary logger functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "logger.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | namespace ft { 18 | 19 | static std::mutex loggerGetMutex; 20 | 21 | void LoggerInit() 22 | { 23 | spdlog::cfg::load_env_levels(); 24 | spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %n: %v"); 25 | } 26 | 27 | std::shared_ptr LoggerGet(std::string_view name) 28 | { 29 | std::lock_guard guard(loggerGetMutex); 30 | 31 | const std::string tmp {name}; 32 | auto logger = spdlog::get(tmp); 33 | 34 | if (logger) { 35 | // Logger already exists 36 | return logger; 37 | } 38 | 39 | return spdlog::stdout_color_mt(tmp); 40 | } 41 | 42 | } // namespace ft 43 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/custom-key-wrong.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "fe80::c001:2ff:fe40:0" 3 | dst_ip: "ff02::1:ffe4:0" 4 | ip_version: 6 5 | protocol: 58 6 | bytes: 72 7 | packets: 1 8 | - src_ip: "fe80::c002:3ff:fee4:0" 9 | dst_ip: "fe80::c001:2ff:fe40:0" 10 | ip_version: 6 11 | protocol: 58 12 | bytes: 72 13 | packets: 1 14 | - src_ip: "fe80::c002:3ff:fee4:0" 15 | dst_ip: "fe80::c001:2ff:fe40:0" 16 | ip_version: 6 17 | protocol: 58 18 | bytes: 75 19 | packets: 1 20 | - src_ip: "fe80::c001:2ff:fe40:0" 21 | dst_ip: "fe80::c002:3ff:fee4:0" 22 | ip_version: 60 23 | protocol: 58 24 | bytes: 64 25 | packets: 1 26 | 27 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/ipv6DestOptions.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief IPv6 Destination layer 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::protocol { 14 | 15 | /** 16 | * @brief IPv6 Destination header. 17 | */ 18 | struct IPv6DestOptions { 19 | uint8_t _nextProtoId; 20 | uint8_t _extensionLen; /**< Not including first 8 octets */ 21 | // ... data ... 22 | 23 | /** @brief Minimum size of the header to be casted and interpreted. */ 24 | static constexpr uint16_t HEADER_SIZE_MIN = 2; 25 | 26 | /** @brief Get the real length of the header */ 27 | uint16_t GetHdrLength() const noexcept { return (_extensionLen + 1U) * 8U; } 28 | } __attribute__((packed)); 29 | 30 | static_assert( 31 | sizeof(IPv6DestOptions) == IPv6DestOptions::HEADER_SIZE_MIN, 32 | "Unexpected header size"); 33 | 34 | } // namespace replay::protocol 35 | -------------------------------------------------------------------------------- /testing/validation/http_404.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Error 404 2 | description: Check that HTTP 404 error response code is parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_404.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_referer] 11 | 12 | flows: 13 | - src_ip: 192.168.1.11 14 | dst_ip: 192.168.1.1 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 657 18 | bytes@rev: 867 19 | packets: 6 20 | packets@rev: 5 21 | src_port: 50820 22 | dst_port: 80 23 | http_host: 192.168.1.1 24 | http_url: /check.lp?dsl=1&old_dsl=Up 25 | http_method: GET 26 | http_method_id: 1 27 | http_status_code: 404 28 | http_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, 29 | like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063 30 | http_referer: http://192.168.1.1/ 31 | -------------------------------------------------------------------------------- /testing/validation/tls_ssl30.yml: -------------------------------------------------------------------------------- 1 | name: SSL 3.0 Traffic 2 | description: Check that SSL v3.0 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls_ssl30.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3, 10 | tls_subject_cn, tls_validity_not_before, tls_validity_not_after, tls_public_key_alg] 11 | 12 | flows: 13 | - src_ip: 10.100.50.48 14 | dst_ip: 10.100.50.139 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 3302 18 | bytes@rev: 2919 19 | packets: 15 20 | packets@rev: 11 21 | src_port: 44854 22 | dst_port: 7001 23 | tls_server_version: 0x0300 24 | tls_cipher_suite: 0xc014 25 | tls_client_version: 0x0300 26 | tls_subject_cn: '' 27 | tls_validity_not_before: 1679647830 28 | tls_validity_not_after: 1682239830 29 | tls_public_key_alg: rsaEncryption 30 | tls_ja3: '0x77bfeeb56cc1af3a4241cf31c4a49e1a' 31 | -------------------------------------------------------------------------------- /tools/ft-generator/src/pcppethlayer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief A wrapper class around pcpp::EthLayer 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace generator { 14 | 15 | /** 16 | * @brief A customized pcpp::EthLayer 17 | * 18 | * This is needed because the original pcpp::EthLayer's computeCalculateFields 19 | * overwrites the etherType, yet only supports a very limited set of layers, so 20 | * we set the correct etherType ourselves instead of relying on the 21 | * computeCalculateFields method to do so automatically. 22 | */ 23 | class PcppEthLayer : public pcpp::EthLayer { 24 | public: 25 | using pcpp::EthLayer::EthLayer; 26 | 27 | /** 28 | * @brief Override computeCalculateFields of pcpp::EthLayer to do nothing 29 | */ 30 | void computeCalculateFields() override; 31 | }; 32 | 33 | } // namespace generator 34 | -------------------------------------------------------------------------------- /tools/ft-generator/src/data/tlskeys.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Pregenerated TLS keys 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace generator { 16 | 17 | struct TlsKeyData { 18 | std::string _cn; 19 | std::vector _certDer; 20 | std::string _privKeyPem; 21 | }; 22 | 23 | /** 24 | * These keys were generated using command: 25 | * openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes \ 26 | * -subj \ 27 | * "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname" 28 | * 29 | * the certificates were transformed to DER format using command: 30 | * openssl x509 -outform der cert.der 31 | */ 32 | extern const std::vector TLS_KEY_DATABASE; 33 | 34 | } // namespace generator 35 | -------------------------------------------------------------------------------- /testing/validation/tls_ssl20.yml: -------------------------------------------------------------------------------- 1 | name: SSL 2.0 Traffic 2 | description: Check that SSL v2.0 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: ssl-v2.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3, 10 | tls_subject_cn, tls_validity_not_before, tls_validity_not_after, tls_public_key_alg] 11 | 12 | flows: 13 | - src_ip: 10.10.1.89 14 | dst_ip: 10.10.3.1 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 1022 18 | bytes@rev: 1890 19 | packets: 13 20 | packets@rev: 11 21 | src_port: 49288 22 | dst_port: 443 23 | tls_server_version: 0x0002 24 | tls_cipher_suite: 0x0700c0 25 | tls_client_version: 0x0002 26 | tls_subject_cn: stan.musecurity.com 27 | tls_validity_not_before: 1118100538 28 | tls_validity_not_after: 1382916538 29 | tls_public_key_alg: rsaEncryption 30 | tls_ja3: '0xe76a0619f4cf744ab2b9ea0ac9b8d5a4' 31 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-wrong.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | dns_flags: 0x0100 14 | dns_req_query_type: 1 15 | dns_req_query_class: 1 16 | dns_req_query_name: "newportconceptsla.com" 17 | dns_flags@rev: 0x8180 18 | dns_resp_rcode: 0 19 | dns_resp_rr: 20 | - name: "newportconceptsla.com" 21 | type: 1 22 | class: 2 23 | ttl: 136 24 | data: "192.168.215.181" 25 | - name: "unexpected.com" 26 | type: 5 27 | class: 2 28 | ttl: 136 29 | data: "192.168.215.1" 30 | 31 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/ipv6Routing.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief IPv6 Routing layer 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::protocol { 14 | 15 | /** 16 | * @brief IPv6 Routing header. 17 | */ 18 | struct IPv6Routing { 19 | uint8_t _nextProtoId; 20 | uint8_t _extensionLen; /**< Not including first 8 octets */ 21 | uint8_t _routingType; 22 | uint8_t _segmentsLeft; 23 | // ... data ... 24 | 25 | /** @brief Minimum size of the header to be casted and interpreted. */ 26 | static constexpr uint16_t HEADER_SIZE_MIN = 4; 27 | 28 | /** @brief Get the real length of the header */ 29 | uint16_t GetHdrLength() const noexcept { return (_extensionLen + 1U) * 8U; } 30 | } __attribute__((packed)); 31 | 32 | static_assert(sizeof(IPv6Routing) == IPv6Routing::HEADER_SIZE_MIN, "Unexpected header size"); 33 | 34 | } // namespace replay::protocol 35 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/ipv4addressgenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief IPv4 address generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "prefixedgenerator.h" 10 | 11 | #include 12 | 13 | namespace generator { 14 | 15 | using IPv4Address = pcpp::IPv4Address; 16 | 17 | /** 18 | * @brief Generator of IPv4 addresses 19 | */ 20 | class IPv4AddressGenerator { 21 | public: 22 | /** 23 | * @brief Construct a new IPv4AddressGenerator object 24 | * 25 | * @param netIp The network address to generate the addresses from 26 | * @param prefixLen The prefix length 27 | */ 28 | IPv4AddressGenerator(IPv4Address netIp, uint8_t prefixLen); 29 | 30 | /** 31 | * @brief Generate an IPv4 address 32 | * 33 | * @return The address 34 | */ 35 | IPv4Address Generate(); 36 | 37 | private: 38 | PrefixedGenerator _gen; 39 | }; 40 | 41 | } // namespace generator 42 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: > 2 | -*, 3 | clang-analyzer-*, 4 | clang-diagnostic-*, 5 | performance-*, 6 | -performance-enum-size, 7 | readability-identifier-naming 8 | 9 | FormatStyle: file 10 | WarningsAsErrors: '*' 11 | HeaderFilterRegex: 'tools/*' 12 | CheckOptions: 13 | - key: readability-identifier-naming.NamespaceCase 14 | value: lower_case 15 | - key: readability-identifier-naming.ClassCase 16 | value: CamelCase 17 | - key: readability-identifier-naming.ClassMethodCase 18 | value: CamelCase 19 | - key: readability-identifier-naming.PrivateMemberPrefix 20 | value: _ 21 | - key: readability-identifier-naming.StructCase 22 | value: CamelCase 23 | - key: readability-identifier-naming.FunctionCase 24 | value: CamelCase 25 | - key: readability-identifier-naming.StaticConstantCase 26 | value: CamelCase 27 | - key: readability-identifier-naming.VariableCase 28 | value: camelBack 29 | - key: readability-identifier-naming.GlobalConstantCase 30 | value: UPPER_CASE 31 | -------------------------------------------------------------------------------- /ansible/roles/nfb_tsu/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Make sure the FPGA card ({{ nfb_card }}) is available 3 | ansible.builtin.stat: 4 | path: "{{ nfb_card }}" 5 | follow: true 6 | get_attributes: false 7 | get_checksum: false 8 | get_mime: false 9 | register: card_stat 10 | failed_when: not card_stat.stat.exists 11 | 12 | - name: Determine escaped systemd path of the FPGA card ({{ nfb_card }}) 13 | ansible.builtin.command: "systemd-escape -p {{ nfb_card }}" 14 | register: card_escaped 15 | 16 | - name: Install NFB-TSU systemd service (if not already present) 17 | ansible.builtin.copy: 18 | src: flowtest-nfb-tsu@.service 19 | dest: /run/systemd/system/flowtest-nfb-tsu@.service 20 | 21 | - name: "{{ nfb_tsu_enable | ternary(\"Enable\", \"Disable\") }} NFB-TSU systemd service" 22 | ansible.builtin.systemd: 23 | daemon_reload: true 24 | name: "flowtest-nfb-tsu@{{ card_escaped.stdout }}.service" 25 | state: "{{ nfb_tsu_enable | ternary(\"started\", \"stopped\") }}" 26 | -------------------------------------------------------------------------------- /testing/validation/tls11.yml: -------------------------------------------------------------------------------- 1 | name: TLS 1.1 Traffic 2 | description: Check that TLS 1.1 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls11.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3, 10 | tls_subject_cn, tls_validity_not_before, tls_validity_not_after, tls_public_key_alg] 11 | 12 | flows: 13 | - src_ip: 10.100.50.48 14 | dst_ip: 10.100.50.139 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 3230 18 | bytes@rev: 3854 19 | packets: 15 20 | packets@rev: 11 21 | src_port: 45926 22 | dst_port: 7001 23 | tls_server_version: 0x0302 24 | tls_cipher_suite: 0xc014 25 | tls_client_version: 0x0302 26 | tls_issuer_cn: Flowmon Packet Investigator 27 | tls_subject_cn: '' 28 | tls_validity_not_before: 1679647830 29 | tls_validity_not_after: 1682239830 30 | tls_public_key_alg: rsaEncryption 31 | tls_ja3: '0x94341b7808a52862a34787f3050d736d' 32 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/ipv6addressgenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief IPv6 address generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "prefixedgenerator.h" 12 | 13 | #include 14 | 15 | namespace generator { 16 | 17 | using IPv6Address = pcpp::IPv6Address; 18 | 19 | /** 20 | * @brief Generator of IPv6 addresses 21 | */ 22 | class IPv6AddressGenerator { 23 | public: 24 | /** 25 | * @brief Construct a new IPv6AddressGenerator object 26 | * 27 | * @param netIp The network address to generate the addresses from 28 | * @param prefixLen The prefix length 29 | */ 30 | IPv6AddressGenerator(IPv6Address netIp, uint8_t prefixLen); 31 | 32 | /** 33 | * @brief Generate an IPv6 address 34 | * 35 | * @return The address 36 | */ 37 | IPv6Address Generate(); 38 | 39 | private: 40 | PrefixedGenerator _gen; 41 | }; 42 | 43 | } // namespace generator 44 | -------------------------------------------------------------------------------- /tools/common/include/handlers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Lukas Hutak 4 | * @brief Auxiliary handler functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace ft { 14 | 15 | /** 16 | * @brief Throw a properly formatted exception about invalid option. 17 | * @param[in] arg Option name 18 | * @throw std::invalid_argument 19 | */ 20 | [[noreturn]] void CliHandleInvalidOption(std::string_view opt); 21 | 22 | /** 23 | * @brief Throw a properly formatted exception about missing required argument. 24 | * @param[in] arg Option name 25 | * @throw std::invalid_argument 26 | */ 27 | [[noreturn]] void CliHandleMissingArgument(std::string_view opt); 28 | 29 | /** 30 | * @brief Throw a properly formatted exception about unimplemented option. 31 | * @param[in] arg Argument name 32 | * @throw std::runtime_error 33 | */ 34 | [[noreturn]] void CliHandleUnimplementedOption(std::string_view opt); 35 | 36 | } // namespace ft 37 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/any-direction-both.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.1.140" 3 | dst_ip: "174.143.213.184" 4 | ip_version: 4 5 | protocol: 6 6 | bytes: 1234 7 | packets: 21 8 | src_port: 57678 9 | dst_port: 80 10 | http_host: "packetlife.net" 11 | http_url: "/images/layout/logo.png" 12 | http_method: "GET" 13 | http_status_code: 200 14 | http_agent: "Wget/1.12 (linux-gnu)" 15 | http_content_type: "image/png" 16 | - src_ip: "174.143.213.184" 17 | dst_ip: "192.168.1.140" 18 | ip_version: 4 19 | protocol: 6 20 | bytes: 23041 21 | packets: 19 22 | src_port: 80 23 | dst_port: 57678 24 | http_host: "packetlife.net" 25 | http_url: "/images/layout/logo.png" 26 | http_method: "GET" 27 | http_status_code: 200 28 | http_agent: "Wget/1.12 (linux-gnu)" 29 | http_content_type: "image/png" 30 | 31 | -------------------------------------------------------------------------------- /tools/ft-generator/src/layers/payload.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @author Michal Sedlak 5 | * @brief Generic payload layer planner 6 | * 7 | * SPDX-License-Identifier: BSD-3-Clause 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "../flow.h" 13 | #include "../layer.h" 14 | #include "../packet.h" 15 | #include "../pcpppacket.h" 16 | 17 | namespace generator { 18 | 19 | /** 20 | * @brief A representation of a Payload layer. 21 | */ 22 | class Payload : public Layer { 23 | public: 24 | /** 25 | * @brief Plan Payload layer 26 | * 27 | * @param flow Flow to plan. 28 | */ 29 | void PlanFlow(Flow& flow) override; 30 | 31 | /** 32 | * @brief Build Payload layer in packet 33 | * 34 | * @param packet Packet to build. 35 | * @param params Layers parameters 36 | * @param plan Packet plan. 37 | */ 38 | void Build(PcppPacket& packet, Packet::layerParams& params, Packet& plan) override; 39 | 40 | private: 41 | }; 42 | 43 | } // namespace generator 44 | -------------------------------------------------------------------------------- /tools/ft-replay/src/protocol/udp.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief UDP layer 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | namespace replay::protocol { 15 | 16 | /** 17 | * @brief UDP header with auxiliary functions. 18 | */ 19 | struct UDP { 20 | uint16_t _srcPort; 21 | uint16_t _dstPort; 22 | uint16_t _length; /**< Total length including header and payload */ 23 | uint16_t _checksum; 24 | 25 | /** @brief Exact size of the header */ 26 | static constexpr uint16_t HEADER_SIZE = 8; 27 | /** @brief Minimum value of Length */ 28 | static constexpr uint16_t LENGTH_MIN_VALUE = 8U; 29 | 30 | /** @brief Check if the length definition is valid. */ 31 | bool IsValid() const noexcept { return be16toh(_length) >= LENGTH_MIN_VALUE; } 32 | } __attribute__((packed)); 33 | 34 | static_assert(sizeof(UDP) == UDP::HEADER_SIZE, "Unexpected header size"); 35 | 36 | } // namespace replay::protocol 37 | -------------------------------------------------------------------------------- /testing/validation/tls10.yml: -------------------------------------------------------------------------------- 1 | name: TLS 1.0 Traffic 2 | description: Check that TLS 1.0 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls10.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_client_version, tls_ja3, 10 | tls_issuer_cn, tls_subject_cn, tls_validity_not_before, tls_validity_not_after, 11 | tls_public_key_alg] 12 | 13 | flows: 14 | - src_ip: 10.100.50.48 15 | dst_ip: 10.100.50.139 16 | ip_version: 4 17 | protocol: 6 18 | bytes: 3319 19 | bytes@rev: 3864 20 | packets: 15 21 | packets@rev: 11 22 | src_port: 45216 23 | dst_port: 7001 24 | tls_server_version: 0x0301 25 | tls_cipher_suite: 0xc014 26 | tls_client_version: 0x0301 27 | tls_issuer_cn: Flowmon Packet Investigator 28 | tls_subject_cn: '' 29 | tls_validity_not_before: 1679647830 30 | tls_validity_not_after: 1682239830 31 | tls_public_key_alg: rsaEncryption 32 | tls_ja3: '0xf51d9908719e96c24a1b539da446a39f' 33 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/precise/flows/split.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1694766049217,1694766049217,58,75dc:b024:c91a:9cac:e1f3:6816:fee0:df5e,baee:5812:648d:4e56:70f9:b40b:7f70:6faf,,,1,72 3 | 1694766089639,1694766089639,58,75dc:b024:c91a:9cac:e1f3:6816:fee0:df5e,baee:5812:648d:4e56:70f9:b40b:7f70:6faf,,,1,72 4 | 1694766120987,1694766128628,58,75dc:b024:c91a:9cac:e1f3:6816:fee0:df5e,baee:5812:648d:4e56:70f9:b40b:7f70:6faf,,,2,144 5 | 1694766028859,1694766323538,6,158.251.62.121,61.246.124.243,443,56259,17,2328 6 | 1694766327274,1694766327274,6,158.251.62.121,61.246.124.243,443,56259,1,40 7 | 1694766026732,1694766321937,6,61.246.124.243,158.251.62.121,56259,443,32,2153 8 | 1694766328767,1694766328767,6,61.246.124.243,158.251.62.121,56259,443,1,40 9 | 1694766019694,1694766319629,17,132.37.167.45,66.18.211.150,35145,443,477,316307 10 | 1694766319759,1694766326452,17,132.37.167.45,66.18.211.150,35145,443,15,9427 11 | 1694766019694,1694766326452,17,132.37.168.46,66.18.212.151,32358,443,492,325734 12 | -------------------------------------------------------------------------------- /tools/ft-generator/src/config/tlsencryption.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief TlsEncryption configuration section 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "tlsencryption.h" 10 | #include "common.h" 11 | 12 | namespace generator { 13 | namespace config { 14 | 15 | TlsEncryption::TlsEncryption(const YAML::Node& node) 16 | { 17 | CheckAllowedKeys( 18 | node, 19 | {"always_encrypt_ports", "never_encrypt_ports", "otherwise_with_probability"}); 20 | 21 | if (node["always_encrypt_ports"].IsDefined()) { 22 | _alwaysEncryptPorts = ParseMany(node["always_encrypt_ports"]); 23 | } 24 | 25 | if (node["never_encrypt_ports"].IsDefined()) { 26 | _neverEncryptPorts = ParseMany(node["never_encrypt_ports"]); 27 | } 28 | 29 | if (node["otherwise_with_probability"].IsDefined()) { 30 | _otherwiseEncryptProbability = ParseProbability(node["otherwise_with_probability"]); 31 | } 32 | } 33 | 34 | } // namespace config 35 | } // namespace generator 36 | -------------------------------------------------------------------------------- /testing/validation/icmpv6.yml: -------------------------------------------------------------------------------- 1 | name: ICMPv6 Traffic 2 | description: Check that ICMPv6 is properly parsed. 3 | requirements: 4 | protocols: [icmpv6] 5 | marks: [icmpv6] 6 | pcap: ipv6-neighbor-discovery.pcap 7 | probe: 8 | protocols: [icmpv6] 9 | key: [src_ip, dst_ip, protocol] 10 | at_least_one: [icmp_type, icmp_code, icmp_type_code] 11 | 12 | flows: 13 | - src_ip: fe80::c002:3ff:fee4:0 14 | dst_ip: fe80::c001:2ff:fe40:0 15 | ip_version: 6 16 | protocol: 58 17 | bytes: 72 18 | packets: 1 19 | icmp_type: 136 20 | icmp_code: 0 21 | icmp_type_code: 34816 22 | - src_ip: fe80::c002:3ff:fee4:0 23 | dst_ip: fe80::c001:2ff:fe40:0 24 | ip_version: 6 25 | protocol: 58 26 | bytes: 72 27 | packets: 1 28 | icmp_type: 135 29 | icmp_code: 0 30 | icmp_type_code: 34560 31 | - src_ip: fe80::c001:2ff:fe40:0 32 | dst_ip: fe80::c002:3ff:fee4:0 33 | ip_version: 6 34 | protocol: 58 35 | bytes: 64 36 | packets: 1 37 | icmp_type: 136 38 | icmp_code: 0 39 | icmp_type_code: 34816 40 | -------------------------------------------------------------------------------- /tools/common/external/yaml-cpp.cmake: -------------------------------------------------------------------------------- 1 | # Yaml-cpp library 2 | # 3 | # yaml-cpp is a YAML parser and emitter in C++ matching the YAML 1.2 spec. 4 | # 5 | # "yaml-cpp" is exposed to be used as a dependency in other CMake targets 6 | # example usage: target_link_libraries(my_target PRIVATE yaml-cpp) 7 | 8 | include(FetchContent) 9 | 10 | FetchContent_Declare( 11 | yaml-cpp 12 | GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git 13 | GIT_TAG yaml-cpp-0.7.0 14 | ) 15 | 16 | # Make sure that subproject accepts predefined build options without warnings. 17 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 18 | 19 | # Library does not compile with -Werror that we use in some builds 20 | string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ") 21 | string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ") 22 | string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ") 23 | set(YAML_CPP_BUILD_TESTS OFF) 24 | set(YAML_CPP_BUILD_TOOLS OFF) 25 | set(YAML_CPP_INSTALL OFF) 26 | FetchContent_MakeAvailable(yaml-cpp) 27 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/flows/long_flows_missing.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1653637200311,1653637440474,17,192.168.187.28,212.24.128.196,5060,5060,5,2325 3 | 1653637200339,1653637491979,17,212.24.128.196,192.168.187.28,5060,5060,25,2410 4 | 1653637500525,1653637740718,17,192.168.187.28,212.24.128.196,5060,5060,5,2325 5 | 1653637500575,1653637792002,17,212.24.128.196,192.168.187.28,5060,5060,25,2410 6 | 1653637800748,1653638040871,17,192.168.187.28,212.24.128.196,5060,5060,5,2323 7 | 1653637800758,1653638092007,17,212.24.128.196,192.168.187.28,5060,5060,25,2408 8 | 1653637200281,1653637500005,1,5.180.196.2,5.180.196.6,0,0,152,13150 9 | 1653637200281,1653637500005,1,5.180.196.6,5.180.196.2,0,0,221,12480 10 | 1653637500508,1653637800435,1,5.180.196.2,5.180.196.6,0,0,128,13565 11 | 1653637500508,1653637800435,1,5.180.196.6,5.180.196.2,0,0,352,11250 12 | 1653637800936,1653638100595,1,5.180.196.2,5.180.196.6,0,0,120,12369 13 | 1653637800937,1653638100595,1,5.180.196.6,5.180.196.2,0,0,548,13421 14 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | _forward: 14 | dns_flags: 0x0100 15 | dns_req_query_type: 1 16 | dns_req_query_class: 1 17 | dns_req_query_name: "newportconceptsla.com" 18 | _reverse: 19 | dns_flags: 0x8180 20 | dns_resp_rcode: 0 21 | dns_resp_rr: 22 | - name: "newportconceptsla.com" 23 | type: 1 24 | class: 1 25 | ttl: 136 26 | data: "192.168.73.162" 27 | - name: "newportconceptsla.com" 28 | type: 1 29 | class: 1 30 | ttl: 136 31 | data: "192.168.215.181" 32 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/macaddressgenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Mac address generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "prefixedgenerator.h" 12 | 13 | #include 14 | 15 | namespace generator { 16 | 17 | using MacAddress = pcpp::MacAddress; 18 | 19 | /** 20 | * @brief Generator of Mac addresses 21 | */ 22 | class MacAddressGenerator { 23 | public: 24 | /** 25 | * @brief Construct a new Mac Address Generator object 26 | * 27 | * @param baseAddr The base address to generate the addresses from, respectively the prefix 28 | * @param prefixLen The prefix length 29 | */ 30 | MacAddressGenerator(MacAddress baseAddr, uint8_t prefixLen); 31 | 32 | /** 33 | * @brief Generate a Mac address 34 | * 35 | * @return MacAddress 36 | */ 37 | MacAddress Generate(); 38 | 39 | private: 40 | PrefixedGenerator _gen; 41 | uint8_t _prefixLen; 42 | }; 43 | 44 | } // namespace generator 45 | -------------------------------------------------------------------------------- /tools/ft-replay/src/timeDuration.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @brief Implementation of the TimeDuration class for calculating duration based on timestamps. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "timeDuration.hpp" 10 | 11 | #include 12 | 13 | namespace replay { 14 | 15 | TimeDuration::TimeDuration() 16 | : _isInitailized(false) 17 | , _oldestTimestamp(std::numeric_limits::max()) 18 | , _newestTimestamp(0) 19 | { 20 | } 21 | 22 | void TimeDuration::Update(uint64_t currentTimestamp) noexcept 23 | { 24 | _isInitailized = true; 25 | 26 | if (_oldestTimestamp > currentTimestamp) { 27 | _oldestTimestamp = currentTimestamp; 28 | } 29 | 30 | if (_newestTimestamp < currentTimestamp) { 31 | _newestTimestamp = currentTimestamp; 32 | } 33 | } 34 | 35 | uint64_t TimeDuration::GetDuration() const noexcept 36 | { 37 | if (!_isInitailized) { 38 | return 0; 39 | } 40 | 41 | return _newestTimestamp - _oldestTimestamp; 42 | } 43 | 44 | } // namespace replay 45 | -------------------------------------------------------------------------------- /tools/ft-generator/tests/ftgeneratortests/src/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Matej Hulák 3 | 4 | Copyright: (C) 2023 CESNET, z.s.p.o. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | 7 | isort:skip_file 8 | """ 9 | 10 | from ftgeneratortests.src.constants import ( 11 | GENERATOR_ERROR_RET_CODE, 12 | L3_PROTOCOL_IPV4, 13 | L3_PROTOCOL_IPV6, 14 | L4_PROTOCOL_TCP, 15 | L4_PROTOCOL_UDP, 16 | L4_PROTOCOL_ICMP, 17 | L4_PROTOCOL_ICMPV6, 18 | L4_PROTOCOL_NONE, 19 | MAC_MASK_SIZE, 20 | MTU_SIZE, 21 | ENCAPSULATION_ABS_TOLERANCE, 22 | FRAGMENTATION_ABS_TOLERANCE, 23 | REPORT_REL_TOLERANCE, 24 | TIMING_ABS_TOLERANCE, 25 | ) 26 | from ftgeneratortests.src.common import get_prob_from_str 27 | from ftgeneratortests.src.flow import ExtendedFlow, Flow 28 | from ftgeneratortests.src.cache import FlowCache 29 | from ftgeneratortests.src.generator_config import GeneratorConfig 30 | from ftgeneratortests.src.generator import Generator 31 | from ftgeneratortests.src.parser import parse_pcap, parse_profiles, parse_report 32 | -------------------------------------------------------------------------------- /testing/validation/ovpn.yml: -------------------------------------------------------------------------------- 1 | name: Open VPN Traffic 2 | description: Check that traffic with Open VPN protocol is recognized. 3 | requirements: 4 | protocols: [ovpn] 5 | marks: [ovpn] 6 | pcap: ovpn.pcap 7 | probe: 8 | protocols: [ovpn] 9 | at_least_one: [ovpn_conf_level] 10 | 11 | flows: 12 | - src_ip: 192.168.43.91 13 | dst_ip: 90.178.247.107 14 | ip_version: 4 15 | protocol: 6 16 | src_port: 54113 17 | dst_port: 10103 18 | bytes: 49004 19 | bytes@rev: 64203 20 | packets: 164 21 | packets@rev: 166 22 | ovpn_conf_level: 74 23 | - src_ip: 90.178.247.107 24 | dst_ip: 192.168.43.91 25 | ip_version: 4 26 | protocol: 17 27 | src_port: 10102 28 | dst_port: 60753 29 | bytes: 1380 30 | bytes@rev: 0 31 | packets: 6 32 | packets@rev: 0 33 | ovpn_conf_level: 0 34 | - src_ip: 90.178.247.107 35 | dst_ip: 192.168.43.91 36 | ip_version: 4 37 | protocol: 17 38 | src_port: 10100 39 | dst_port: 62158 40 | bytes: 204 41 | bytes@rev: 0 42 | packets: 3 43 | packets@rev: 0 44 | -------------------------------------------------------------------------------- /tools/ft-generator/src/tests/domainnamegenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Tests for domain name generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "../domainnamegenerator.h" 10 | 11 | #include 12 | 13 | #include 14 | 15 | using namespace generator; 16 | 17 | TEST_SUITE_BEGIN("DomainNameGenerator"); 18 | 19 | TEST_CASE("generated domain names are the specified length") 20 | { 21 | auto& g = DomainNameGenerator::GetInstance(); 22 | 23 | for (int i = 4; i < 255; i++) { 24 | auto domain = g.Generate(i); 25 | CAPTURE(domain); 26 | CHECK(domain.size() == i); 27 | } 28 | } 29 | 30 | TEST_CASE("generated domain names are the correct format") 31 | { 32 | auto& g = DomainNameGenerator::GetInstance(); 33 | 34 | std::regex re("(([a-zA-Z0-9]+-)*[a-zA-Z0-9]+\\.)+[a-zA-Z0-9]+"); 35 | for (int i = 4; i < 255; i++) { 36 | auto domain = g.Generate(i); 37 | CAPTURE(domain); 38 | CHECK(std::regex_match(domain, re)); 39 | } 40 | } 41 | 42 | TEST_SUITE_END(); 43 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/replicator/ref/basic_time_0.8.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1678312161600,1678312169100,17,192.168.128.134,81.2.248.189,60426,123,4,304 3 | 1678312161600,1678312169100,17,192.168.128.124,81.2.249.189,60426,123,4,304 4 | 1678312157497,1678312164997,17,192.168.128.60,147.251.48.140,38626,123,4,304 5 | 1678312157497,1678312164997,17,192.168.128.50,147.251.49.140,38626,123,4,304 6 | 1678312163078,1678312170578,17,192.168.4.235,147.251.48.140,35133,123,4,304 7 | 1678312163078,1678312170578,17,192.168.4.225,147.251.49.140,35133,123,4,304 8 | 1678312174681,1678312182181,17,192.168.128.134,81.2.248.189,60426,123,4,304 9 | 1678312174681,1678312182181,17,192.168.128.124,81.2.249.189,60426,123,4,304 10 | 1678312170578,1678312178078,17,192.168.128.60,147.251.48.140,38626,123,4,304 11 | 1678312170578,1678312178078,17,192.168.128.50,147.251.49.140,38626,123,4,304 12 | 1678312176159,1678312183659,17,192.168.4.235,147.251.48.140,35133,123,4,304 13 | 1678312176159,1678312183659,17,192.168.4.225,147.251.49.140,35133,123,4,304 14 | -------------------------------------------------------------------------------- /tools/ft-analyzer/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author(s): Tomas Jansky 6 | 7 | Copyright: (C) 2022 Flowmon Networks a.s. 8 | SPDX-License-Identifier: BSD-3-Clause 9 | 10 | Setup script with necessary information to create python package. 11 | """ 12 | 13 | import setuptools 14 | 15 | with open("README.md", "r", encoding="utf-8") as fh: 16 | long_description = fh.read() 17 | 18 | setuptools.setup( 19 | name="ftanalyzer", 20 | version="1.0.0", 21 | author="Flowmon Networks a.s.", 22 | author_email="support@flowmon.com", 23 | description="Library evaluating network flows. It contains different flow validation models.", 24 | long_description=long_description, 25 | long_description_content_type="text/markdown", 26 | classifiers=[ 27 | "Programming Language :: Python :: 3", 28 | "License :: OSI Approved :: BSD-3-Clause", 29 | "Operating System :: OS Independent", 30 | ], 31 | python_requires=">=3.6", 32 | packages=setuptools.find_packages(), 33 | ) 34 | -------------------------------------------------------------------------------- /tools/ft-generator/src/layers/http.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief HTTP application layer 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "../flow.h" 12 | #include "../layer.h" 13 | #include "../packet.h" 14 | #include "../pcpppacket.h" 15 | 16 | namespace generator { 17 | 18 | /** 19 | * @brief A representation of a Http layer. 20 | */ 21 | class Http : public Layer { 22 | public: 23 | /** 24 | * @brief Plan Http layer 25 | * 26 | * @param flow Flow to plan. 27 | */ 28 | void PlanFlow(Flow& flow) override; 29 | 30 | /** 31 | * @brief Post plan callback 32 | * 33 | * @param flow The flow 34 | */ 35 | void PostPlanFlow(Flow& flow) override; 36 | 37 | /** 38 | * @brief Build Http layer in packet 39 | * 40 | * @param packet Packet to build. 41 | * @param params Layers parameters 42 | * @param plan Packet plan. 43 | */ 44 | void Build(PcppPacket& packet, Packet::layerParams& params, Packet& plan) override; 45 | }; 46 | 47 | } // namespace generator 48 | -------------------------------------------------------------------------------- /testing/validation/tls12.yml: -------------------------------------------------------------------------------- 1 | name: TLS 1.2 Traffic 2 | description: Check that TLS 1.2 is properly parsed. 3 | requirements: 4 | protocols: [tls] 5 | marks: [tls] 6 | pcap: tls12_alpn.pcap 7 | probe: 8 | protocols: [tls] 9 | at_least_one: [tls_server_version, tls_cipher_suite, tls_alpn, tls_sni, tls_client_version, 10 | tls_issuer_cn, tls_ja3, tls_subject_cn, tls_validity_not_before, tls_validity_not_after, 11 | tls_public_key_alg] 12 | 13 | flows: 14 | - src_ip: 10.100.50.30 15 | dst_ip: 77.75.77.222 16 | ip_version: 4 17 | protocol: 6 18 | bytes: 1726 19 | bytes@rev: 6358 20 | packets: 23 21 | packets@rev: 16 22 | src_port: 46766 23 | dst_port: 443 24 | tls_server_version: 0x0303 25 | tls_cipher_suite: 0xcca8 26 | tls_alpn: h2 27 | tls_sni: seznam.cz 28 | tls_client_version: 0x0303 29 | tls_issuer_cn: R3 30 | tls_subject_cn: www.seznam.cz 31 | tls_validity_not_before: 1680498180 32 | tls_validity_not_after: 1688274179 33 | tls_public_key_alg: rsaEncryption 34 | tls_ja3: '0x7f9ee38af4d6bfadb75f00b209febe07' 35 | -------------------------------------------------------------------------------- /tools/ft-generator/src/calendar.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief A flow calendar 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "calendar.h" 10 | #include "flow.h" 11 | 12 | #include 13 | 14 | namespace generator { 15 | 16 | static bool CompareFlows(const std::unique_ptr& lhs, const std::unique_ptr& rhs) 17 | { 18 | return lhs->GetNextPacketTime() > rhs->GetNextPacketTime(); 19 | } 20 | 21 | void Calendar::Push(std::unique_ptr flow) 22 | { 23 | _flows.push_back(std::move(flow)); 24 | std::push_heap(_flows.begin(), _flows.end(), CompareFlows); 25 | } 26 | 27 | const Flow& Calendar::Top() const 28 | { 29 | return *_flows.front().get(); 30 | } 31 | 32 | std::unique_ptr Calendar::Pop() 33 | { 34 | std::pop_heap(_flows.begin(), _flows.end(), CompareFlows); 35 | std::unique_ptr flow = std::move(_flows.back()); 36 | _flows.pop_back(); 37 | return flow; 38 | } 39 | 40 | bool Calendar::IsEmpty() const 41 | { 42 | return _flows.empty(); 43 | } 44 | 45 | } // namespace generator 46 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/custom-key-ok.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "fe80::c001:2ff:fe40:0" 3 | dst_ip: "ff02::1:ffe4:0" 4 | ip_version: 6 5 | protocol: 58 6 | bytes: 72 7 | packets: 1 8 | icmp_type_code: 34560 9 | - src_ip: "fe80::c002:3ff:fee4:0" 10 | dst_ip: "fe80::c001:2ff:fe40:0" 11 | ip_version: 6 12 | protocol: 58 13 | bytes: 72 14 | packets: 1 15 | icmp_type_code: 34816 16 | - src_ip: "fe80::c002:3ff:fee4:0" 17 | dst_ip: "fe80::c001:2ff:fe40:0" 18 | ip_version: 6 19 | protocol: 58 20 | bytes: 72 21 | packets: 1 22 | icmp_type_code: 34560 23 | - src_ip: "fe80::c001:2ff:fe40:0" 24 | dst_ip: "fe80::c002:3ff:fee4:0" 25 | ip_version: 6 26 | protocol: 58 27 | bytes: 64 28 | packets: 1 29 | icmp_type_code: 34816 30 | 31 | -------------------------------------------------------------------------------- /ci/test.gitlab-ci.yaml: -------------------------------------------------------------------------------- 1 | .install: 2 | stage: test 3 | image: $DOCKER_IMAGE:$DOCKER_TAG 4 | script: 5 | - sudo yum install -y --setopt='tsflags=' $DOCKER_TAG/RPMS/*/*.rpm 6 | variables: { GIT_STRATEGY: none } 7 | 8 | install [Oracle Linux 8]: 9 | extends: .install 10 | needs: ["rpmbuild [Oracle Linux 8]"] 11 | variables: { DOCKER_TAG: ol8 } 12 | 13 | install [Oracle Linux 9]: 14 | extends: .install 15 | needs: ["rpmbuild [Oracle Linux 9]"] 16 | variables: { DOCKER_TAG: ol9 } 17 | 18 | install [Rocky Linux 8]: 19 | extends: .install 20 | needs: ["rpmbuild [Rocky Linux 9]"] 21 | variables: { DOCKER_TAG: rl9 } 22 | 23 | pytest: 24 | stage: test 25 | needs: ["rpmbuild [Oracle Linux 8]"] 26 | image: $DOCKER_IMAGE:$DOCKER_TAG 27 | variables: { DOCKER_TAG: ol8 } 28 | script: 29 | - sudo yum install -y --setopt='tsflags=' $DOCKER_TAG/RPMS/*/*.rpm 30 | - pipenv run pytest -v -s -m "not dev and not dev_docker" | tee pytest.log 31 | artifacts: 32 | paths: [ pytest.log ] 33 | when: always 34 | 35 | ctest: 36 | stage: test 37 | script: [make test] 38 | -------------------------------------------------------------------------------- /tools/common/include/converters.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Lukas Hutak 4 | * @brief Auxiliary conversion functions 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace ft { 16 | 17 | /** 18 | * @brief Convert an unsigned integer value to hexadecimal string 19 | * @tparam T Type of the number 20 | * @param[in] value Value to convert 21 | * @return Converted value in the format "0xXXXX" (number of digits depends on the type) 22 | */ 23 | template , bool> = true> 24 | std::string ConvertUintToHex(T value) 25 | { 26 | const size_t digits = 2 * sizeof(T); 27 | std::stringstream stream; 28 | 29 | stream << "0x"; 30 | 31 | // Since stringstream handles uint8_t as a character, convert the value to uint64_t 32 | stream << std::setfill('0'); 33 | stream << std::setw(digits); 34 | stream << std::hex; 35 | stream << uint64_t(value); 36 | 37 | return stream.str(); 38 | } 39 | 40 | } // namespace ft 41 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/basic-wrong-unsupported.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.56.101" 3 | dst_ip: "192.168.56.102" 4 | protocol: 6 5 | bytes: 751 6 | packets: 6 7 | src_port: 45422 8 | dst_port: 443 9 | tcp_flags: 0x1a 10 | - src_ip: "192.168.56.102" 11 | dst_ip: "192.168.56.101" 12 | protocol: 6 13 | bytes: 1900 14 | packets: 4 15 | src_port: 443 16 | dst_port: 45422 17 | tcp_flags: 0x1a 18 | - src_ip: "192.168.56.101" 19 | dst_ip: "192.168.56.102" 20 | protocol: 6 21 | bytes: 625 22 | packets: 5 23 | src_port: 45422 24 | dst_port: 443 25 | tcp_flags: 0x1a 26 | - src_ip: "192.168.56.102" 27 | dst_ip: "192.168.56.101" 28 | protocol: 6 29 | bytes: 1520 30 | packets: 3 31 | src_port: 443 32 | dst_port: 45422 33 | tcp_flags: 0x1a 34 | -------------------------------------------------------------------------------- /tools/ft-generator/src/generators/prefixedgenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Prefixed generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "prefixedgenerator.h" 10 | #include "../utils.h" 11 | 12 | #include 13 | 14 | namespace generator { 15 | 16 | PrefixedGenerator::PrefixedGenerator(const std::vector& base, unsigned int prefixLen) 17 | : _base(base) 18 | , _prefixLen(prefixLen) 19 | , _totalLen(base.size() * 8) 20 | , _lfsr(_totalLen - _prefixLen) 21 | { 22 | if (_prefixLen > _totalLen) { 23 | throw std::invalid_argument("invalid PrefixedGenerator prefix length"); 24 | } 25 | } 26 | 27 | std::vector PrefixedGenerator::Generate() 28 | { 29 | std::vector result = _base; 30 | const std::vector& state = _lfsr.GetState(); 31 | auto it = state.begin(); 32 | for (unsigned int n = _prefixLen; n < _totalLen && it != state.end(); n++, it++) { 33 | SetBit(n, *it, result.data()); 34 | } 35 | _lfsr.Next(); 36 | return result; 37 | } 38 | 39 | } // namespace generator 40 | -------------------------------------------------------------------------------- /ansible/roles/repository_crb/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: DNF config-manager is available 3 | ansible.builtin.dnf: 4 | name: dnf-command(config-manager) 5 | state: latest 6 | 7 | - name: PowerTools repository is enabled (CentOS/Rocky/etc. 8) 8 | ansible.builtin.command: dnf config-manager --set-enabled powertools 9 | when: 10 | - ansible_os_family == 'RedHat' 11 | - ansible_distribution != 'OracleLinux' 12 | - ansible_distribution_major_version | int == 8 13 | 14 | - name: CodeReady Builder repository is enabled (CentOS/Rocky/etc. 9+) 15 | ansible.builtin.command: dnf config-manager --set-enabled crb 16 | when: 17 | - ansible_os_family == 'RedHat' 18 | - ansible_distribution != 'OracleLinux' 19 | - ansible_distribution_major_version | int > 8 20 | 21 | - name: CodeReady Builder repository is enabled (Oracle Linux) 22 | ansible.builtin.command: dnf config-manager --set-enabled {{ repo }} 23 | vars: 24 | repo: "ol{{ ansible_distribution_major_version }}_codeready_builder" 25 | when: 26 | - ansible_os_family == 'RedHat' 27 | - ansible_distribution == 'OracleLinux' 28 | -------------------------------------------------------------------------------- /tools/ft-replay/src/dissector/protocolType.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file 3 | * @brief Protocol type 4 | * @author Lukas Hutak 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace replay::dissector { 14 | 15 | /** 16 | * @brief IANA Internet Protocol Number. 17 | * @see https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml 18 | */ 19 | enum class ProtocolType : uint8_t { 20 | IPv6HopOpt = 0, /**< IPv6 Hop-by-Hop Option */ 21 | IPv4 = 4, /**< IPv4 encapsulation (i.e. IP in IP) */ 22 | TCP = 6, /**< Transmission Control */ 23 | UDP = 17, /**< User Datagram */ 24 | IPv6 = 41, /**< IPv6 encapsulation */ 25 | IPv6Route = 43, /**< Routing Header for IPv6 */ 26 | IPv6Frag = 44, /**< Fragment Header for IPv6 */ 27 | ICMPv6 = 58, /**< Internet Control Message Protocol for IPv6 */ 28 | IPv6NoNext = 59, /**< No Next Header for IPv6 */ 29 | IPv6Dest = 60, /**< Destination Options for IPv6 */ 30 | 31 | Unknown = 255, /**< Unknown/unsupported/unrecognized protocol */ 32 | }; 33 | 34 | } // namespace replay::dissector 35 | -------------------------------------------------------------------------------- /testing/validation/http_500.yml: -------------------------------------------------------------------------------- 1 | name: HTTP Error 500 2 | description: Check that HTTP 500 error response code is parsed properly. 3 | requirements: 4 | protocols: [http] 5 | marks: [http] 6 | pcap: http_500.pcap 7 | probe: 8 | protocols: [http] 9 | at_least_one: [http_host, http_method, http_method_id, http_url, http_status_code, 10 | http_agent, http_content_type, http_referer] 11 | 12 | flows: 13 | - src_ip: 192.168.0.113 14 | dst_ip: 209.31.22.39 15 | ip_version: 4 16 | protocol: 6 17 | bytes: 931 18 | bytes@rev: 4298 19 | packets: 6 20 | packets@rev: 6 21 | src_port: 3541 22 | dst_port: 80 23 | http_host: www.frys.com 24 | http_url: 25 | /category/Outpost/Notebooks+&+Tablets/View+All+Notebooks?site=sa:Notebook%20Pod:Pod2 26 | http_method: GET 27 | http_method_id: 1 28 | http_status_code: 500 29 | http_agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.3) Gecko/20090824 30 | Firefox/3.5.3 (.NET CLR 3.5.30729) 31 | http_content_type: [text/html, text/html; charset=UTF-8] 32 | http_referer: http://www.frys.com/template/notebook/ 33 | -------------------------------------------------------------------------------- /tools/ft-replay/src/CStringArray/cStringArray.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Samuel Luptak 4 | * @brief CStringArray class header (used in dpdk plugins) 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * class CStringArray is used to convert 17 | * C++ strings (std::string) into C strings (char *) 18 | * and store them. 19 | */ 20 | 21 | class CStringArray { 22 | public: 23 | /** 24 | * @brief Converts std::string into char * and saves the result 25 | * 26 | * @param[in] s std::string that gets converted into char * 27 | * 28 | */ 29 | void Push(const std::string& s); 30 | 31 | /** 32 | * @brief Returns the stored C strings 33 | * 34 | * @return Array of C strings 35 | */ 36 | char** GetData(); 37 | 38 | /** 39 | * @brief Returns the number of stored C strings 40 | * 41 | * @return Number of stored C strings 42 | */ 43 | int GetSize(); 44 | 45 | private: 46 | std::vector> _storage; 47 | std::vector _chars; 48 | }; 49 | -------------------------------------------------------------------------------- /ci/upload.gitlab-ci.yaml: -------------------------------------------------------------------------------- 1 | upload python packages: 2 | stage: upload 3 | needs: ["python package build", "pytest", "ctest"] 4 | script: 5 | - | 6 | REPO_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi" 7 | export TWINE_USERNAME=gitlab-ci-token 8 | export TWINE_PASSWORD=${CI_JOB_TOKEN} 9 | 10 | set +e # allow errors (job ends if return code isn't 0 by default) 11 | pipenv run python3 -m twine upload --verbose --skip-existing --repository-url $REPO_URL tools/**/dist/* 12 | only: ['main'] 13 | 14 | upload rpm package: 15 | stage: upload 16 | tags: [ci-shell] 17 | needs: ["rpmbuild [Oracle Linux 8]", "rpmbuild [Oracle Linux 9]", "pytest", "ctest"] 18 | script: 19 | - | 20 | umask 0002 21 | mkdir -p $CI_REPO_PATH/8 22 | mkdir -p $CI_REPO_PATH/9 23 | rsync -ur --chmod=g+w --delete ol8/RPMS/x86_64/* $CI_REPO_PATH/8 24 | rsync -ur --chmod=g+w --delete ol9/RPMS/x86_64/* $CI_REPO_PATH/9 25 | find $CI_REPO_PATH -mindepth 1 -maxdepth 2 -type d -exec createrepo --update '{}' \; 26 | only: 27 | variables: 28 | - $CI_COMMIT_BRANCH == "main" && $CI_REPO_PATH 29 | -------------------------------------------------------------------------------- /tools/ft-generator/src/domainnamegenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Domain name generator 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "randomgenerator.h" 12 | 13 | #include 14 | #include 15 | 16 | namespace generator { 17 | 18 | /** 19 | * @brief A singleton component to generate random domain names 20 | */ 21 | class DomainNameGenerator { 22 | public: 23 | /** 24 | * @brief Get the domain name generator instance 25 | */ 26 | static DomainNameGenerator& GetInstance(); 27 | 28 | /** 29 | * @brief Generate a domain name 30 | * 31 | * @param length The desired length 32 | * @return The randomly generated domain name 33 | */ 34 | std::string Generate(std::size_t length); 35 | 36 | private: 37 | const std::size_t _minWordLen; 38 | const std::size_t _maxWordLen; 39 | std::vector _startIndexForWordLen; 40 | std::vector _endIndexForWordLen; 41 | 42 | DomainNameGenerator(); 43 | 44 | std::string GenerateName(uint64_t length, RandomGenerator& rng); 45 | }; 46 | 47 | } // namespace generator 48 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/references/basic.yml: -------------------------------------------------------------------------------- 1 | # Check that TCP header is properly parsed 2 | test: 3 | name: Simple TCP traffic 4 | pcaps: ["tls12.pcap"] 5 | 6 | flows: 7 | - src_ip: "192.168.56.101" 8 | dst_ip: "192.168.56.102" 9 | ip_version: 4 10 | protocol: 6 11 | bytes: 751 12 | bytes@rev: 1900 13 | packets: 6 14 | packets@rev: 4 15 | ttl: 64 16 | ttl@rev: 64 17 | tcp_flags: 0x1a 18 | tcp_flags@rev: 0x1a 19 | src_port: 45422 20 | dst_port: 443 21 | tcp_options: 0x11e 22 | tcp_options@rev: 0x11e 23 | - src_ip: "192.168.56.101" 24 | dst_ip: "192.168.56.102" 25 | ip_version: 4 26 | protocol: 6 27 | bytes: 625 28 | bytes@rev: 1520 29 | packets: 5 30 | packets@rev: 3 31 | ttl: 128 32 | ttl@rev: 64 33 | tcp_flags: 0x1a 34 | tcp_flags@rev: 0x1a 35 | src_port: 45422 36 | dst_port: 443 37 | tcp_options: 0x11e 38 | tcp_options@rev: 0x11e 39 | -------------------------------------------------------------------------------- /ansible/roles/firewall/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Choose controller for firewall configuration. 3 | # By default (i.e. "auto"), the role tries to detect running controller 4 | # automatically. If no supported controller is found, all firewall actions 5 | # are skipped. 6 | # If no firewall should be configured, set controller to "none". 7 | # Supported values: auto/nftables/firewalld/none 8 | firewall_controller: auto 9 | 10 | # Reload firewall rules before configuration. 11 | # Any previously defined non-permanent rules will be removed. 12 | firewall_reload: true 13 | 14 | # List of firewall ports to open in tuple format [, ]. 15 | # Newly added rules are NOT permanent and they will be removed when 16 | # the firewall is reloaded next time. 17 | # For example: [[80, tcp], [443, tcp]] 18 | firewall_ports: [] 19 | 20 | # -- nftable controller specific variables -- 21 | 22 | # Ruleset where to append new firewall rules. 23 | # Expected format: " " 24 | firewall_nftables_ruleset: "inet firewall input" 25 | 26 | # -- firewalld controller specific variables -- 27 | 28 | # Firewall zone to configure. 29 | firewall_firewalld_zone: "public" 30 | -------------------------------------------------------------------------------- /ci/prepare.gitlab-ci.yaml: -------------------------------------------------------------------------------- 1 | .docker: 2 | stage: prepare 3 | tags: [$DOCKER_SHELL_TAG] 4 | script: ["docker build $DOCKER_OPTS -t $DOCKER_IMAGE:$DOCKER_TAG --build-arg OS_DISTRO=$OS_DISTRO --build-arg OS_RELEASE=$OS_RELEASE -f docker/Dockerfile.gitlab-ci ."] 5 | 6 | docker [Oracle Linux 8]: 7 | extends: .docker 8 | variables: 9 | OS_DISTRO: "oraclelinux" 10 | OS_RELEASE: "8" 11 | DOCKER_TAG: "ol8" 12 | 13 | docker [Oracle Linux 9]: 14 | extends: .docker 15 | variables: 16 | OS_DISTRO: "oraclelinux" 17 | OS_RELEASE: "9" 18 | DOCKER_TAG: "ol9" 19 | 20 | docker [Rocky Linux 9]: 21 | extends: .docker 22 | variables: 23 | OS_DISTRO: "rockylinux" 24 | OS_RELEASE: "9" 25 | DOCKER_TAG: "rl9" 26 | 27 | docker-rebuild [Oracle Linux 8]: 28 | extends: "docker [Oracle Linux 8]" 29 | variables: { DOCKER_OPTS: --no-cache } 30 | when: manual 31 | 32 | docker-rebuild [Oracle Linux 9]: 33 | extends: "docker [Oracle Linux 9]" 34 | variables: { DOCKER_OPTS: --no-cache } 35 | when: manual 36 | 37 | docker-rebuild [Rocky Linux 9]: 38 | extends: "docker [Rocky Linux 9]" 39 | variables: { DOCKER_OPTS: --no-cache } 40 | when: manual 41 | -------------------------------------------------------------------------------- /tools/ft-generator/src/config/timestamps.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief Timestamps configuration section 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "timestamps.h" 10 | #include "common.h" 11 | 12 | namespace generator { 13 | namespace config { 14 | 15 | Timestamps::Timestamps(const YAML::Node& node) 16 | { 17 | CheckAllowedKeys( 18 | node, 19 | { 20 | "link_speed", 21 | "min_packet_gap", 22 | "flow_min_dir_switch_gap", 23 | "flow_max_interpacket_gap", 24 | }); 25 | 26 | if (node["link_speed"].IsDefined()) { 27 | _linkSpeedBps = ParseSpeedUnit(node["link_speed"]); 28 | } 29 | 30 | if (node["min_packet_gap"].IsDefined()) { 31 | _minPacketGapNanos = ParseTimeUnit(node["min_packet_gap"]); 32 | } 33 | 34 | if (node["flow_min_dir_switch_gap"].IsDefined()) { 35 | _flowMinDirSwitchGapNanos = ParseTimeUnit(node["flow_min_dir_switch_gap"]); 36 | } 37 | 38 | if (node["flow_max_interpacket_gap"].IsDefined()) { 39 | _flowMaxInterpacketGapNanos = ParseTimeUnit(node["flow_max_interpacket_gap"]); 40 | } 41 | } 42 | 43 | } // namespace config 44 | } // namespace generator 45 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/statistical/flows/long_flows_split.csv: -------------------------------------------------------------------------------- 1 | START_TIME,END_TIME,PROTOCOL,SRC_IP,DST_IP,SRC_PORT,DST_PORT,PACKETS,BYTES 2 | 1653637200311,1653637440474,17,192.168.187.28,212.24.128.196,5060,5060,5,2325 3 | 1653637200339,1653637491979,17,212.24.128.196,192.168.187.28,5060,5060,25,2410 4 | 1653637500525,1653637740718,17,192.168.187.28,212.24.128.196,5060,5060,5,2325 5 | 1653637500575,1653637792002,17,212.24.128.196,192.168.187.28,5060,5060,25,2410 6 | 1653637800748,1653638040871,17,192.168.187.28,212.24.128.196,5060,5060,5,2323 7 | 1653637800758,1653638092007,17,212.24.128.196,192.168.187.28,5060,5060,25,2408 8 | 1653637200281,1653637500005,1,5.180.196.2,5.180.196.6,0,0,595,17255 9 | 1653637200281,1653637500005,1,5.180.196.6,5.180.196.2,0,0,595,17255 10 | 1653637500508,1653637800435,1,5.180.196.2,5.180.196.6,0,0,595,17255 11 | 1653637500508,1653637800435,1,5.180.196.6,5.180.196.2,0,0,595,17255 12 | 1653637800936,1653638100595,1,5.180.196.2,5.180.196.6,0,0,595,17255 13 | 1653637800937,1653638100595,1,5.180.196.6,5.180.196.2,0,0,595,17255 14 | 1653638101095,1653638111095,1,5.180.196.2,5.180.196.6,0,0,15,3255 15 | 1653638101095,1653638111095,1,5.180.196.6,5.180.196.2,0,0,15,3255 16 | -------------------------------------------------------------------------------- /tools/ft-analyzer/tests/validation/flows/subfields-unexpected.yml: -------------------------------------------------------------------------------- 1 | flows: 2 | - src_ip: "192.168.21.89" 3 | dst_ip: "192.168.197.92" 4 | ip_version: 4 5 | protocol: 17 6 | bytes: 67 7 | bytes@rev: 99 8 | packets: 1 9 | packets@rev: 1 10 | src_port: 40980 11 | dst_port: 53 12 | dns_id: 14402 13 | dns_flags: 0x0100 14 | dns_req_query_type: 1 15 | dns_req_query_class: 1 16 | dns_req_query_name: "newportconceptsla.com" 17 | dns_flags@rev: 0x8180 18 | dns_resp_rcode: 0 19 | dns_resp_rr: 20 | - name: "newportconceptsla.com" 21 | type: 1 22 | class: 1 23 | ttl: 136 24 | data: "192.168.73.162" 25 | - name: "newportconceptsla.com" 26 | type: 1 27 | class: 1 28 | ttl: 136 29 | data: "192.168.215.181" 30 | - name: "newportconceptsla.com" 31 | type: 1 32 | class: 1 33 | ttl: 136 34 | data: "192.168.215.192" 35 | 36 | -------------------------------------------------------------------------------- /tools/ft-replay/src/outputPluginFactoryRegistrator.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @brief Output plugin registration to factory 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "outputPluginFactory.hpp" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace replay { 18 | 19 | /** 20 | * @brief Output plugin registration. 21 | * 22 | * @tparam T Type of class to register 23 | */ 24 | template 25 | struct OutputPluginFactoryRegistrator { 26 | /** 27 | * @brief Register Output plugin to the factory. 28 | * 29 | * @param pluginName Unique plugin name 30 | */ 31 | explicit OutputPluginFactoryRegistrator(const std::string& pluginName) 32 | { 33 | bool inserted; 34 | inserted = OutputPluginFactory::Instance().RegisterPlugin( 35 | pluginName, 36 | [](const std::string& params) -> std::unique_ptr { 37 | return std::make_unique(params); 38 | }); 39 | if (!inserted) { 40 | throw std::runtime_error("Multiple registration of Output plugin: " + pluginName); 41 | } 42 | } 43 | }; 44 | 45 | } // namespace replay 46 | -------------------------------------------------------------------------------- /testing/validation/dns_zone_change.yml: -------------------------------------------------------------------------------- 1 | name: DNS Zone Change Notification Request 2 | description: Check that Zone change notification is parsed properly from DNS Zone 3 | change notification request. 4 | requirements: 5 | protocols: [dns] 6 | marks: [dns] 7 | pcap: dns_zone_change.pcap 8 | probe: 9 | protocols: [dns] 10 | at_least_one: [dns_id, dns_flags, dns_req_query_type, dns_req_query_class, dns_req_query_name, 11 | dns_resp_rr.name, dns_resp_rr.type, dns_resp_rr.class, dns_resp_rr.ttl, dns_resp_rr.data, 12 | dns_resp_rr.flowmon_data] 13 | 14 | flows: 15 | - src_ip: 192.168.3.250 16 | dst_ip: 192.168.74.118 17 | ip_version: 4 18 | protocol: 17 19 | bytes: 105 20 | packets: 1 21 | src_port: 31545 22 | dst_port: 53 23 | dns_id: 51350 24 | _forward: 25 | dns_flags: 0x2400 26 | dns_req_query_type: 6 27 | dns_req_query_class: 1 28 | dns_req_query_name: kkkresort.com 29 | dns_resp_rr: 30 | - name: kkkresort.com 31 | type: 6 32 | class: 1 33 | ttl: 0 34 | data: du.ac vk.me 2020865903 28880 7200 604800 86400 35 | flowmon_data: '0x64752E616320766B2E6D65207873F76F000070D000001C2000093A800001518' 36 | -------------------------------------------------------------------------------- /tools/ft-generator/src/layers/icmprandom.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Michal Sedlak 4 | * @brief ICMP layer planner using random messages 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "../flow.h" 12 | #include "../layer.h" 13 | #include "../packet.h" 14 | #include "../pcpppacket.h" 15 | 16 | #include 17 | 18 | namespace generator { 19 | 20 | /** 21 | * @brief A representation of an IcmpRandom layer. 22 | */ 23 | class IcmpRandom : public Layer { 24 | public: 25 | /** 26 | * @brief Construct a new IcmpRandom object 27 | * 28 | */ 29 | IcmpRandom(); 30 | 31 | /** 32 | * @brief Plan IcmpRandom layer 33 | * 34 | * @param flow Flow to plan. 35 | */ 36 | virtual void PlanFlow(Flow& flow) override; 37 | 38 | /** 39 | * @brief Build IcmpRandom layer in packet 40 | * 41 | * @param packet Packet to build. 42 | * @param params Layers parameters 43 | * @param plan Packet plan. 44 | */ 45 | virtual void Build(PcppPacket& packet, Packet::layerParams& params, Packet& plan) override; 46 | 47 | private: 48 | pcpp::IcmpDestUnreachableCodes _destUnreachableCode; 49 | }; 50 | 51 | } // namespace generator 52 | -------------------------------------------------------------------------------- /tools/ft-profiler/src/ftprofiler/readers/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Author(s): Tomas Jansky 3 | 4 | Copyright: (C) 2022 Flowmon Networks a.s. 5 | SPDX-License-Identifier: BSD-3-Clause 6 | """ 7 | 8 | import argparse 9 | 10 | from .csvfile import CSVFile 11 | from .fdsfile import Fdsfile 12 | from .interface import InputException, InputInterface 13 | from .nffile import Nffile 14 | 15 | flow_readers = [Nffile, CSVFile, Fdsfile] 16 | 17 | 18 | def init_reader(name, args: argparse.Namespace) -> InputInterface: 19 | """Initialize input reader. 20 | 21 | Parameters 22 | ---------- 23 | name : str 24 | Name of the reader. 25 | args : argparse.Namespace 26 | Arguments to be passed to the reader. 27 | 28 | Returns 29 | ------- 30 | InputInterface 31 | Input reader (object) overriding methods of InputInterface abstract class. 32 | 33 | Raises 34 | ------ 35 | InputException 36 | Unknown name of the input reader or error during reader initialization. 37 | """ 38 | 39 | for reader in flow_readers: 40 | if reader.NAME == name: 41 | return reader(args) 42 | 43 | raise InputException(f"Unknown input reader: {name}") 44 | -------------------------------------------------------------------------------- /tools/ft-replay/src/nfbReplicatorCore.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @brief Definition of the NfbReplicatorCore class. 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #include "nfbReplicatorCore.hpp" 10 | 11 | #include 12 | 13 | namespace replay { 14 | 15 | const std::string NfbReplicatorCore::COMPATIBLE_NAME = "cesnet,replicator,app_core"; 16 | 17 | NfbReplicatorCore::NfbReplicatorCore(nfb_device* nfbDevice) 18 | : NfbFirmwareCompoment(COMPATIBLE_NAME, nfbDevice) 19 | { 20 | _coreCount = GetCoreCount(); 21 | } 22 | 23 | size_t NfbReplicatorCore::GetCoreCount() const 24 | { 25 | return _compatible.GetCompatibleCount(); 26 | } 27 | 28 | bool NfbReplicatorCore::IsPresent() const 29 | { 30 | return _coreCount; 31 | } 32 | 33 | bool NfbReplicatorCore::IsChecksumOffloadSupported() const 34 | { 35 | const std::string checksumPropertyName = "checksum_offload"; 36 | size_t propertyCount = _compatible.GetCompatiblePropertyCount(checksumPropertyName); 37 | if (propertyCount != _coreCount) { 38 | _logger->warn("Checksum property is not present in all replicator cores"); 39 | return false; 40 | } 41 | return propertyCount; 42 | } 43 | 44 | } // namespace replay 45 | -------------------------------------------------------------------------------- /ansible/roles/ndk_fw_nic/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Directory where FPGA firmwares are installed 3 | nfb_firmware_dir: /usr/share/ndk-fw 4 | 5 | # FPGA card to configure 6 | # System path to the card. Usually contains "/dev/nfb/{by-pci-slot,by-serial-no}/". 7 | # For example: 8 | # "/dev/nfb0" # Specified by card index 9 | # "/dev/nfb/by-serial-no/NFB-200G2QL/86" # Specified by card type and serial number. 10 | # "/dev/nfb/by-pci-slot/0000:ca:00.0" # Specified by PCI endpoint 11 | nfb_card: "/dev/nfb0" 12 | 13 | # Set MTU (Maximum transmission unit) of Ethernet interfaces 14 | # If empty, no configuration is performed. 15 | nfb_mtu: 9020 16 | 17 | # Set PMA (Physical Medium Attachment) of the Ethernet interface (e.g. LR, SR). 18 | # For possible option see output of `nfb-eth -Pv`. 19 | # If empty, no configuration is performed. 20 | nfb_pma: 21 | 22 | # RSS (Receive Side Scaling) 23 | # Set the range of queues to which packets arriving on the card will be 24 | # distributed. The number of queues must not exceed the number supported 25 | # by the firmware. See "RX queues" in `nfb-info` output. 26 | # For example: To distribute packets to 16 queues, use range 0 - 15. 27 | rss_queue_min: 0 28 | rss_queue_max: 15 29 | -------------------------------------------------------------------------------- /tools/ft-replay/src/replicator-core/ipAddress.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Pavel Siska 4 | * @brief Replicator Ip address 5 | * 6 | * SPDX-License-Identifier: BSD-3-Clause 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace replay { 17 | 18 | /** 19 | * @brief Represent basic operation over IP address pointer 20 | */ 21 | class IpAddressView { 22 | public: 23 | using Ip4Ptr = uint32_t*; 24 | using Ip6Ptr = __int128_t*; 25 | 26 | IpAddressView(Ip4Ptr ip4Ptr) 27 | : _ipPtr(ip4Ptr) 28 | { 29 | } 30 | 31 | IpAddressView(Ip6Ptr ip6Ptr) 32 | : _ipPtr(ip6Ptr) 33 | { 34 | } 35 | 36 | IpAddressView operator+=(uint32_t value) 37 | { 38 | if (IsIp4()) { 39 | Ip4Ptr ip = std::get(_ipPtr); 40 | *ip = htonl(ntohl(*ip) + value); 41 | } else { 42 | Ip6Ptr ip = std::get(_ipPtr); 43 | uint32_t* ipAs32b = reinterpret_cast(ip); 44 | ipAs32b[0] = htonl(ntohl(ipAs32b[0]) + value); 45 | } 46 | return *this; 47 | } 48 | 49 | private: 50 | std::variant _ipPtr; 51 | 52 | bool IsIp4() { return std::holds_alternative(_ipPtr); } 53 | }; 54 | 55 | } // namespace replay 56 | -------------------------------------------------------------------------------- /testing/validation/dns_cname.yml: -------------------------------------------------------------------------------- 1 | name: DNS CNAME Request 2 | description: Check that the canonical name from DNS response to CNAME request is present 3 | in the flow. 4 | requirements: 5 | protocols: [dns] 6 | marks: [dns] 7 | pcap: dns_cname.pcap 8 | probe: 9 | protocols: [dns] 10 | at_least_one: [dns_id, dns_flags, dns_req_query_type, dns_req_query_class, dns_req_query_name, 11 | dns_resp_rcode, dns_resp_rr.name, dns_resp_rr.type, dns_resp_rr.class, dns_resp_rr.ttl, 12 | dns_resp_rr.data, dns_resp_rr.flowmon_data] 13 | 14 | flows: 15 | - src_ip: 192.168.233.84 16 | dst_ip: 192.168.179.148 17 | ip_version: 4 18 | protocol: 17 19 | bytes: 62 20 | bytes@rev: 87 21 | packets: 1 22 | packets@rev: 1 23 | src_port: 59961 24 | dst_port: 53 25 | dns_id: 38661 26 | _forward: 27 | dns_flags: 0x0100 28 | dns_req_query_type: 5 29 | dns_req_query_class: 1 30 | dns_req_query_name: se-ssl-cloud.com 31 | _reverse: 32 | dns_flags: 0x8180 33 | dns_resp_rcode: 0 34 | dns_resp_rr: 35 | - name: se-ssl-cloud.com 36 | type: 5 37 | class: 1 38 | ttl: 300 39 | data: glaston.net 40 | flowmon_data: '0x676C6173746F6E2E6E6574' 41 | --------------------------------------------------------------------------------