parent
bf30811ee7
commit
da30452fc1
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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(¤t_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))
|
||||
;
|
||||
}
|
Loading…
Reference in New Issue