2015-02-04 13:00:06 +01:00
|
|
|
// log4cpp logging facility
|
|
|
|
#include "log4cpp/Category.hh"
|
|
|
|
#include "log4cpp/Appender.hh"
|
|
|
|
#include "log4cpp/FileAppender.hh"
|
|
|
|
#include "log4cpp/OstreamAppender.hh"
|
|
|
|
#include "log4cpp/Layout.hh"
|
|
|
|
#include "log4cpp/BasicLayout.hh"
|
|
|
|
#include "log4cpp/PatternLayout.hh"
|
|
|
|
#include "log4cpp/Priority.hh"
|
|
|
|
|
2015-03-21 12:24:31 +01:00
|
|
|
#include "../fast_library.h"
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
// For support uint32_t, uint16_t
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <iomanip>
|
|
|
|
|
|
|
|
// For config map operations
|
|
|
|
#include <string>
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
// For support: IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_UDP
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
#include "pfring_collector.h"
|
|
|
|
|
|
|
|
#include "pfring.h"
|
2015-02-24 17:53:41 +01:00
|
|
|
|
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
#include "pfring_zc.h"
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
#include <numa.h>
|
|
|
|
|
2015-06-24 00:51:04 +02:00
|
|
|
uint32_t pfring_sampling_ratio = 1;
|
|
|
|
|
2017-05-08 16:21:52 +02:00
|
|
|
// Get log4cpp logger from main program
|
2015-02-04 13:00:06 +01:00
|
|
|
extern log4cpp::Category& logger;
|
|
|
|
|
|
|
|
extern uint64_t total_unparsed_packets;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
// Global configuration map
|
2015-02-04 13:00:06 +01:00
|
|
|
extern std::map<std::string, std::string> 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;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
pfring* ring;
|
2015-02-04 13:00:06 +01:00
|
|
|
pthread_t pd_thread;
|
|
|
|
int core_affinity;
|
|
|
|
|
|
|
|
volatile u_int64_t do_shutdown;
|
|
|
|
|
|
|
|
u_int64_t __padding_1[3];
|
|
|
|
};
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
struct thread_stats* threads;
|
2015-02-04 13:00:06 +01:00
|
|
|
pfring* pf_ring_descr = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// We can use ZC api
|
|
|
|
bool pf_ring_zc_api_mode = false;
|
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
u_int32_t zc_num_threads = 0;
|
2015-05-15 12:55:52 +02:00
|
|
|
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;
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// Prototypes
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
bool zc_main_loop(const char* device);
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "PF_RING plugin started";
|
2015-02-04 13:00:06 +01:00
|
|
|
pfring_process_func_ptr = func_ptr;
|
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (configuration_map.count("interfaces") != 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
work_on_interfaces = configuration_map["interfaces"];
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// 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;
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO
|
|
|
|
<< "We detect run in PF_RING Zero Copy or DNA mode and we enable packet parser!";
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "We selected interface:" << work_on_interfaces;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-06-24 00:51:04 +02:00
|
|
|
if (configuration_map.count("pfring_sampling_ratio") != 0) {
|
|
|
|
pfring_sampling_ratio = convert_string_to_integer(configuration_map["pfring_sampling_ratio"]);
|
|
|
|
}
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
if (work_on_interfaces == "") {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "Please specify interface";
|
2015-02-04 13:00:06 +01:00
|
|
|
exit(1);
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
pfring_main_packet_process_task();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void stop_pfring_collection() {
|
|
|
|
pfring_breakloop(pf_ring_descr);
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
void parse_packet_pf_ring(const struct pfring_pkthdr* h, const u_char* p, const u_char* user_bytes) {
|
2015-06-16 21:09:02 +02:00
|
|
|
// Description of all fields: http://www.ntop.org/pfring_api/structpkt__parsing__info.html
|
2015-02-04 13:00:06 +01:00
|
|
|
simple_packet packet;
|
|
|
|
|
|
|
|
// We pass only one packet to processing
|
|
|
|
packet.number_of_packets = 1;
|
|
|
|
|
|
|
|
// Now we support only non sampled input from PF_RING
|
2015-06-24 00:51:04 +02:00
|
|
|
packet.sample_ratio = pfring_sampling_ratio;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
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"
|
2015-05-15 12:55:52 +02:00
|
|
|
// http://www.ntop.org/pfring_api/pfring_8h.html
|
2015-02-04 13:00:06 +01:00
|
|
|
// 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));
|
2015-05-13 22:52:00 +02:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
// We do not calculate timestamps here because it's useless and consumes so much cpu
|
2015-05-13 22:52:00 +02:00
|
|
|
// 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);
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (do_unpack_l2tp_over_ip) {
|
2015-05-15 12:55:52 +02:00
|
|
|
// 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]
|
2015-02-04 13:00:06 +01:00
|
|
|
// L2TP has an proto number 115
|
|
|
|
if (h->extended_hdr.parsed_pkt.l3_proto == 115) {
|
2015-05-15 12:55:52 +02:00
|
|
|
// pfring_parse_pkt expects that the hdr memory is either zeroed or contains valid
|
|
|
|
// values
|
2015-02-04 13:00:06 +01:00
|
|
|
// 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);
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
const u_char* l2tp_tunnel_payload = p + l4_offset + l2tp_header_size;
|
2015-02-04 13:00:06 +01:00
|
|
|
// 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<<log4cpp::Priority::INFO<<buffer;
|
|
|
|
*/
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-06-18 16:11:08 +02:00
|
|
|
if (h->extended_hdr.parsed_pkt.ip_version != 4 && h->extended_hdr.parsed_pkt.ip_version != 6) {
|
2015-06-18 15:42:51 +02:00
|
|
|
total_unparsed_packets++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-18 16:11:08 +02:00
|
|
|
packet.ip_protocol_version = h->extended_hdr.parsed_pkt.ip_version;
|
2015-06-18 15:42:51 +02:00
|
|
|
|
|
|
|
if (packet.ip_protocol_version == 4) {
|
|
|
|
// IPv4
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
/* PF_RING stores data in host byte order but we use network byte order */
|
2015-06-18 16:11:08 +02:00
|
|
|
packet.src_ip = htonl(h->extended_hdr.parsed_pkt.ip_src.v4);
|
|
|
|
packet.dst_ip = htonl(h->extended_hdr.parsed_pkt.ip_dst.v4);
|
2015-06-18 15:42:51 +02:00
|
|
|
} else {
|
|
|
|
// IPv6
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-06-18 16:11:08 +02:00
|
|
|
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);
|
2015-06-18 15:42:51 +02:00
|
|
|
}
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-06-18 15:42:51 +02:00
|
|
|
packet.source_port = h->extended_hdr.parsed_pkt.l4_src_port;
|
|
|
|
packet.destination_port = h->extended_hdr.parsed_pkt.l4_dst_port;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-07-16 22:42:11 +02:00
|
|
|
// We need this for deep packet inspection
|
|
|
|
packet.packet_payload_length = h->len;
|
|
|
|
packet.packet_payload_pointer = (void*)p;
|
|
|
|
|
2015-06-18 15:42:51 +02:00
|
|
|
packet.length = h->len;
|
|
|
|
packet.protocol = h->extended_hdr.parsed_pkt.l3_proto;
|
|
|
|
packet.ts = h->ts;
|
2015-06-18 12:07:55 +02:00
|
|
|
|
2015-06-18 15:42:51 +02:00
|
|
|
// Copy flags from PF_RING header to our pseudo header
|
|
|
|
if (packet.protocol == IPPROTO_TCP) {
|
|
|
|
packet.flags = h->extended_hdr.parsed_pkt.tcp.flags;
|
2015-02-04 13:00:06 +01:00
|
|
|
} else {
|
2015-06-18 15:42:51 +02:00
|
|
|
packet.flags = 0;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-06-18 15:42:51 +02:00
|
|
|
pfring_process_func_ptr(packet);
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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) {
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
pf_ring_init_result = zc_main_loop((char*)device_name);
|
2015-02-24 17:53:41 +01:00
|
|
|
#else
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR
|
|
|
|
<< "PF_RING library hasn't ZC support, please try SVN version";
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
} 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
|
2017-05-08 16:21:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "PF_RING initilization failed, exit from program";
|
2015-02-04 13:00:06 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string get_pf_ring_stats() {
|
|
|
|
std::stringstream output_buffer;
|
|
|
|
|
|
|
|
if (pf_ring_zc_api_mode) {
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
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);
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
if (stats_res) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for in queue";
|
2015-02-04 13:00:06 +01:00
|
|
|
} else {
|
|
|
|
double dropped_percent = 0;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
if (stats.recv + stats.sent > 0) {
|
2015-02-04 13:00:06 +01:00
|
|
|
dropped_percent = (double)stats.drop / ((double)stats.recv + (double)stats.sent) * 100;
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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";
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
output_buffer << "\n";
|
|
|
|
output_buffer << "PF_RING ZC out queue statistics\n";
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "Can't get PF_RING ZC stats for out queue";
|
2015-02-04 13:00:06 +01:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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";
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
// 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;
|
2015-05-15 12:55:52 +02:00
|
|
|
|
|
|
|
if (pfring_stats(pf_ring_descr, &pfring_status_data) >= 0) {
|
2015-02-04 13:00:06 +01:00
|
|
|
char stats_buffer[256];
|
2015-05-15 12:55:52 +02:00
|
|
|
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;
|
2015-02-04 13:00:06 +01:00
|
|
|
} else {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "Can't get PF_RING stats";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "Can't allocate memory for threads structure";
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
u_int32_t flags = 0;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
flags |= PF_RING_PROMISC; /* hardcode: promisc=1 */
|
|
|
|
flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */
|
2015-02-04 13:00:06 +01:00
|
|
|
flags |= PF_RING_LONG_HEADER;
|
|
|
|
|
|
|
|
packet_direction direction = rx_only_direction;
|
|
|
|
|
|
|
|
pfring* ring_array[MAX_NUM_RX_CHANNELS];
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
unsigned int snaplen = 128;
|
|
|
|
num_pfring_channels = pfring_open_multichannel(dev, snaplen, flags, ring_array);
|
|
|
|
|
|
|
|
if (num_pfring_channels <= 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "pfring_open_multichannel returned: " << num_pfring_channels
|
|
|
|
<< " and error:" << strerror(errno);
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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";
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// We should not start more processes then we have kernel cores
|
2015-05-15 12:55:52 +02:00
|
|
|
// if (num_pfring_channels > num_cpus) {
|
2015-02-04 13:00:06 +01:00
|
|
|
// num_pfring_channels = num_cpus;
|
|
|
|
//}
|
|
|
|
|
|
|
|
for (int i = 0; i < num_pfring_channels; i++) {
|
|
|
|
// char buf[32];
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
threads[i].ring = ring_array[i];
|
|
|
|
// threads[i].core_affinity = threads_core_affinity[i];
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
if ((rc = pfring_set_direction(threads[i].ring, direction)) != 0) {
|
|
|
|
logger << log4cpp::Priority::INFO << "pfring_set_direction returned: " << rc;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
if ((rc = pfring_set_socket_mode(threads[i].ring, recv_only_mode)) != 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "pfring_set_socket_mode returned: " << rc;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int rehash_rss = 0;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
for (int i = 0; i < num_pfring_channels; i++) {
|
2015-02-04 13:00:06 +01:00
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
u_char* buffer = NULL;
|
2015-02-04 13:00:06 +01:00
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
usleep(1); // sched_yield();
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
}
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
return NULL;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
int rr = -1;
|
2015-05-15 12:55:52 +02:00
|
|
|
int32_t rr_distribution_func(pfring_zc_pkt_buff* pkt_handle, pfring_zc_queue* in_queue, void* user) {
|
|
|
|
long num_out_queues = (long)user;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (++rr == num_out_queues) {
|
|
|
|
rr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rr;
|
|
|
|
}
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
int bind2core(int core_id) {
|
|
|
|
cpu_set_t cpuset;
|
|
|
|
int s;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
if (core_id < 0) return -1;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
CPU_ZERO(&cpuset);
|
|
|
|
CPU_SET(core_id, &cpuset);
|
|
|
|
if ((s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) != 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "Error while binding to core:" << core_id;
|
|
|
|
return -1;
|
2015-02-04 13:00:06 +01:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-05-15 12:55:52 +02:00
|
|
|
void* zc_packet_consumer_thread(void* _id) {
|
|
|
|
long id = (long)_id;
|
|
|
|
pfring_zc_pkt_buff* b = buffers[id];
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// 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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
u_char* pkt_data = pfring_zc_pkt_buff_data(b, outzq[id]);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
memset(&zc_header, 0, sizeof(zc_header));
|
2015-05-15 12:55:52 +02:00
|
|
|
zc_header.len = b->len;
|
2015-02-04 13:00:06 +01:00
|
|
|
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);
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
int max_packet_len(const char* device) {
|
2015-02-04 13:00:06 +01:00
|
|
|
int max_len = 0;
|
|
|
|
|
|
|
|
pfring* ring = pfring_open(device, 1536, PF_RING_PROMISC);
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
if (ring == NULL) return 1536;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// pfring_get_card_settings have added in 6.0.3
|
2015-05-15 12:55:52 +02:00
|
|
|
// 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
|
2015-03-24 11:27:40 +01:00
|
|
|
#if RING_VERSION_NUM >= 0x060003 and !defined(WE_USE_PFRING_FROM_NTOP)
|
2015-02-04 13:00:06 +01:00
|
|
|
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 */;
|
2015-05-15 12:55:52 +02:00
|
|
|
max_len += 14 /* Eth */ + 4 /* VLAN */;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pfring_close(ring);
|
|
|
|
|
|
|
|
return max_len;
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
#define MAX_CARD_SLOTS 32768
|
|
|
|
#define PREFETCH_BUFFERS 8
|
|
|
|
#define QUEUE_LEN 8192
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-02-24 17:53:41 +01:00
|
|
|
#ifdef PF_RING_ZC
|
2015-02-04 13:00:06 +01:00
|
|
|
bool zc_main_loop(const char* device) {
|
|
|
|
u_int32_t cluster_id = 0;
|
|
|
|
int bind_core = -1;
|
2015-05-15 12:55:52 +02:00
|
|
|
|
|
|
|
u_int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
|
|
|
logger << log4cpp::Priority::INFO << "We have: " << num_cpus << " logical cpus in this server";
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// TODO: add support for multiple devices!
|
|
|
|
u_int32_t num_devices = 1;
|
2015-05-15 12:55:52 +02:00
|
|
|
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 */
|
|
|
|
);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (zc == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
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;
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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*));
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
for (int i = 0; i < zc_num_threads; i++) {
|
2015-02-04 13:00:06 +01:00
|
|
|
buffers[i] = pfring_zc_get_packet_handle(zc);
|
|
|
|
|
|
|
|
if (buffers[i] == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "pfring_zc_get_packet_handle failed";
|
2015-02-04 13:00:06 +01:00
|
|
|
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) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "pfring_zc_open_device error " << strerror(errno)
|
|
|
|
<< " Please check that device is up and not already used";
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if RING_VERSION_NUM >= 0x060003
|
|
|
|
int pf_ring_license_state = pfring_zc_check_license();
|
|
|
|
|
|
|
|
if (!pf_ring_license_state) {
|
2015-05-15 12:55:52 +02:00
|
|
|
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
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
for (int i = 0; i < zc_num_threads; i++) {
|
2015-02-04 13:00:06 +01:00
|
|
|
outzq[i] = pfring_zc_create_queue(zc, QUEUE_LEN);
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
if (outzq[i] == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "pfring_zc_create_queue error: " << strerror(errno);
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
wsp = pfring_zc_create_buffer_pool(zc, PREFETCH_BUFFERS);
|
|
|
|
|
|
|
|
if (wsp == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "pfring_zc_create_buffer_pool error";
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
logger << log4cpp::Priority::INFO << "We are starting balancer with: " << zc_num_threads
|
|
|
|
<< " threads";
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
pfring_zc_distribution_func func = rr_distribution_func;
|
|
|
|
|
|
|
|
u_int8_t wait_for_packet = 1;
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
// We run balancer at last thread
|
2015-06-09 13:56:32 +02:00
|
|
|
int32_t bind_worker_core = zc_num_threads;
|
|
|
|
|
|
|
|
logger << log4cpp::Priority::INFO << "We will run balancer on core: " << bind_worker_core;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (zw == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR << "pfring_zc_run_balancer error:" << strerror(errno);
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
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);
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
return true;
|
|
|
|
}
|
2015-02-24 17:53:41 +01:00
|
|
|
#endif
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
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;
|
2015-05-15 12:55:52 +02:00
|
|
|
bool dont_strip_timestamps = false;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
u_int32_t flags = 0;
|
2015-05-15 12:55:52 +02:00
|
|
|
if (num_threads > 1) flags |= PF_RING_REENTRANT;
|
2015-02-04 13:00:06 +01:00
|
|
|
if (use_extended_pkt_header) flags |= PF_RING_LONG_HEADER;
|
2015-05-15 12:55:52 +02:00
|
|
|
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;
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (!we_use_pf_ring_in_kernel_parser) {
|
|
|
|
flags |= PF_RING_DO_NOT_PARSE;
|
|
|
|
}
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
flags |= PF_RING_DNA_SYMMETRIC_RSS; /* Note that symmetric RSS is ignored by non-DNA drivers */
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
// use default value from pfcount.c
|
|
|
|
unsigned int snaplen = 128;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
pf_ring_descr = pfring_open(dev, snaplen, flags);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (pf_ring_descr == NULL) {
|
2015-05-15 12:55:52 +02:00
|
|
|
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
|
|
|
|
<< ")";
|
2015-02-04 13:00:06 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "Successully binded to: " << dev;
|
2015-07-30 17:20:24 +02:00
|
|
|
|
|
|
|
// We need cast to int because in other way it will be interpreted as char :(
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO
|
2015-07-30 17:20:24 +02:00
|
|
|
<< "Device RX channels number: " << int(pfring_get_num_rx_channels(pf_ring_descr));
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
u_int32_t version;
|
|
|
|
// Set spplication name in /proc
|
|
|
|
int pfring_set_application_name_result =
|
2015-05-15 12:55:52 +02:00
|
|
|
pfring_set_application_name(pf_ring_descr, (char*)"fastnetmon");
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (pfring_set_application_name_result != 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::ERROR
|
2017-05-08 16:21:52 +02:00
|
|
|
<< "Can't set program name for PF_RING: pfring_set_application_name";
|
2015-02-04 13:00:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pfring_version(pf_ring_descr, &version);
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
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);
|
2015-02-04 13:00:06 +01:00
|
|
|
|
|
|
|
if (pfring_set_socket_mode_result != 0) {
|
|
|
|
logger.info("pfring_set_socket_mode returned [rc=%d]\n", pfring_set_socket_mode_result);
|
2015-05-15 12:55:52 +02:00
|
|
|
}
|
|
|
|
|
2015-02-04 13:00:06 +01:00
|
|
|
// enable ring
|
|
|
|
if (pfring_enable_ring(pf_ring_descr) != 0) {
|
2015-05-15 12:55:52 +02:00
|
|
|
logger << log4cpp::Priority::INFO << "Unable to enable ring :-(";
|
2015-02-04 13:00:06 +01:00
|
|
|
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;
|
|
|
|
}
|