Removed Snabb Switch support. Closes #858 (#859)

This commit is contained in:
Pavel Odintsov 2020-09-27 12:22:50 +01:00 committed by GitHub
parent bf30811ee7
commit da30452fc1
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 11 additions and 581 deletions

View File

@ -26,7 +26,6 @@ Supported packet capture engines
- PCAP
- AF_PACKET
- Netmap
- SnabbSwitch (experimental)
- PF_RING / PF_RING ZC (available only for CentOS 6 for compatibiliy, otherwise use AF_PACKET)
You can check out the [comparison table](https://fastnetmon.com/docs/capture_backends/) for all available packet capture engines.

View File

@ -210,15 +210,6 @@ add_library(ipfix_rfc STATIC ipfix_rfc.cpp)
# Our packet parser
add_library(fastnetmon_packet_parser STATIC fastnetmon_packet_parser.c)
# -DENABLE_SNABBSWITCH_SUPPORT=ON ..
if (ENABLE_SNABBSWITCH_SUPPORT)
add_definitions(-DSNABB_SWITCH)
add_library(snabbswitch_plugin STATIC snabbswitch_plugin/snabbswitch_collector.cpp)
link_directories(/usr/src/snabbswitch/src)
target_link_libraries(snabbswitch_plugin snabb)
endif()
CHECK_CXX_SOURCE_COMPILES("
#include <linux/if_packet.h>
int main() {
@ -580,10 +571,6 @@ if (ENABLE_GOBGP_SUPPORT)
target_link_libraries(fastnetmon gobgp_action)
endif()
if (ENABLE_SNABBSWITCH_SUPPORT)
target_link_libraries(fastnetmon snabbswitch_plugin)
endif()
if (ENABLE_AFPACKET_SUPPORT)
target_link_libraries(fastnetmon afpacket_plugin)
endif()
@ -598,10 +585,6 @@ endif()
if (BUILD_PLUGIN_RUNNER)
add_executable(fastnetmon_plugin_runner plugin_runner.cpp)
if (ENABLE_SNABBSWITCH_SUPPORT)
target_link_libraries(fastnetmon_plugin_runner snabbswitch_plugin)
endif()
if (ENABLE_AFPACKET_SUPPORT)
target_link_libraries(fastnetmon_plugin_runner afpacket_plugin)
endif()

View File

@ -1,27 +0,0 @@
#ifndef FAST_PLATFORM_H
#define FAST_PLATFORM_H
// This file automatically generated for your platform (Linux, FreeBSD and others) with cmake
/* Platform specific paths */
std::string fastnetmon_version = "1.1.8 master git-23efd99d277a4e3161c3e6c510ad010e6e436842";
std::string pid_path = "/var/run/fastnetmon.pid";
std::string global_config_path = "/etc/fastnetmon.conf";
std::string log_file_path = "/var/log/fastnetmon.log";
std::string attack_details_folder = "/var/log/fastnetmon_attacks";
// Default path to notify script
std::string notify_script_path = "/usr/local/bin/notify_about_attack.sh";
// Default path to file with networks for whitelising
std::string white_list_path = "/etc/networks_whitelist";
// Default path to file with all networks listing
std::string networks_list_path = "/etc/networks_list";
/* Platform specific paths end */
#endif

View File

@ -92,9 +92,6 @@ pfring_sampling_ratio = 1
# Netmap traffic capture (very fast but needs patched drivers)
mirror_netmap = off
# SnabbSwitch traffic capture
mirror_snabbswitch = off
# AF_PACKET capture engine
# Please use it only with modern Linux kernels (3.6 and more)
# And please install birq for irq ditribution over cores
@ -108,9 +105,6 @@ mirror_af_packet_custom_sampling_rate = 1
# Available modes: cpu, lb, hash, random, rollover, queue_mapping
mirror_af_packet_fanout_mode = cpu
# use PCI-e addresses here instead of OS device names. You can find them in "lspci" output
interfaces_snabbswitch = 0000:04:00.0,0000:04:00.1,0000:03:00.0,0000:03:00.1
# Port mirroring sampling ratio
netmap_sampling_ratio = 1

View File

@ -66,10 +66,6 @@
#include "pfring_plugin/pfring_collector.h"
#endif
#ifdef SNABB_SWITCH
#include "snabbswitch_plugin/snabbswitch_collector.h"
#endif
#ifdef FASTNETMON_ENABLE_AFPACKET
#include "afpacket_plugin/afpacket_collector.h"
#endif
@ -263,7 +259,6 @@ void init_global_ban_settings() {
bool enable_conection_tracking = true;
bool enable_snabbswitch_collection = false;
bool enable_afpacket_collection = false;
bool enable_data_collection_from_mirror = true;
bool enable_netmap_collection = false;
@ -1316,10 +1311,6 @@ bool load_configuration_file() {
}
}
if (configuration_map.count("mirror_snabbswitch") != 0) {
enable_snabbswitch_collection = configuration_map["mirror_snabbswitch"] == "on";
}
if (configuration_map.count("mirror_afpacket") != 0) {
enable_afpacket_collection = configuration_map["mirror_afpacket"] == "on";
}
@ -3085,12 +3076,6 @@ int main(int argc, char** argv) {
}
#endif
#ifdef SNABB_SWITCH
if (enable_snabbswitch_collection) {
packet_capture_plugin_thread_group.add_thread(new boost::thread(start_snabbswitch_collection, process_packet));
}
#endif
#ifdef FASTNETMON_ENABLE_AFPACKET
if (enable_afpacket_collection) {
packet_capture_plugin_thread_group.add_thread(new boost::thread(start_afpacket_collection, process_packet));

10
src/grep.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
script_dir=`dirname "$0"`
find $script_dir/.. -type f | egrep -v 'fastnetmon.pb.cc|.git|build'> /tmp/file_list
for i in `cat /tmp/file_list` ; do
grep -Hi "$1" $i
done

View File

@ -25,10 +25,6 @@
#include "afpacket_plugin/afpacket_collector.h"
#endif
#ifdef SNABB_SWITCH
#include "snabbswitch_plugin/snabbswitch_collector.h"
#endif
#ifdef NETMAP_PLUGIN
#include "netmap_plugin/netmap_collector.h"
#endif
@ -108,7 +104,7 @@ int main(int argc, char* argv[]) {
init_logging();
if (argc < 2) {
std::cout << "Please specify sflow, netflow, raw, dpi, snabbswitch, afpacket as param" << std::endl;
std::cout << "Please specify sflow, netflow, raw, dpi, afpacket as param" << std::endl;
return 1;
}
@ -138,14 +134,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], "snabbswitch") != NULL) {
std::cout << "Starting snabbswitch" << std::endl;
#ifdef SNABB_SWITCH
start_snabbswitch_collection(process_packet);
#else
printf("SnabbSwitch support is not compiled here\n");
#endif
} else if (strstr(argv[1], "pfring") != NULL) {
#ifdef PF_RING
std::cout << "Starting pf_ring" << std::endl;

View File

@ -1,155 +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 <boost/algorithm/string.hpp>
#include <boost/version.hpp>
#include "../fast_library.h"
// For support uint32_t, uint16_t
#include <sys/types.h>
// For config map operations
#include <map>
#include <string>
#include <iostream>
#include <stdio.h>
#include <string>
#include "../fastnetmon_packet_parser.h"
// For support: IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_UDP
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "snabbswitch_collector.h"
#include "unified_parser.hpp"
#ifdef __cplusplus
extern "C" {
#endif
// This code defined in SnabbSwitch
int start_snabb_switch(int snabb_argc, const char** snabb_argv);
#ifdef __cplusplus
}
#endif
// Get log4cpp logger from main program
extern log4cpp::Category& logger;
// Pass unparsed packets number to main program
extern uint64_t total_unparsed_packets;
// Global configuration map
extern std::map<std::string, std::string> configuration_map;
// This variable name should be uniq for every plugin!
process_packet_pointer snabbswitch_process_func_ptr = NULL;
inline void firehose_packet(const char* pciaddr, char* data, int length);
/* Intel 82599 "Legacy" receive descriptor format.
* See Intel 82599 data sheet section 7.1.5.
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
*/
struct firehose_rdesc {
uint64_t address;
uint16_t length;
uint16_t cksum;
uint8_t status;
uint8_t errors;
uint16_t vlan;
} __attribute__((packed));
void firehose_packet(const char* pciaddr, char* data, int length) {
simple_packet_t packet;
if (!parse_raw_packet_to_simple_packet((u_char*)data, length, packet, false)) {
total_unparsed_packets++;
return;
}
snabbswitch_process_func_ptr(packet);
}
#ifdef __cplusplus
extern "C" {
#endif
int firehose_callback_v1(const char* pciaddr, char** packets, struct firehose_rdesc* rxring, int ring_size, int index);
#ifdef __cplusplus
}
#endif
int firehose_callback_v1(const char* pciaddr, char** packets, struct firehose_rdesc* rxring, int ring_size, int index) {
while (rxring[index].status & 1) {
int next_index = (index + 1) & (ring_size - 1);
__builtin_prefetch(packets[next_index]);
firehose_packet(pciaddr, packets[index], rxring[index].length);
rxring[index].status = 0; /* reset descriptor for reuse */
index = next_index;
}
return index;
}
void start_snabbswitch_collection(process_packet_pointer func_ptr) {
logger << log4cpp::Priority::INFO << "SnabbSwitch plugin started";
snabbswitch_process_func_ptr = func_ptr;
std::string interfaces_list = "";
if (configuration_map.count("interfaces_snabbswitch") != 0) {
interfaces_list = configuration_map["interfaces_snabbswitch"];
}
std::vector<std::string> interfaces_for_capture;
boost::split(interfaces_for_capture, interfaces_list, boost::is_any_of(","), boost::token_compress_on);
if (interfaces_for_capture.size() == 0) {
logger << log4cpp::Priority::ERROR << "Please specify list of PCI-e addresses for SnabbSwitch capture";
}
logger << log4cpp::Priority::INFO << "SnabbSwitch will listen on "
<< interfaces_for_capture.size() << " interfaces";
boost::thread_group snabbswitch_main_threads;
for (std::vector<std::string>::iterator interface = interfaces_for_capture.begin();
interface != interfaces_for_capture.end(); ++interface) {
// We could specify multiple NIC's for single thread with multiple --input
const char* cli_arguments[5];
cli_arguments[0] = "snabb"; // emulate call of standard application
cli_arguments[1] = "firehose";
cli_arguments[2] = "--input";
cli_arguments[3] = interface->c_str();
cli_arguments[4] = "weird_data";
int cli_number_of_arguments = sizeof(cli_arguments) / sizeof(char*);
logger << log4cpp::Priority::INFO
<< "We are starting SnabbSwitch instance for PCIe interface " << *interface;
snabbswitch_main_threads.add_thread(
new boost::thread(start_snabb_switch, cli_number_of_arguments, cli_arguments));
// We should sleep here because init code of SnabbSwitch is not thread safe
sleep(10);
}
snabbswitch_main_threads.join_all();
}

View File

@ -1,8 +0,0 @@
#ifndef SNABBSWITCH_PLUGIN_H
#define SNABBSWITCH_PLUGIN_H
#include "../fastnetmon_types.h"
void start_snabbswitch_collection(process_packet_pointer func_ptr);
#endif

View File

@ -1,73 +0,0 @@
### Here we store all code related with Snabb switch intergration :) We like it because it's awesome!
First of all, please compile Snabb Switch from next branch:
```bash
cd /usr/src/
git clone https://github.com/SnabbCo/snabbswitch.git -b next
cd snabbswitch
make
```
Then compile our .so library:
```
g++ -O3 ../../fastnetmon_packet_parser.c -c -o fastnetmon_packet_parser.o -fPIC
g++ -O3 -shared -o capturecallback.so -fPIC capturecallback.cpp fastnetmon_packet_parser.o
```
Polly enabled clang compilation (offer significant speedup):
```bash
alias pollycc="/usr/src/polly/llvm_build/bin/clang -Xclang -load -Xclang /usr/src/polly/llvm_build/lib/LLVMPolly.so"
pollycc -O3 ../../fastnetmon_packet_parser.c -c -o fastnetmon_packet_parser.o -fPIC
pollycc -O3 -shared -o capturecallback.so -fPIC capturecallback.c fastnetmon_packet_parser.o
```
Get NIC's PCI address:
```bash
lspci -m|grep 82599
00:05.0 "Ethernet controller" "Intel Corporation" "82599ES 10-Gigabit SFI/SFP+ Network Connection" -r01 "Intel Corporation" "Ethernet Server Adapter X520-2"
00:06.0 "Ethernet controller" "Intel Corporation" "82599ES 10-Gigabit SFI/SFP+ Network Connection" -r01 "Intel Corporation" "Ethernet Server Adapter X520-2"
```
For example, we will use 00:06.0, we need convert this value to Snabb's format with adding 4 leading zeroes: 0000:00:06.0
Run capture:
```bash
/usr/src/snabbswitch/src/snabb firehose --input 0000:03:00.0 --input 0000:03:00.1 /usr/src/fastnetmon/src/tests/snabb/capturecallback.so
```
I have got really amazing results:
```bash
Loading shared object: ./capturecallback.so
Initializing NIC: 0000:00:06.0
Run speed printer from C code
Processing traffic...
We process: 14566196 pps
We process: 14820487 pps
We process: 14856881 pps
We process: 14863727 pps
```
We achieved this with only single logical core of i7 3820 CPU:
```bash
1 [ 0.0%]
5 [ 0.0%]
2 [ 0.0%]
6 [ 0.0%]
3 [ 0.0%]
7 [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
4 [ 0.0%]
8 [ 0.0%]
```
Really awesome! Huge thanks to Luke Gorrie for great help with it!
Once the testing is done we can rebind the NIC to the kernel `ixgbe`
driver. This can be done either be reloading `ixgbe` or, less
disruptively, like this:
```bash
echo 0000:00:06.0 | sudo tee /sys/bus/pci/drivers/ixgbe/bind
```

View File

@ -1,266 +0,0 @@
// Author: Pavel.Odintsov@gmail.com
// License GPLv2
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <memory>
#include <thread>
#include <boost/atomic.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/thread/thread.hpp>
#include "../../fastnetmon_pcap_format.h"
/*
Compile it:
g++ -O3 -fPIC -std=c++11 ../../fastnetmon_pcap_format.cpp -c -o fastnetmon_pcap_format.o
g++ -O3 -shared -o capturetodisk.so -fPIC capturetodisk.cpp fastnetmon_pcap_format.o -std=c++11 -lboost_system
Run it:
/usr/src/snabbswitch/src/snabb firehose --input 0000:02:00.0 --input 0000:02:00.1 /usr/src/fastnetmon/src/tests/snabb/capturetodisk.so
Please use ext4 with writeback feature:
mount -odata=writeback /dev/sdb /mnt
*/
class packet_buffer_t {
public:
unsigned char buffer[1600];
unsigned int length;
};
typedef std::shared_ptr<packet_buffer_t> packet_buffer_shared_pointer_t;
constexpr auto size_spsc_queue = 1048576;
// We use persistent preallocation for ext4 and allocate 20 GB for storing data before any operations
uint64_t preallocate_packet_dump_file_size = 1073741824ul * 20ul;
typedef boost::lockfree::spsc_queue<packet_buffer_shared_pointer_t, boost::lockfree::capacity<size_spsc_queue> > my_spsc_queue_t;
int pcap_file = 0;
my_spsc_queue_t my_spsc_queue;
#ifdef __cplusplus
extern "C" {
#endif
/* Called once before processing packets. */
void firehose_start(); /* optional */
#ifdef __cplusplus
}
#endif
/* Called once after processing packets. */
void firehose_stop(); /* optional */
void firehose_stop() {
// Close file and flush data
close(pcap_file);
}
/*
* Process a packet received from a NIC.
*
* pciaddr: name of PCI device packet is received from
* data: packet payload (ethernet frame)
* length: payload length in bytes
*/
inline void firehose_packet(const char* pciaddr, char* data, int length);
/* Intel 82599 "Legacy" receive descriptor format.
* See Intel 82599 data sheet section 7.1.5.
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
*/
struct firehose_rdesc {
uint64_t address;
uint16_t length;
uint16_t cksum;
uint8_t status;
uint8_t errors;
uint16_t vlan;
} __attribute__((packed));
/* Traverse the hardware receive descriptor ring.
* Process each packet that is ready.
* Return the updated ring index.
*/
#ifdef __cplusplus
extern "C" {
#endif
int firehose_callback_v1(const char* pciaddr, char** packets, struct firehose_rdesc* rxring, int ring_size, int index) {
while (rxring[index].status & 1) {
int next_index = (index + 1) & (ring_size - 1);
__builtin_prefetch(packets[next_index]);
firehose_packet(pciaddr, packets[index], rxring[index].length);
rxring[index].status = 0; /* reset descriptor for reuse */
index = next_index;
}
return index;
}
#ifdef __cplusplus
}
#endif
uint64_t received_packets = 0;
uint64_t received_bytes = 0;
void* speed_printer(void* ptr) {
while (1) {
uint64_t packets_before = received_packets;
uint64_t bytes_before = received_bytes;
sleep(1);
uint64_t packets_after = received_packets;
uint64_t bytes_after = received_bytes;
uint64_t pps = packets_after - packets_before;
uint64_t bps = bytes_after - bytes_before;
float gbps_speed = (float)bps / 1024 / 1024 / 1024 * 8;
float gb_total = (float)received_bytes / 1024 / 1024 / 1024;
printf("We process: %llu pps %.2f Gbps. We will store %.2f megabytes per second. We have "
"stored %.2f GB of data\n",
(long long)pps, gbps_speed, gbps_speed / 8 * 1024, gb_total);
}
}
void write_packet_to_file(packet_buffer_shared_pointer_t packet) {
struct timeval current_time;
current_time.tv_sec = 0;
current_time.tv_usec = 0;
// It's performance killer!
bool we_do_timestamps = false;
if (we_do_timestamps) {
gettimeofday(&current_time, NULL);
}
struct fastnetmon_pcap_pkthdr pcap_packet_header;
pcap_packet_header.ts_sec = current_time.tv_sec;
pcap_packet_header.ts_usec = current_time.tv_usec;
pcap_packet_header.incl_len = packet->length;
pcap_packet_header.orig_len = packet->length;
unsigned int packet_header_written_bytes =
write(pcap_file, &pcap_packet_header, sizeof(pcap_packet_header));
if (packet_header_written_bytes != sizeof(pcap_packet_header)) {
printf("Can't write pcap pcaket header\n");
}
unsigned int packet_written_bytes = write(pcap_file, packet->buffer, packet->length);
if (packet_written_bytes != packet->length) {
printf("Can't write data to file\n");
}
}
void* packets_consumer(void* ptr) {
printf("Start consumer thread\n");
packet_buffer_shared_pointer_t packet;
while (true) {
while (my_spsc_queue.pop(packet)) {
write_packet_to_file(packet);
__sync_fetch_and_add(&received_packets, 1);
__sync_fetch_and_add(&received_bytes, packet->length);
}
}
}
void sigproc(int sig) {
firehose_stop();
printf("We caught SINGINT and will finish application\n");
exit(0);
}
#ifdef __cplusplus
extern "C" {
#endif
// We will start speed printer
void firehose_start() {
signal(SIGINT, sigproc);
pcap_file = open("/mnt/traffic_capture.pcap", O_TRUNC | O_WRONLY | O_CREAT);
if (pcap_file < 0) {
printf("Can't open file for capture\n");
exit(-1);
}
printf("Preaallocate %llu bytes on file system for storing traffic\n", preallocate_packet_dump_file_size);
int fallocate_result = posix_fallocate(pcap_file, 0, preallocate_packet_dump_file_size);
if (fallocate_result != 0) {
printf("fallocate failed! Please check disk space and Linux Kernel Code\n");
}
/* Caching is useless for our case because we have average linear traffic in most cases
// We enable full buffering: _IOFBF
int setvbuf_result = setvbuf(pcap_file, NULL, _IONBF, 1024 * 1024 * 4);
if (setvbuf_result != 0) {
printf("Can't set buffer for file operation\n");
}
*/
struct fastnetmon_pcap_file_header pcap_header;
fill_pcap_header(&pcap_header, 1600);
unsigned int written_bytes = write(pcap_file, &pcap_header, sizeof(pcap_header));
if (written_bytes != sizeof(pcap_header)) {
printf("Can't write pcap header\n");
}
pthread_t thread;
pthread_create(&thread, NULL, speed_printer, NULL);
pthread_t consumer_thread;
pthread_create(&consumer_thread, NULL, packets_consumer, NULL);
pthread_detach(thread);
pthread_detach(consumer_thread);
}
#ifdef __cplusplus
}
#endif
void firehose_packet(const char* pciaddr, char* data, int length) {
std::shared_ptr<packet_buffer_t> packet_pointer(new packet_buffer_t);
packet_pointer->length = length;
if (length < 1600) {
memcpy(packet_pointer->buffer, data, length);
} else {
printf("So big packet: %d\n", length);
}
// Put pointer to the tube!
while (!my_spsc_queue.push(packet_pointer))
;
}