From 54da2b6cad25cbf5e5cbc9a1ee36e7c0f6f79480 Mon Sep 17 00:00:00 2001 From: Pavel Odintsov Date: Mon, 4 Apr 2022 15:30:23 +0100 Subject: [PATCH] Deprecated PF_RING plugin for new versions. We switched to AF_PACKET which is compeltely open source and worse way better (#929) --- README.md | 5 +- debian/rules | 2 +- src/CMakeLists.txt | 48 +- src/Dockerfile | 2 +- src/FreeBSD_port/pkg-descr | 3 +- src/fast_library.cpp | 2 +- src/fastnetmon.conf | 14 +- src/fastnetmon.cpp | 10 - src/fastnetmon_build.pl | 150 ----- src/fastnetmon_centos6.spec | 13 +- src/fastnetmon_centos7.spec | 11 +- src/fastnetmon_fedora12.spec | 7 +- src/fastnetmon_logic.cpp | 10 - src/man/fastnetmon.1 | 2 +- src/pfring_plugin/pfring_collector.cpp | 767 ------------------------- src/pfring_plugin/pfring_collector.h | 10 - src/plugin_runner.cpp | 13 +- src/scripts/build_any_package.pl | 6 +- src/scripts/build_libary_bundle.pl | 8 +- src/tests/pfring_parser_zc_issue.c | 78 --- src/tests/spsc_prototype.cpp | 6 +- 21 files changed, 26 insertions(+), 1141 deletions(-) delete mode 100644 src/pfring_plugin/pfring_collector.cpp delete mode 100644 src/pfring_plugin/pfring_collector.h delete mode 100644 src/tests/pfring_parser_zc_issue.c diff --git a/README.md b/README.md index 42b1102..6ab4f94 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ perform a configurable action to handle that event. These configurable actions i Flow is one or more ICMP, UDP, or TCP packets which can be identified via their unique src IP, dst IP, src port, dst port, and protocol fields. -![CI status](https://circleci.com/gh/pavel-odintsov/fastnetmon.svg) [CI status](https://app.circleci.com/pipelines/github/pavel-odintsov/fastnetmon) +![CI status](https://circleci.com/gh/pavel-odintsov/fastnetmon.svg) +[CI status](https://app.circleci.com/pipelines/github/pavel-odintsov/fastnetmon) Project ------- @@ -28,7 +29,7 @@ Supported packet capture engines - PCAP - AF_PACKET - Netmap -- PF_RING / PF_RING ZC (available only for CentOS 6 for compatibiliy, otherwise use AF_PACKET) +- PF_RING / PF_RING ZC (CentOS 6 only) You can check out the [comparison table](https://fastnetmon.com/docs/capture_backends/) for all available packet capture engines. diff --git a/debian/rules b/debian/rules index d408eec..38d2e16 100755 --- a/debian/rules +++ b/debian/rules @@ -2,4 +2,4 @@ %: dh $@ --buildsystem=cmake --sourcedirectory=src override_dh_auto_configure: - dh_auto_configure -- -DDISABLE_PF_RING_SUPPORT=yes + dh_auto_configure -- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aeda0a9..514198b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,7 +27,6 @@ set (FASTNETMON_VERSION_MINOR 1) set(HIREDIS_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13") set(LOG4CPP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1") set(JSONC_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13") -set(PFRING_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/pf_ring_6.0.3") set(LIBPCAP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libpcap_1.7.4") set(MONGO_C_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/mongo_c_driver_1_16_1") set(CAPNP_CUSTOM_INSTALL_PATH "${FASTNETMON_LIBRARIES_GLOBAL_PATH}/capnproto_0_8_0") @@ -87,7 +86,7 @@ SET(CMAKE_SKIP_BUILD_RPATH FALSE) # Create builds in current folder with install RPATH SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/pf_ring_6.0.3/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib64;${GRPC_CUSTOM_INSTALL_PATH}/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/protobuf_3.11.4/lib;${CAPNP_CUSTOM_INSTALL_PATH}/lib;${OPENSSL_CUSTOM_INSTALL_PATH}/lib") +SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${FASTNETMON_LIBRARIES_GLOBAL_PATH}/libhiredis_0_13/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/log4cpp1.1.1/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/json-c-0.13/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib;${MONGO_C_CUSTOM_INSTALL_PATH}/lib64;${GRPC_CUSTOM_INSTALL_PATH}/lib;${FASTNETMON_LIBRARIES_GLOBAL_PATH}/protobuf_3.11.4/lib;${CAPNP_CUSTOM_INSTALL_PATH}/lib;${OPENSSL_CUSTOM_INSTALL_PATH}/lib") message(STATUS "C++ compilation flags: ${CMAKE_CXX_FLAGS_RELEASE}") message(STATUS "C++ debug compilation flags: ${CMAKE_CXX_FLAGS_DEBUG}") @@ -145,9 +144,6 @@ if (NOT HAVE__ATOMIC_ADD_FETCH) endif() endif() -# With this flag we can enable PF_RING build via console: cmake .. -DENABLE_PF_RING_SUPPORT=ON -option(ENABLE_PF_RING_SUPPORT "Enable PF_RING build" OFF) - option(ENABLE_NETMAP_SUPPORT "Enable Netmap support" ON) CHECK_CXX_SOURCE_COMPILES(" @@ -169,32 +165,6 @@ if (ENABLE_NETMAP_SUPPORT) add_definitions(-DNETMAP_PLUGIN) endif() -if (ENABLE_PF_RING_SUPPORT) - # Set path to manually compiled PF_RING - set(PFRING_INCLUDE_DIRS "${PFRING_CUSTOM_INSTALL_PATH}/include") - - find_library(PFRING_LIBRARIES NAMES pfring PATHS "${PFRING_CUSTOM_INSTALL_PATH}/lib" NO_DEFAULT_PATH) - - if (NOT PFRING_LIBRARIES) - message(FATAL_ERROR "Could not find PF_RING") - endif() - - link_directories("${PFRING_CUSTOM_INSTALL_PATH}/lib") - add_definitions(-DPF_RING) - - if (EXISTS "${PFRING_CUSTOM_INSTALL_PATH}/include/pfring_zc.h" OR EXISTS "/usr/local/include/pfring_zc.h") - message(STATUS "We found PF_RING ZC headers and will build PF_RING ZC support") - # Enable ZC support - add_definitions(-DPF_RING_ZC) - else() - message(WARNING "We can't find PF_RING ZC header pfring_zc.h. Will not compile ZC support") - endif() - - include_directories(${PFRING_INCLUDE_DIRS}) - - message(STATUS "We have enabled PF_RING's hardware filtering option") -endif() - add_library(simple_packet_capnp STATIC simple_packet_capnp/simple_packet.capnp.c++) # Our LPM library @@ -283,13 +253,6 @@ target_link_libraries(pcap_plugin pcap) find_package(Threads) -if (ENABLE_PF_RING_SUPPORT) - add_library(pfring_plugin STATIC pfring_plugin/pfring_collector.cpp) - target_link_libraries(pfring_plugin ${PFRING_LIBRARIES}) - target_link_libraries(pfring_plugin numa) - target_link_libraries(pfring_plugin ${CMAKE_THREAD_LIBS_INIT}) -endif() - add_library(exabgp_action STATIC actions/exabgp_action.cpp) if (ENABLE_GOBGP_SUPPORT) @@ -593,10 +556,6 @@ target_link_libraries(fastnetmon fast_library) # link to our unified parser target_link_libraries(fastnetmon unified_parser) -if (ENABLE_PF_RING_SUPPORT) - target_link_libraries(fastnetmon pfring_plugin) -endif() - target_link_libraries(fastnetmon ${OPENSSL_LIBRARY_PATH}) target_link_libraries(fastnetmon ${OPENSSL_CRYPTO_LIBRARY_PATH}) @@ -638,11 +597,6 @@ if (BUILD_PLUGIN_RUNNER) if (ENABLE_NETMAP_SUPPORT) target_link_libraries(fastnetmon_plugin_runner netmap_plugin) endif() - - if (ENABLE_PF_RING_SUPPORT) - target_link_libraries(fastnetmon_plugin_runner ${PFRING_LIBRARIES}) - target_link_libraries(fastnetmon_plugin_runner pfring_plugin) - endif() endif() # cmake .. -DBUILD_PCAP_READER=ON diff --git a/src/Dockerfile b/src/Dockerfile index 9bccd1e..0bf5d80 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -32,7 +32,7 @@ RUN cd /usr/src; git clone https://github.com/pavel-odintsov/fastnetmon.git #COPY exabgp_blackhole.conf /etc/exabgp_blackhole.conf -RUN cd /usr/src/fastnetmon/src; mkdir build; cd build; cmake .. -DDISABLE_PF_RING_SUPPORT=ON; make +RUN cd /usr/src/fastnetmon/src; mkdir build; cd build; cmake ..; make RUN cp /usr/src/fastnetmon/src/fastnetmon.conf /etc/ RUN cp /usr/src/fastnetmon/src/build/fastnetmon /usr/bin/ diff --git a/src/FreeBSD_port/pkg-descr b/src/FreeBSD_port/pkg-descr index ffffc65..33ec8a2 100644 --- a/src/FreeBSD_port/pkg-descr +++ b/src/FreeBSD_port/pkg-descr @@ -1,5 +1,4 @@ FastNetMon - A high performance DoS/DDoS load analyzer built on top -of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, -PF_RING, PCAP). +of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). WWW: https://fastnetmon.com diff --git a/src/fast_library.cpp b/src/fast_library.cpp index cc8a173..6be613b 100644 --- a/src/fast_library.cpp +++ b/src/fast_library.cpp @@ -449,7 +449,7 @@ std::string print_simple_packet(simple_packet_t packet) { std::stringstream buffer; if (packet.ts.tv_sec == 0) { - // PF_RING and netmap do not generate timestamp for all packets because it's very CPU + // Netmap does not generate timestamp for all packets because it's very CPU // intensive operation // But we want pretty attack report and fill it there gettimeofday(&packet.ts, NULL); diff --git a/src/fastnetmon.conf b/src/fastnetmon.conf index 031ed00..2a44031 100644 --- a/src/fastnetmon.conf +++ b/src/fastnetmon.conf @@ -86,12 +86,6 @@ ban_for_icmp_pps = off ### Traffic capture methods ### -# PF_RING traffic capture, fast enough but the wirespeed version needs a paid license -mirror = off - -# Port mirroring sample rate -pfring_sampling_ratio = 1 - # Netmap traffic capture (very fast but needs patched drivers) mirror_netmap = off @@ -124,13 +118,9 @@ netflow = off # sFLOW capture suitable for switches sflow = off -# PF_RING configuration -# If you have a license for PF_RING ZC, enable this mode and it might achieve wire speed for 10GE -enable_pf_ring_zc_mode = off - # Configuration for netmap, mirror, pcap modes -# For pcap and PF_RING we could specify "any" -# For netmap and PF_RING we could specify multiple interfaces separated by comma +# For pcap we could specify "any" +# For Netmap we could specify multiple interfaces separated by comma interfaces = eth3,eth4 # We use average values for traffic speed to certain IP and we calculate average over this time slice diff --git a/src/fastnetmon.cpp b/src/fastnetmon.cpp index 7d270fe..394ca10 100644 --- a/src/fastnetmon.cpp +++ b/src/fastnetmon.cpp @@ -62,10 +62,6 @@ #include "netmap_plugin/netmap_collector.h" #endif -#ifdef PF_RING -#include "pfring_plugin/pfring_collector.h" -#endif - #ifdef FASTNETMON_ENABLE_AFPACKET #include "afpacket_plugin/afpacket_collector.h" #endif @@ -1690,12 +1686,6 @@ int main(int argc, char** argv) { set_boost_process_name(check_traffic_buckets_thread, "check_buckets"); service_thread_group.add_thread(check_traffic_buckets_thread); -#ifdef PF_RING - if (enable_data_collection_from_mirror) { - packet_capture_plugin_thread_group.add_thread(new boost::thread(start_pfring_collection, process_packet)); - } -#endif - #ifdef NETMAP_PLUGIN // netmap processing if (enable_netmap_collection) { diff --git a/src/fastnetmon_build.pl b/src/fastnetmon_build.pl index 8e09981..05f2982 100755 --- a/src/fastnetmon_build.pl +++ b/src/fastnetmon_build.pl @@ -56,10 +56,6 @@ sub fast_die { exit(1); } -my $pf_ring_version = '6.0.3'; -my $pf_ring_url = "https://github.com/ntop/PF_RING/archive/v$pf_ring_version.tar.gz"; -my $pf_ring_sha = '9fb8080defd1a079ad5f0097e8a8adb5bc264d00'; - my $fastnetmon_git_path = 'https://github.com/pavel-odintsov/fastnetmon.git'; my $temp_folder_for_building_project = `mktemp -d /tmp/fastnetmon.build.dir.XXXXXXXXXX`; @@ -91,8 +87,6 @@ my $make_options = ''; # We could pass options to configure with this variable my $configure_options = ''; -my $use_modern_pf_ring = ''; - my $show_help = ''; my $install_dependency_packages_only = ''; @@ -106,7 +100,6 @@ my $build_dependencies_only = ''; # Get options from command line GetOptions( 'use-git-master' => \$we_use_code_from_master, - 'use-modern-pf-ring' => \$use_modern_pf_ring, 'use-mirror' => \$use_mirror, 'build_fastnetmon_only' => \$build_fastnetmon_only, 'build_dependencies_only' => \$build_dependencies_only, @@ -129,13 +122,6 @@ if ($show_help) { welcome_message(); -# Bump PF_RING version -if ($use_modern_pf_ring) { - $pf_ring_version = '6.6.0'; - $pf_ring_url = "https://github.com/ntop/PF_RING/archive/$pf_ring_version.tar.gz"; - $pf_ring_sha = '79ff86e48df857e4e884646accfc97bdcdc54b04'; -} - my $we_have_hiredis_support = '1'; my $we_have_log4cpp_support = '1'; my $we_have_mongo_support = '1'; @@ -143,9 +129,6 @@ my $we_have_protobuf_support = '1'; my $we_have_grpc_support = '1'; my $we_have_gobgp_support = '1'; -# We allow it only for legacy systems -my $we_have_pfring_support = ''; - main(); # Applies colors to terminal if we have this module @@ -290,17 +273,6 @@ sub main { } } - # We use PF_RING only for very old Linux distros, all new one should use AF_PACKET - if ($os_type eq 'linux') { - if ($distro_type eq 'ubuntu' && $distro_version =~ m/^12\.04/) { - $we_have_pfring_support = 1; - } - - if ($distro_type eq 'centos' && $distro_version == 6) { - $we_have_pfring_support = 1; - } - } - # CentOS base repository is very very poor and we need EPEL for some dependencies install_additional_repositories(); @@ -329,10 +301,6 @@ sub main { # Install only depencdency packages, we need it to cache installed packages in CI if ($install_dependency_packages_only) { - if ($we_have_pfring_support) { - install_pf_ring_dependencies(); - } - if ($we_have_protobuf_support) { install_protobuf_dependencies(); } @@ -347,11 +315,6 @@ sub main { } if ($build_dependencies_only) { - if ($we_have_pfring_support) { - install_pf_ring_dependencies(); - install_pf_ring(); - } - install_json_c(); install_openssl(); @@ -1049,110 +1012,6 @@ sub detect_distribution { } } -sub install_pf_ring_dependencies { - my $kernel_version = `uname -r`; - chomp $kernel_version; - - print "Install PF_RING dependencies with package manager\n"; - - if ($distro_type eq 'debian' or $distro_type eq 'ubuntu') { - my @debian_packages_for_pfring = ('build-essential', 'bison', 'flex', 'subversion', - 'libnuma-dev', 'wget', 'tar', 'make', 'dpkg-dev', 'dkms', 'debhelper'); - - # Install kernel headers only when we could compile kernel modules there - my $kernel_headers_package_name = "linux-headers-$kernel_version"; - - push @debian_packages_for_pfring, $kernel_headers_package_name; - - apt_get(@debian_packages_for_pfring); - } elsif ($distro_type eq 'centos') { - my @centos_dependency_packages = ('make', 'bison', 'flex', 'gcc', 'gcc-c++', 'dkms', 'numactl-devel', 'subversion'); - - # This package is not going to install devel headers for current kernel! - my $kernel_package_name = 'kernel-devel'; - - # Fix deplist for OpenVZ - if ($kernel_version =~ /stab/) { - $kernel_package_name = "vzkernel-devel-$kernel_version"; - } - - push @centos_dependency_packages, $kernel_package_name; - - my $centos_kernel_version = `uname -r`; - chomp $centos_kernel_version; - - # But this package will install kernel devel headers for current kernel version! - push @centos_dependency_packages, "$kernel_package_name-$centos_kernel_version"; - - yum(@centos_dependency_packages); - } -} - -sub install_pf_ring { - my $pf_ring_archive_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version.tar.gz"; - my $pf_ring_sources_path = "$temp_folder_for_building_project/PF_RING-$pf_ring_version"; - - my $pf_ring_install_path = "$library_install_folder/pf_ring_$pf_ring_version"; - - if (-e $pf_ring_install_path) { - print "PF_RING was already installed\n"; - return 1; - } - - # Sometimes we do not want to build kernel module (Docker, KVM and other cases) - my $we_could_install_kernel_modules = 1; - - if ($we_could_install_kernel_modules) { - print "Download PF_RING $pf_ring_version sources\n"; - my $pfring_download_result = download_file($pf_ring_url, $pf_ring_archive_path, $pf_ring_sha); - - unless ($pfring_download_result) { - fast_die("Can't download PF_RING sources"); - } - - my $archive_file_name = $pf_ring_archive_path; - - if ($? == 0) { - print "Unpack PF_RING\n"; - mkdir $pf_ring_sources_path; - exec_command("tar -xf $pf_ring_archive_path -C $temp_folder_for_building_project"); - - print "Build PF_RING kernel module\n"; - exec_command("make $make_options -C $pf_ring_sources_path/kernel clean"); - exec_command("make $make_options -C $pf_ring_sources_path/kernel"); - exec_command("make $make_options -C $pf_ring_sources_path/kernel install"); - - print "Unload PF_RING if it was installed earlier\n"; - exec_command("rmmod pf_ring 2>/dev/null"); - - print "Load PF_RING module into kernel\n"; - exec_command("modprobe pf_ring"); - - my @dmesg = `dmesg`; - chomp @dmesg; - - if (scalar grep (/\[PF_RING\] Initialized correctly/, @dmesg) > 0) { - print "PF_RING loaded correctly\n"; - - } else { - warn "PF_RING load error! Please fix this issue manually\n"; - - # We need this headers for building userspace libs - exec_command("cp $pf_ring_sources_path/kernel/linux/pf_ring.h /usr/include/linux"); - } - } else { - warn "Can't download PF_RING source code. Disable support of PF_RING\n"; - } - } - - print "Build PF_RING lib\n"; - # Because we can't run configure from another folder because it can't find ZC dependency :( - chdir "$pf_ring_sources_path/userland/lib"; - exec_command("$configure_options ./configure --prefix=$pf_ring_install_path"); - exec_command("make $make_options"); - exec_command("make $make_options install"); -} - sub apt_get { my @packages_list = @_; @@ -1714,21 +1573,12 @@ sub install_fastnetmon { my $cmake_params = ""; - if ($we_have_pfring_support) { - $cmake_params .= " -DENABLE_PF_RING_SUPPORT=ON"; - } - if ($distro_type eq 'centos' && $distro_version == 6) { # Disable cmake script from Boost package because it's broken: # http://public.kitware.com/Bug/view.php?id=15270 $cmake_params .= " -DBoost_NO_BOOST_CMAKE=BOOL:ON"; } - # Bump version in cmake build system - if ($use_modern_pf_ring) { - system("sed -i 's/pf_ring_6.0.3/pf_ring_$pf_ring_version/' ../CMakeLists.txt") - } - # Fix dependencies for Netmap in 1.1.4 if ($distro_type eq 'centos' && int($distro_version) == 6) { system("sed -i 's/netmap_plugin fastnetmon_packet_parser/netmap_plugin fastnetmon_packet_parser unified_parser/' ../CMakeLists.txt") diff --git a/src/fastnetmon_centos6.spec b/src/fastnetmon_centos6.spec index 458657a..54958b1 100644 --- a/src/fastnetmon_centos6.spec +++ b/src/fastnetmon_centos6.spec @@ -11,7 +11,7 @@ Name: fastnetmon Version: 1.1.1 Release: 1%{?dist} -Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). Group: System Environment/Daemons License: GPLv2 URL: https://fastnetmon.com @@ -20,13 +20,9 @@ URL: https://fastnetmon.com #Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz -# Yes, it's bad idea to specify fixed version of PF_RING but they have strange issue when we use another library version - BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake -BuildRequires: pfring >= 6.0.3-9154 -Requires: pfring >= 6.0.3-9154 Requires: log4cpp, daemonize, libpcap, boost-thread, boost-thread, boost-regex Requires(pre): shadow-utils Requires(post): chkconfig @@ -36,7 +32,7 @@ Provides: fastnetmon %description A high performance DoS/DDoS load analyzer built on top of multiple packet capture -engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). %prep # For production @@ -49,10 +45,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). cd src mkdir build cd build -# You could disable PF_RING support with param: -DDISABLE_PF_RING_SUPPORT=ON -# WE have broken cmake library with Boost on CentOS 6 and should use library from cmake -# http://public.kitware.com/Bug/view.php?id=15270 -cmake .. -DWE_USE_PFRING_FROM_NTOP=ON -DBoost_NO_BOOST_CMAKE=BOOL:ON +cmake .. -DBoost_NO_BOOST_CMAKE=BOOL:ON make %install diff --git a/src/fastnetmon_centos7.spec b/src/fastnetmon_centos7.spec index 662cb53..e209925 100644 --- a/src/fastnetmon_centos7.spec +++ b/src/fastnetmon_centos7.spec @@ -11,7 +11,7 @@ Name: fastnetmon Version: 1.1.1 Release: 1%{?dist} -Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). Group: System Environment/Daemons License: GPLv2 URL: https://fastnetmon.com @@ -20,14 +20,10 @@ URL: https://fastnetmon.com #Source0: https://github.com/pavel-odintsov/fastnetmon/archive/v%{version}.tar.gz Source0: https://github.com/pavel-odintsov/fastnetmon/archive/fastnetmon-%{version}.tar.gz -# Yes, it's bad idea to specify fixed version of PF_RING but they have strange issue when we use another library version - BuildRequires: git, make, gcc, gcc-c++, boost-devel, GeoIP-devel, log4cpp-devel BuildRequires: ncurses-devel, boost-thread, boost-regex, libpcap-devel, gpm-devel, clang, cmake -BuildRequires: pfring >= 6.0.3-9154 BuildRequires: systemd -Requires: pfring >= 6.0.3-9154 Requires: log4cpp, libpcap, boost-thread, boost-thread, boost-regex Requires(pre): shadow-utils Requires(post): systemd @@ -38,7 +34,7 @@ Provides: fastnetmon %description A high performance DoS/DDoS load analyzer built on top of multiple packet capture -engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +engines (NetFlow, IPFIX, sFLOW, netmap, PCAP). %prep # For production @@ -51,8 +47,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). cd src mkdir build cd build -# You could disable PF_RING support with param: -DDISABLE_PF_RING_SUPPORT=ON -cmake .. -DWE_USE_PFRING_FROM_NTOP=ON +cmake .. make %install diff --git a/src/fastnetmon_fedora12.spec b/src/fastnetmon_fedora12.spec index b57dde7..eb893cf 100644 --- a/src/fastnetmon_fedora12.spec +++ b/src/fastnetmon_fedora12.spec @@ -11,7 +11,7 @@ Name: fastnetmon Version: 1.1.1 Release: 1%{?dist} -Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). Group: System Environment/Daemons License: GPLv2 URL: https://fastnetmon.com @@ -32,7 +32,7 @@ Provides: fastnetmon %description A high performance DoS/DDoS load analyzer built on top of multiple packet capture -engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). %prep %setup -n %{name}-%{fastnetmon_commit} @@ -41,8 +41,7 @@ engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). cd src mkdir build cd build -# We should disable PF_RING plugon support because we did not have it in repository -cmake .. -DDISABLE_PF_RING_SUPPORT=ON +cmake .. make %install diff --git a/src/fastnetmon_logic.cpp b/src/fastnetmon_logic.cpp index 87b42c8..b633f49 100644 --- a/src/fastnetmon_logic.cpp +++ b/src/fastnetmon_logic.cpp @@ -20,10 +20,6 @@ #include "netmap_plugin/netmap_collector.h" #endif -#ifdef PF_RING -#include "pfring_plugin/pfring_collector.h" -#endif - #ifdef FASTNETMON_ENABLE_AFPACKET #include "afpacket_plugin/afpacket_collector.h" #endif @@ -1982,12 +1978,6 @@ void traffic_draw_ipv4_program() { output_buffer << get_pcap_stats() << "\n"; } -#ifdef PF_RING - if (enable_data_collection_from_mirror) { - output_buffer << get_pf_ring_stats(); - } -#endif - if (!ban_list.empty()) { output_buffer << std::endl << "Ban list:" << std::endl; output_buffer << print_ddos_attack_details(); diff --git a/src/man/fastnetmon.1 b/src/man/fastnetmon.1 index 10523b4..e48da35 100644 --- a/src/man/fastnetmon.1 +++ b/src/man/fastnetmon.1 @@ -6,7 +6,7 @@ FastNetMon \- a high performance DoS/DDoS load analyzer built on top of multiple .SH SYNOPSIS fastnetmon [--daemonize] .SH DESCRIPTION -FastNetMon - a high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +FastNetMon - a high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). For more information about configuration, please look at the comments in /etc/fastnetmon.conf and check the project GitHub page: https://github.com/pavel-odintsov/fastnetmon. .SH OPTIONS diff --git a/src/pfring_plugin/pfring_collector.cpp b/src/pfring_plugin/pfring_collector.cpp deleted file mode 100644 index 85a0395..0000000 --- a/src/pfring_plugin/pfring_collector.cpp +++ /dev/null @@ -1,767 +0,0 @@ -// log4cpp logging facility -#include "log4cpp/Appender.hh" -#include "log4cpp/BasicLayout.hh" -#include "log4cpp/Category.hh" -#include "log4cpp/FileAppender.hh" -#include "log4cpp/Layout.hh" -#include "log4cpp/OstreamAppender.hh" -#include "log4cpp/PatternLayout.hh" -#include "log4cpp/Priority.hh" - -#include "../fast_library.h" - -// For support uint32_t, uint16_t -#include - -#include -#include - -// For config map operations -#include -#include - -// For support: IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_UDP -#include -#include -#include - -#include "pfring_collector.h" - -#include "pfring.h" - -#ifdef PF_RING_ZC -#include "pfring_zc.h" -#endif - -#include - -uint32_t pfring_sampling_ratio = 1; - -// Get log4cpp logger from main program -extern log4cpp::Category& logger; - -extern uint64_t total_unparsed_packets; - -// Global configuration map -extern std::map configuration_map; - -// Interface name or interface list (delimitered by comma) -std::string work_on_interfaces = ""; - -// This variable name should be uniq for every plugin! -process_packet_pointer pfring_process_func_ptr = NULL; - -// We can look inside L2TP packets with IP encapsulation -// And do it by default -bool do_unpack_l2tp_over_ip = true; - -// Variable from PF_RING multi channel mode -int num_pfring_channels = 0; - -// We can use software or hardware (in kernel module) packet parser -bool we_use_pf_ring_in_kernel_parser = true; - -// By default we pool PF_RING on one thread -bool enable_pfring_multi_channel_mode = false; - -struct thread_stats { - u_int64_t __padding_0[8]; - - u_int64_t numPkts; - u_int64_t numBytes; - - pfring* ring; - pthread_t pd_thread; - int core_affinity; - - volatile u_int64_t do_shutdown; - - u_int64_t __padding_1[3]; -}; - -struct thread_stats* threads; -pfring* pf_ring_descr = NULL; - - -// We can use ZC api -bool pf_ring_zc_api_mode = false; - -#ifdef PF_RING_ZC -u_int32_t zc_num_threads = 0; -pthread_t* zc_threads; -pfring_zc_cluster* zc; -pfring_zc_worker* zw; -pfring_zc_queue** inzq; -pfring_zc_queue** outzq; -pfring_zc_multi_queue* outzmq; /* fanout */ -pfring_zc_buffer_pool* wsp; -pfring_zc_pkt_buff** buffers; -#endif - -// Prototypes -#ifdef PF_RING_ZC -bool zc_main_loop(const char* device); -#endif - -bool pf_ring_main_loop(const char* dev); -bool pf_ring_main_loop_multi_channel(const char* dev); -void* pf_ring_packet_consumer_thread(void* _id); -void pfring_main_packet_process_task(); - -void start_pfring_collection(process_packet_pointer func_ptr) { - logger << log4cpp::Priority::INFO << "PF_RING plugin started"; - pfring_process_func_ptr = func_ptr; - -#ifdef PF_RING_ZC - if (configuration_map.count("enable_pf_ring_zc_mode")) { - if (configuration_map["enable_pf_ring_zc_mode"] == "on") { - pf_ring_zc_api_mode = true; - } else { - pf_ring_zc_api_mode = false; - } - } -#endif - - if (configuration_map.count("interfaces") != 0) { - work_on_interfaces = configuration_map["interfaces"]; - - // We should check all interfaces and check zc flag for all - if (work_on_interfaces.find("zc:") != std::string::npos) { - we_use_pf_ring_in_kernel_parser = false; - logger << log4cpp::Priority::INFO - << "We detect run in PF_RING Zero Copy or DNA mode and we enable packet parser!"; - } - - logger << log4cpp::Priority::INFO << "We selected interface:" << work_on_interfaces; - } - - if (configuration_map.count("pfring_sampling_ratio") != 0) { - pfring_sampling_ratio = - convert_string_to_integer(configuration_map["pfring_sampling_ratio"]); - } - - if (work_on_interfaces == "") { - logger << log4cpp::Priority::ERROR << "Please specify interface"; - exit(1); - } - - pfring_main_packet_process_task(); -} - - -void stop_pfring_collection() { - pfring_breakloop(pf_ring_descr); -} - -void parse_packet_pf_ring(const struct pfring_pkthdr* h, const u_char* p, const u_char* user_bytes) { - // Description of all fields: http://www.ntop.org/pfring_api/structpkt__parsing__info.html - simple_packet_t packet; - - // We pass only one packet to processing - packet.number_of_packets = 1; - - // Now we support only non sampled input from PF_RING - packet.sample_ratio = pfring_sampling_ratio; - - if (!pf_ring_zc_api_mode) { - if (!we_use_pf_ring_in_kernel_parser) { - // In ZC (zc:eth0) mode you should manually add packet parsing here - // Because it disabled by default: "parsing already disabled in zero-copy" - // http://www.ntop.org/pfring_api/pfring_8h.html - // Parse up to L3, no timestamp, no hashing - // 1 - add timestamp, 0 - disable hash - - // We should zeroify packet header because PFRING ZC did not do this! - memset((void*)&h->extended_hdr.parsed_pkt, 0, sizeof(h->extended_hdr.parsed_pkt)); - - // We do not calculate timestamps here because it's useless and consumes so much cpu - // https://github.com/ntop/PF_RING/issues/9 - u_int8_t timestamp = 0; - u_int8_t add_hash = 0; - pfring_parse_pkt((u_char*)p, (struct pfring_pkthdr*)h, 4, timestamp, add_hash); - } - } - - if (do_unpack_l2tp_over_ip) { - // 2014-12-08 13:36:53,537 [INFO] [00:1F:12:84:E2:E7 -> 90:E2:BA:49:85:C8] - // [IPv4][5.254.105.102:0 -> 159.253.17.251:0] - // [l3_proto=115][hash=2784721876][tos=32][tcp_seq_num=0] - // [caplen=128][len=873][parsed_header_len=0][eth_offset=-14][l3_offset=14][l4_offset=34][payload_offset=0] - // L2TP has an proto number 115 - if (h->extended_hdr.parsed_pkt.l3_proto == 115) { - // pfring_parse_pkt expects that the hdr memory is either zeroed or contains valid - // values - // for the current packet, in order to avoid parsing twice the same packet headers. - struct pfring_pkthdr l2tp_header; - memset(&l2tp_header, 0, sizeof(l2tp_header)); - - int16_t l4_offset = h->extended_hdr.parsed_pkt.offset.l4_offset; - - // L2TP has two headers: L2TP and default L2-Specific Sublayer: every header for 4bytes - int16_t l2tp_header_size = 8; - l2tp_header.len = h->len - (l4_offset + l2tp_header_size); - l2tp_header.caplen = h->caplen - (l4_offset + l2tp_header_size); - - const u_char* l2tp_tunnel_payload = p + l4_offset + l2tp_header_size; - // 1 - add timestamp, 0 - disable hash - pfring_parse_pkt((u_char*)l2tp_tunnel_payload, &l2tp_header, 4, 1, 0); - - // Copy data back - // TODO: it's not fine solution and I should redesign this code - memcpy((struct pfring_pkthdr*)h, &l2tp_header, sizeof(l2tp_header)); - - // TODO: Global pfring_print_parsed_pkt can fail because we did not shift 'p' pointer - - // Uncomment this line for deep inspection of all packets - /* - char buffer[512]; - pfring_print_parsed_pkt(buffer, 512, l2tp_tunnel_payload, h); - logger<extended_hdr.parsed_pkt.ip_version != 4 && h->extended_hdr.parsed_pkt.ip_version != 6) { - total_unparsed_packets++; - return; - } - - packet.ip_protocol_version = h->extended_hdr.parsed_pkt.ip_version; - - if (packet.ip_protocol_version == 4) { - // IPv4 - - /* PF_RING stores data in host byte order but we use network byte order */ - packet.src_ip = htonl(h->extended_hdr.parsed_pkt.ip_src.v4); - packet.dst_ip = htonl(h->extended_hdr.parsed_pkt.ip_dst.v4); - } else { - // IPv6 - - memcpy(packet.src_ipv6.s6_addr, h->extended_hdr.parsed_pkt.ip_src.v6.s6_addr, 16); - memcpy(packet.dst_ipv6.s6_addr, h->extended_hdr.parsed_pkt.ip_dst.v6.s6_addr, 16); - } - - - packet.source_port = h->extended_hdr.parsed_pkt.l4_src_port; - packet.destination_port = h->extended_hdr.parsed_pkt.l4_dst_port; - - // We need this for deep packet inspection - packet.packet_payload_length = h->len; - packet.packet_payload_pointer = (void*)p; - - packet.length = h->len; - packet.protocol = h->extended_hdr.parsed_pkt.l3_proto; - packet.ts = h->ts; - - // Copy flags from PF_RING header to our pseudo header - if (packet.protocol == IPPROTO_TCP) { - packet.flags = h->extended_hdr.parsed_pkt.tcp.flags; - } else { - packet.flags = 0; - } - - pfring_process_func_ptr(packet); -} - - -// Main worker thread for packet handling -void pfring_main_packet_process_task() { - const char* device_name = work_on_interfaces.c_str(); - - bool pf_ring_init_result = false; - - if (pf_ring_zc_api_mode) { -#ifdef PF_RING_ZC - pf_ring_init_result = zc_main_loop((char*)device_name); -#else - logger << log4cpp::Priority::ERROR << "PF_RING library hasn't ZC support, please try SVN version"; -#endif - } else { - if (enable_pfring_multi_channel_mode) { - pf_ring_init_result = pf_ring_main_loop_multi_channel(device_name); - } else { - pf_ring_init_result = pf_ring_main_loop(device_name); - } - } - - if (!pf_ring_init_result) { - // Internal error in PF_RING - logger << log4cpp::Priority::ERROR << "PF_RING initilization failed, exit from program"; - exit(1); - } -} - - -std::string get_pf_ring_stats() { - std::stringstream output_buffer; - - if (pf_ring_zc_api_mode) { -#ifdef PF_RING_ZC - pfring_zc_stat stats; - // We have elements in insq for every hardware device! We shoulw add ability to configure ot - int stats_res = pfring_zc_stats(inzq[0], &stats); - - if (stats_res) { - logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for in queue"; - } else { - double dropped_percent = 0; - - if (stats.recv + stats.sent > 0) { - dropped_percent = (double)stats.drop / ((double)stats.recv + (double)stats.sent) * 100; - } - - output_buffer << "\n"; - output_buffer << "PF_RING ZC in queue statistics\n"; - output_buffer << "Received:\t" << stats.recv << "\n"; - output_buffer << "Sent:\t\t" << stats.sent << "\n"; - output_buffer << "Dropped:\t" << stats.drop << "\n"; - output_buffer << "Dropped:\t" << std::fixed << std::setprecision(2) << dropped_percent << " %\n"; - } - - output_buffer << "\n"; - output_buffer << "PF_RING ZC out queue statistics\n"; - - u_int64_t total_recv = 0; - u_int64_t total_sent = 0; - u_int64_t total_drop = 0; - for (int i = 0; i < zc_num_threads; i++) { - pfring_zc_stat outq_stats; - - int outq_stats_res = pfring_zc_stats(outzq[0], &outq_stats); - if (stats_res) { - logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for out queue"; - } else { - total_recv += outq_stats.recv; - total_sent += outq_stats.sent; - total_drop += outq_stats.drop; - } - } - - double total_drop_percent = 0; - - if (total_recv + total_sent > 0) { - total_drop_percent = (double)total_drop / ((double)total_recv + (double)total_sent) * 100; - } - - output_buffer << "Received:\t" << total_recv << "\n"; - output_buffer << "Sent:\t\t" << total_sent << "\n"; - output_buffer << "Dropped:\t" << total_drop << "\n"; - output_buffer << "Dropped:\t" << std::fixed << std::setprecision(2) << total_drop_percent << " %\n"; -#endif - } - - // Getting stats for multi channel mode is so complex task - if (!enable_pfring_multi_channel_mode && !pf_ring_zc_api_mode) { - pfring_stat pfring_status_data; - - if (pfring_stats(pf_ring_descr, &pfring_status_data) >= 0) { - char stats_buffer[256]; - double packets_dropped_percent = 0; - - if (pfring_status_data.recv > 0) { - packets_dropped_percent = (double)pfring_status_data.drop / pfring_status_data.recv * 100; - } - - sprintf(stats_buffer, - "Packets received:\t%lu\n" - "Packets dropped:\t%lu\n" - "Packets dropped:\t%.1f %%\n", - (long unsigned int)pfring_status_data.recv, - (long unsigned int)pfring_status_data.drop, packets_dropped_percent); - output_buffer << stats_buffer; - } else { - logger << log4cpp::Priority::ERROR << "Can't get PF_RING stats"; - } - } - - return output_buffer.str(); -} - -bool pf_ring_main_loop_multi_channel(const char* dev) { - int MAX_NUM_THREADS = 64; - - if ((threads = (struct thread_stats*)calloc(MAX_NUM_THREADS, sizeof(struct thread_stats))) == NULL) { - logger << log4cpp::Priority::ERROR << "Can't allocate memory for threads structure"; - return false; - } - - u_int32_t flags = 0; - - flags |= PF_RING_PROMISC; /* hardcode: promisc=1 */ - flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */ - flags |= PF_RING_LONG_HEADER; - - packet_direction direction = rx_only_direction; - - pfring* ring_array[MAX_NUM_RX_CHANNELS]; - - unsigned int snaplen = 128; - num_pfring_channels = pfring_open_multichannel(dev, snaplen, flags, ring_array); - - if (num_pfring_channels <= 0) { - logger << log4cpp::Priority::INFO << "pfring_open_multichannel returned: " << num_pfring_channels - << " and error:" << strerror(errno); - return false; - } - - u_int num_cpus = sysconf(_SC_NPROCESSORS_ONLN); - logger << log4cpp::Priority::INFO << "We have: " << num_cpus << " logical cpus in this server"; - logger << log4cpp::Priority::INFO << "We have: " << num_pfring_channels << " channels from pf_ring NIC"; - - // We should not start more processes then we have kernel cores - // if (num_pfring_channels > num_cpus) { - // num_pfring_channels = num_cpus; - //} - - for (int i = 0; i < num_pfring_channels; i++) { - // char buf[32]; - - threads[i].ring = ring_array[i]; - // threads[i].core_affinity = threads_core_affinity[i]; - - int rc = 0; - - if ((rc = pfring_set_direction(threads[i].ring, direction)) != 0) { - logger << log4cpp::Priority::INFO << "pfring_set_direction returned: " << rc; - } - - if ((rc = pfring_set_socket_mode(threads[i].ring, recv_only_mode)) != 0) { - logger << log4cpp::Priority::INFO << "pfring_set_socket_mode returned: " << rc; - } - - int rehash_rss = 0; - - if (rehash_rss) pfring_enable_rss_rehash(threads[i].ring); - - int poll_duration = 0; - if (poll_duration > 0) pfring_set_poll_duration(threads[i].ring, poll_duration); - - pfring_enable_ring(threads[i].ring); - - unsigned long thread_id = i; - pthread_create(&threads[i].pd_thread, NULL, pf_ring_packet_consumer_thread, (void*)thread_id); - } - - for (int i = 0; i < num_pfring_channels; i++) { - pthread_join(threads[i].pd_thread, NULL); - pfring_close(threads[i].ring); - } - - return true; -} - -void* pf_ring_packet_consumer_thread(void* _id) { - long thread_id = (long)_id; - int wait_for_packet = 1; - - // TODO: fix it - bool do_shutdown = false; - - while (!do_shutdown) { - u_char* buffer = NULL; - struct pfring_pkthdr hdr; - - if (pfring_recv(threads[thread_id].ring, &buffer, 0, &hdr, wait_for_packet) > 0) { - // TODO: pass (u_char*)thread_id) - parse_packet_pf_ring(&hdr, buffer, 0); - } else { - if (wait_for_packet == 0) { - usleep(1); // sched_yield(); - } - } - } - - return NULL; -} - -#ifdef PF_RING_ZC -int rr = -1; -int32_t rr_distribution_func(pfring_zc_pkt_buff* pkt_handle, pfring_zc_queue* in_queue, void* user) { - long num_out_queues = (long)user; - - if (++rr == num_out_queues) { - rr = 0; - } - - return rr; -} -#endif - -#ifdef PF_RING_ZC -int bind2core(int core_id) { - cpu_set_t cpuset; - int s; - - if (core_id < 0) return -1; - - CPU_ZERO(&cpuset); - CPU_SET(core_id, &cpuset); - if ((s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) != 0) { - logger << log4cpp::Priority::INFO << "Error while binding to core:" << core_id; - return -1; - } else { - return 0; - } -} -#endif - -#ifdef PF_RING_ZC -void* zc_packet_consumer_thread(void* _id) { - long id = (long)_id; - pfring_zc_pkt_buff* b = buffers[id]; - - // Bind to core with thread number - bind2core(id); - - u_int8_t wait_for_packet = 1; - - struct pfring_pkthdr zc_header; - memset(&zc_header, 0, sizeof(zc_header)); - - while (true) { - if (pfring_zc_recv_pkt(outzq[id], &b, wait_for_packet) > 0) { - u_char* pkt_data = pfring_zc_pkt_buff_data(b, outzq[id]); - - memset(&zc_header, 0, sizeof(zc_header)); - zc_header.len = b->len; - zc_header.caplen = b->len; - - pfring_parse_pkt(pkt_data, (struct pfring_pkthdr*)&zc_header, 4, 1, 0); - - parse_packet_pf_ring(&zc_header, pkt_data, 0); - } - } - - pfring_zc_sync_queue(outzq[id], rx_only); - - return NULL; -} -#endif - -int max_packet_len(const char* device) { - int max_len = 0; - - pfring* ring = pfring_open(device, 1536, PF_RING_PROMISC); - - if (ring == NULL) return 1536; - -// pfring_get_card_settings have added in 6.0.3 -// We should not use 6.0.3 API for PF_RING library from ntop because it announces "6.0.3" but lack -// of many 6.0.3 features -#if RING_VERSION_NUM >= 0x060003 and !defined(WE_USE_PFRING_FROM_NTOP) - pfring_card_settings settings; - pfring_get_card_settings(ring, &settings); - max_len = settings.max_packet_size; -#else - if (ring->dna.dna_mapped_device) { - max_len = ring->dna.dna_dev.mem_info.rx.packet_memory_slot_len; - } else { - max_len = pfring_get_mtu_size(ring); - if (max_len == 0) max_len = 9000 /* Jumbo */; - max_len += 14 /* Eth */ + 4 /* VLAN */; - } -#endif - - pfring_close(ring); - - return max_len; -} - -#define MAX_CARD_SLOTS 32768 -#define PREFETCH_BUFFERS 8 -#define QUEUE_LEN 8192 - -#ifdef PF_RING_ZC -bool zc_main_loop(const char* device) { - u_int32_t cluster_id = 0; - int bind_core = -1; - - u_int num_cpus = sysconf(_SC_NPROCESSORS_ONLN); - logger << log4cpp::Priority::INFO << "We have: " << num_cpus << " logical cpus in this server"; - - // TODO: add support for multiple devices! - u_int32_t num_devices = 1; - zc_num_threads = num_cpus - 1; - logger << log4cpp::Priority::INFO << "We will start " << zc_num_threads << " worker threads"; - - u_int32_t tot_num_buffers = - (num_devices * MAX_CARD_SLOTS) + (zc_num_threads * QUEUE_LEN) + zc_num_threads + PREFETCH_BUFFERS; - - u_int32_t buffer_len = max_packet_len(device); - logger << log4cpp::Priority::INFO << "We got max packet len from device: " << buffer_len; - logger << log4cpp::Priority::INFO << "We will use total number of ZC buffers: " << tot_num_buffers; - - zc = pfring_zc_create_cluster(cluster_id, buffer_len, 0, tot_num_buffers, - numa_node_of_cpu(bind_core), NULL /* auto hugetlb mountpoint */ - ); - - if (zc == NULL) { - logger << log4cpp::Priority::INFO << "pfring_zc_create_cluster error: " << strerror(errno) - << " Please check that pf_ring.ko is loaded and hugetlb fs is mounted"; - return false; - } - - zc_threads = (pthread_t*)calloc(zc_num_threads, sizeof(pthread_t)); - buffers = (pfring_zc_pkt_buff**)calloc(zc_num_threads, sizeof(pfring_zc_pkt_buff*)); - inzq = (pfring_zc_queue**)calloc(num_devices, sizeof(pfring_zc_queue*)); - outzq = (pfring_zc_queue**)calloc(zc_num_threads, sizeof(pfring_zc_queue*)); - - for (int i = 0; i < zc_num_threads; i++) { - buffers[i] = pfring_zc_get_packet_handle(zc); - - if (buffers[i] == NULL) { - logger << log4cpp::Priority::ERROR << "pfring_zc_get_packet_handle failed"; - return false; - } - } - - - for (int i = 0; i < num_devices; i++) { - u_int32_t zc_flags = 0; - inzq[i] = pfring_zc_open_device(zc, device, rx_only, zc_flags); - - if (inzq[i] == NULL) { - logger << log4cpp::Priority::ERROR << "pfring_zc_open_device error " << strerror(errno) - << " Please check that device is up and not already used"; - return false; - } - -#if RING_VERSION_NUM >= 0x060003 - int pf_ring_license_state = pfring_zc_check_license(); - - if (!pf_ring_license_state) { - logger << log4cpp::Priority::WARN << "PF_RING ZC haven't license for device" << device - << " and running in trial mode and will work only 5 minutes! Please buy license " - "or switch to vanilla PF_RING"; - } -#endif - } - - for (int i = 0; i < zc_num_threads; i++) { - outzq[i] = pfring_zc_create_queue(zc, QUEUE_LEN); - - if (outzq[i] == NULL) { - logger << log4cpp::Priority::ERROR << "pfring_zc_create_queue error: " << strerror(errno); - return false; - } - } - - wsp = pfring_zc_create_buffer_pool(zc, PREFETCH_BUFFERS); - - if (wsp == NULL) { - logger << log4cpp::Priority::ERROR << "pfring_zc_create_buffer_pool error"; - return false; - } - - logger << log4cpp::Priority::INFO << "We are starting balancer with: " << zc_num_threads << " threads"; - - pfring_zc_distribution_func func = rr_distribution_func; - - u_int8_t wait_for_packet = 1; - - // We run balancer at last thread - int32_t bind_worker_core = zc_num_threads; - - logger << log4cpp::Priority::INFO << "We will run balancer on core: " << bind_worker_core; - - zw = pfring_zc_run_balancer(inzq, outzq, num_devices, zc_num_threads, wsp, - round_robin_bursts_policy, NULL /* idle callback */, func, - (void*)((long)zc_num_threads), !wait_for_packet, bind_worker_core); - - if (zw == NULL) { - logger << log4cpp::Priority::ERROR << "pfring_zc_run_balancer error:" << strerror(errno); - return false; - } - - for (int i = 0; i < zc_num_threads; i++) { - pthread_create(&zc_threads[i], NULL, zc_packet_consumer_thread, (void*)(long)i); - } - - for (int i = 0; i < zc_num_threads; i++) { - pthread_join(zc_threads[i], NULL); - } - - pfring_zc_kill_worker(zw); - pfring_zc_destroy_cluster(zc); - - return true; -} -#endif - -bool pf_ring_main_loop(const char* dev) { - // We could pool device in multiple threads - unsigned int num_threads = 1; - - bool promisc = true; - /* This flag manages packet parser for extended_hdr */ - bool use_extended_pkt_header = true; - bool enable_hw_timestamp = false; - bool dont_strip_timestamps = false; - - u_int32_t flags = 0; - if (num_threads > 1) flags |= PF_RING_REENTRANT; - if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER; - if (promisc) flags |= PF_RING_PROMISC; - if (enable_hw_timestamp) flags |= PF_RING_HW_TIMESTAMP; - if (!dont_strip_timestamps) flags |= PF_RING_STRIP_HW_TIMESTAMP; - - if (!we_use_pf_ring_in_kernel_parser) { - flags |= PF_RING_DO_NOT_PARSE; - } - - flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */ - - // use default value from pfcount.c - unsigned int snaplen = 128; - - pf_ring_descr = pfring_open(dev, snaplen, flags); - - if (pf_ring_descr == NULL) { - logger - << log4cpp::Priority::INFO << "pfring_open error: " << strerror(errno) - << " (pf_ring not loaded or perhaps you use quick mode and have already a socket bound to: " << dev - << ")"; - return false; - } - - - logger << log4cpp::Priority::INFO << "Successully binded to: " << dev; - - // We need cast to int because in other way it will be interpreted as char :( - logger << log4cpp::Priority::INFO - << "Device RX channels number: " << int(pfring_get_num_rx_channels(pf_ring_descr)); - - u_int32_t version; - // Set spplication name in /proc - int pfring_set_application_name_result = - pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon"); - - if (pfring_set_application_name_result != 0) { - logger << log4cpp::Priority::ERROR << "Can't set program name for PF_RING: pfring_set_application_name"; - } - - pfring_version(pf_ring_descr, &version); - - logger.info("Using PF_RING v.%d.%d.%d", (version & 0xFFFF0000) >> 16, - (version & 0x0000FF00) >> 8, version & 0x000000FF); - - int pfring_set_socket_mode_result = pfring_set_socket_mode(pf_ring_descr, recv_only_mode); - - if (pfring_set_socket_mode_result != 0) { - logger.info("pfring_set_socket_mode returned [rc=%d]\n", pfring_set_socket_mode_result); - } - - // enable ring - if (pfring_enable_ring(pf_ring_descr) != 0) { - logger << log4cpp::Priority::INFO << "Unable to enable ring :-("; - pfring_close(pf_ring_descr); - return false; - } - - // Active wait wor packets. But I did not know what is mean.. - u_int8_t wait_for_packet = 1; - - pfring_loop(pf_ring_descr, parse_packet_pf_ring, (u_char*)NULL, wait_for_packet); - - return true; -} diff --git a/src/pfring_plugin/pfring_collector.h b/src/pfring_plugin/pfring_collector.h deleted file mode 100644 index 110bd03..0000000 --- a/src/pfring_plugin/pfring_collector.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PFRING_PLUGIN_H -#define PFRING_PLUGIN_H - -#include "../fastnetmon_types.h" - -// This function should be implemented in plugin -void start_pfring_collection(process_packet_pointer func_ptr); -void stop_pfring_collection(); -std::string get_pf_ring_stats(); -#endif diff --git a/src/plugin_runner.cpp b/src/plugin_runner.cpp index 8e9e943..68d16ec 100644 --- a/src/plugin_runner.cpp +++ b/src/plugin_runner.cpp @@ -17,10 +17,6 @@ #include "pcap_plugin/pcap_collector.h" #include "sflow_plugin/sflow_collector.h" -#ifdef PF_RING -#include "pfring_plugin/pfring_collector.h" -#endif - #ifdef FASTNETMON_ENABLE_AFPACKET #include "afpacket_plugin/afpacket_collector.h" #endif @@ -121,7 +117,7 @@ int main(int argc, char* argv[]) { } #endif - // Required by Netmap and PF_RING plugins + // Required by Netmap plugin // We use fake interface name here because netmap could make server unreachable :) configuration_map["interfaces"] = "ethXXX"; @@ -134,13 +130,6 @@ int main(int argc, char* argv[]) { } else if (strstr(argv[1], "pcap") != NULL) { std::cout << "Starting pcap" << std::endl; start_pcap_collection(process_packet); - } else if (strstr(argv[1], "pfring") != NULL) { -#ifdef PF_RING - std::cout << "Starting pf_ring" << std::endl; - start_pfring_collection(process_packet); -#else - std::cout << "PF_RING support disabled here" << std::endl; -#endif } else if (strstr(argv[1], "afpacket") != NULL) { #ifdef FASTNETMON_ENABLE_AFPACKET std::cout << "Starting afpacket" << std::endl; diff --git a/src/scripts/build_any_package.pl b/src/scripts/build_any_package.pl index a4b6eca..ec3753d 100755 --- a/src/scripts/build_any_package.pl +++ b/src/scripts/build_any_package.pl @@ -210,7 +210,7 @@ DOC my $spec_file_summary_section = <<'DOC'; Release: 1%{?dist} -Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +Summary: A high performance DoS/DDoS load analyzer built on top of multiple packet capture engines (NetFlow, IPFIX, sFLOW, netmap, PCAP). Group: System Environment/Daemons License: GPLv2 URL: https://fastnetmon.com @@ -239,7 +239,7 @@ DOC %description A high performance DoS/DDoS load analyzer built on top of multiple packet capture -engines (NetFlow, IPFIX, sFLOW, netmap, PF_RING, PCAP). +engines (NetFlow, IPFIX, sFlow, Netmap, PCAP). DOC @@ -509,7 +509,7 @@ my $fastnetmon_systemv_init = <<'DOC'; # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Fast DDoS detection toolkit. -# Description: Fast DDoS detection toolkit with sFLOW/Netflow/netmap/pf_ring support. +# Description: Fast DDoS detection toolkit with sFLOW/Netflow/Netmap support. ### END INIT INFO # test -r /etc/default/fastnetmon && . /etc/default/fastnetmon diff --git a/src/scripts/build_libary_bundle.pl b/src/scripts/build_libary_bundle.pl index 38d5668..689bad1 100755 --- a/src/scripts/build_libary_bundle.pl +++ b/src/scripts/build_libary_bundle.pl @@ -39,7 +39,6 @@ boost_1_74_0 json-c-0.13 libicu_65_1 log4cpp1.1.1 -pf_ring_6.0.3 gobgp_2_17_0 grpc_1_30_2 libhiredis_0_13 @@ -55,12 +54,7 @@ for my $library (@our_libraries) { unless (-e $library_path) { warn "Can't find library $library please check\n"; - - if ($library eq 'pf_ring_6.0.3') { - next; - } else { - die "Some required libraries are missing\n"; - } + die "Some required libraries are missing\n"; } print "Library: $library\n"; diff --git a/src/tests/pfring_parser_zc_issue.c b/src/tests/pfring_parser_zc_issue.c deleted file mode 100644 index 2d7a252..0000000 --- a/src/tests/pfring_parser_zc_issue.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "pfring.h" -#include - -/* How to compile me: - g++ pfring_parser_zc_issue.c -I/opt/pf_ring/include -L/opt/pf_ring/lib/ -lpfring -lnuma -*/ - -void parse_packet_pf_ring(const struct pfring_pkthdr* h, const u_char* p, const u_char* user_bytes) { - memset((void*)&h->extended_hdr.parsed_pkt, 0, sizeof(h->extended_hdr.parsed_pkt)); - pfring_parse_pkt((u_char*)p, (struct pfring_pkthdr*)h, 4, 1, 0); - - char buffer[512]; - pfring_print_parsed_pkt(buffer, 512, p, h); - std::cout << buffer; -} - -int main() { - char* dev = "zc:eth3"; - // We could pool device in multiple threads - unsigned int num_threads = 1; - - bool promisc = true; - /* This flag manages packet parser for extended_hdr */ - bool use_extended_pkt_header = true; - bool enable_hw_timestamp = false; - bool dont_strip_timestamps = false; - - u_int32_t flags = 0; - if (num_threads > 1) flags |= PF_RING_REENTRANT; - if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER; - if (promisc) flags |= PF_RING_PROMISC; - if (enable_hw_timestamp) flags |= PF_RING_HW_TIMESTAMP; - if (!dont_strip_timestamps) flags |= PF_RING_STRIP_HW_TIMESTAMP; - - // if (!we_use_pf_ring_in_kernel_parser) { - // flags != PF_RING_DO_NOT_PARSE; - //} - - // flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers - // */ - - // use default value from pfcount.c - unsigned int snaplen = 128; - - pfring* pf_ring_descr = pfring_open(dev, snaplen, flags); - - if (pf_ring_descr == NULL) { - std::cout - << "pfring_open error: " << strerror(errno) - << " (pf_ring not loaded or perhaps you use quick mode and have already a socket bound to: " << dev - << ")"; - return false; - } - - - u_int32_t version; - // Set spplication name in /proc - int pfring_set_application_name_result = - pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon"); - - if (pfring_set_application_name_result != 0) { - std::cout << "Can't set program name for PF_RING: pfring_set_application_name"; - } - - pfring_version(pf_ring_descr, &version); - - int pfring_set_socket_mode_result = pfring_set_socket_mode(pf_ring_descr, recv_only_mode); - - // enable ring - if (pfring_enable_ring(pf_ring_descr) != 0) { - std::cout << "Unable to enable ring :-("; - pfring_close(pf_ring_descr); - return false; - } - - u_int8_t wait_for_packet = 1; - pfring_loop(pf_ring_descr, parse_packet_pf_ring, (u_char*)NULL, wait_for_packet); -} diff --git a/src/tests/spsc_prototype.cpp b/src/tests/spsc_prototype.cpp index 82859ae..282f960 100644 --- a/src/tests/spsc_prototype.cpp +++ b/src/tests/spsc_prototype.cpp @@ -17,10 +17,6 @@ #include "../pcap_plugin/pcap_collector.h" #include "../sflow_plugin/sflow_collector.h" -#ifdef PF_RING -#include "../pfring_plugin/pfring_collector.h" -#endif - #include "../netmap_plugin/netmap_collector.h" #include @@ -128,7 +124,7 @@ int main(int argc, char* argv[]) { init_logging(); - // Required by Netmap and PF_RING plugins + // Required by Netmap plugin // We use fake interface name here because netmap could make server unreachable :) configuration_map["interfaces"] = "eth5"; start_netmap_collection(process_packet);