blob: 6400ebb49a7c51cc53695e47154503ff70583061 [file] [log] [blame]
/*
*
* (C) 2005-13 - ntop.org
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesses General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#ifndef _PFRING_H_
#define _PFRING_H_
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
#ifndef HAVE_PCAP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#endif
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <time.h>
#include <poll.h>
#include <string.h>
#include <pthread.h>
#include <linux/pf_ring.h>
#include <linux/if_ether.h>
#ifdef HAVE_REDIRECTOR
#include <librdi.h>
#endif
#define MAX_CAPLEN 65535
#define PAGE_SIZE 4096
#define DEFAULT_POLL_DURATION 500
#define POLL_SLEEP_STEP 10 /* ns = 0.1 ms */
#define POLL_SLEEP_MIN POLL_SLEEP_STEP
#define POLL_SLEEP_MAX 1000 /* ns */
#define POLL_QUEUE_MIN_LEN 500 /* # packets */
#ifndef HAVE_RW_LOCK
#define pthread_rwlock_t pthread_mutex_t
#define pthread_rwlock_init pthread_mutex_init
#define pthread_rwlock_rdlock pthread_mutex_lock
#define pthread_rwlock_wrlock pthread_mutex_lock
#define pthread_rwlock_unlock pthread_mutex_unlock
#define pthread_rwlock_destroy pthread_mutex_destroy
#endif
#ifndef max
#define max(a, b) (a > b ? a : b)
#endif
#define timespec_is_before(a, b) \
((((a)->tv_sec<(b)->tv_sec)||(((a)->tv_sec==(b)->tv_sec)&&((a)->tv_nsec<(b)->tv_nsec)))?1:0)
/* ********************************* */
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
/* ********************************* */
/*
See also __builtin_prefetch
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
*/
#define prefetch(x) __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x));
/* ********************************* */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef SAFE_RING_MODE
static char staticBucket[2048];
#endif
typedef void (*pfringProcesssPacket)(const struct pfring_pkthdr *h, const u_char *p, const u_char *user_bytes);
/* ********************************* */
typedef struct __pfring pfring; /* Forward declaration */
/* ********************************* */
#define MAX_NUM_BUNDLE_ELEMENTS 32
typedef enum {
pick_round_robin = 0,
pick_fifo
} bundle_read_policy;
typedef struct {
bundle_read_policy policy;
u_int16_t num_sockets, last_read_socket;
pfring *sockets[MAX_NUM_BUNDLE_ELEMENTS];
struct pollfd pfd[MAX_NUM_BUNDLE_ELEMENTS];
} pfring_bundle;
/* ********************************* */
typedef struct {
u_int64_t recv, drop, droppedbyfilter;
} pfring_stat;
/* ********************************* */
typedef enum {
hardware_and_software = 0,
hardware_only,
software_only
} filtering_mode;
/* ********************************* */
typedef void pfring_pkt_buff;
/* ********************************* */
struct __pfring {
u_int8_t initialized, enabled, long_header, rss_mode, force_timestamp, strip_hw_timestamp,
disable_parsing, disable_timestamp;
packet_direction direction; /* Specify the capture direction for packets */
socket_mode mode;
/* Hardware Timestamp */
struct {
u_int8_t force_timestamp, is_silicom_hw_timestamp_card, enable_hw_timestamp;
u_int32_t last_hw_timestamp_sec, last_hw_timestamp_nsec;
} hw_ts;
struct {
u_int8_t enabled_rx_packet_send;
struct pfring_pkthdr *last_received_hdr; /*
Header of the past packet
that has been received on this socket
*/
} tx;
/* TODO these fields should be moved in ->priv_data */
/* DNA (Direct NIC Access) */
struct {
u_int8_t dna_mapped_device;
u_int32_t sampling_counter;
u_int16_t num_rx_pkts_before_dna_sync, num_tx_pkts_before_dna_sync;
u_int16_t dna_rx_sync_watermark, dna_tx_sync_watermark;
u_int64_t tot_dna_read_pkts, tot_dna_lost_pkts;
u_int32_t rx_reg, tx_reg, last_rx_slot_read;
u_int32_t num_rx_slots_per_chunk, num_tx_slots_per_chunk;
dna_device dna_dev;
dna_indexes *indexes_ptr;
u_int32_t *rx_reg_ptr, *tx_reg_ptr, *mpc_reg_ptr, *qprdc_reg_ptr,
*rnbc_reg_ptr, *rqdpc_reg_ptr, *gorc_reg_ptr;
dna_device_operation last_dna_operation;
} dna;
void *priv_data; /* module private data */
void (*close) (pfring *);
int (*stats) (pfring *, pfring_stat *);
int (*recv) (pfring *, u_char**, u_int, struct pfring_pkthdr *, u_int8_t);
int (*set_poll_watermark) (pfring *, u_int16_t);
int (*set_poll_duration) (pfring *, u_int);
int (*set_tx_watermark) (pfring *, u_int16_t);
int (*set_channel_id) (pfring *, u_int32_t);
int (*set_channel_mask) (pfring *, u_int32_t);
int (*set_application_name) (pfring *, char *);
int (*set_application_stats) (pfring *, char *);
char* (*get_appl_stats_file_name) (pfring *ring, char *path, u_int path_len);
int (*bind) (pfring *, char *);
int (*send) (pfring *, char *, u_int, u_int8_t);
int (*send_ifindex) (pfring *, char *, u_int, u_int8_t, int);
int (*send_parsed) (pfring *, char *, struct pfring_pkthdr *, u_int8_t);
int (*send_get_time) (pfring *, char *, u_int, struct timespec *);
u_int8_t (*get_num_rx_channels) (pfring *);
int (*set_sampling_rate) (pfring *, u_int32_t);
int (*get_selectable_fd) (pfring *);
int (*set_direction) (pfring *, packet_direction);
int (*set_socket_mode) (pfring *, socket_mode);
int (*set_cluster) (pfring *, u_int, cluster_type);
int (*remove_from_cluster) (pfring *);
int (*set_master_id) (pfring *, u_int32_t);
int (*set_master) (pfring *, pfring *);
u_int16_t (*get_ring_id) (pfring *);
u_int32_t (*get_num_queued_pkts) (pfring *);
u_int8_t (*get_packet_consumer_mode) (pfring *);
int (*set_packet_consumer_mode) (pfring *, u_int8_t, char *, u_int);
int (*get_hash_filtering_rule_stats)(pfring *, hash_filtering_rule *, char *, u_int *);
int (*handle_hash_filtering_rule) (pfring *, hash_filtering_rule *, u_char);
int (*purge_idle_hash_rules) (pfring *, u_int16_t);
int (*add_filtering_rule) (pfring *, filtering_rule *);
int (*remove_filtering_rule) (pfring *, u_int16_t);
int (*purge_idle_rules) (pfring *, u_int16_t);
int (*get_filtering_rule_stats) (pfring *, u_int16_t, char *, u_int *);
int (*toggle_filtering_policy) (pfring *, u_int8_t);
int (*enable_rss_rehash) (pfring *);
int (*poll) (pfring *, u_int);
int (*is_pkt_available) (pfring *);
int (*next_pkt_time) (pfring *, struct timespec *);
int (*next_pkt_raw_timestamp) (pfring *, u_int64_t *ts);
int (*version) (pfring *, u_int32_t *);
int (*get_bound_device_address) (pfring *, u_char [6]);
int (*get_bound_device_ifindex) (pfring *, int *);
int (*get_device_ifindex) (pfring *, char *, int *);
u_int16_t (*get_slot_header_len) (pfring *);
int (*set_virtual_device) (pfring *, virtual_filtering_device_info *);
int (*add_hw_rule) (pfring *, hw_filtering_rule *);
int (*remove_hw_rule) (pfring *, u_int16_t);
int (*loopback_test) (pfring *, char *, u_int, u_int);
int (*enable_ring) (pfring *);
int (*disable_ring) (pfring *);
void (*shutdown) (pfring *);
int (*set_bpf_filter) (pfring *, char *);
int (*remove_bpf_filter) (pfring *);
int (*get_device_clock) (pfring *, struct timespec *);
int (*set_device_clock) (pfring *, struct timespec *);
int (*adjust_device_clock) (pfring *, struct timespec *, int8_t);
void (*sync_indexes_with_kernel) (pfring *);
int (*send_last_rx_packet) (pfring *, int);
u_char* (*get_pkt_buff_data) (pfring *, pfring_pkt_buff *);
int (*set_pkt_buff_len) (pfring *, pfring_pkt_buff *, u_int32_t);
int (*set_pkt_buff_ifindex) (pfring *, pfring_pkt_buff *, int);
int (*add_pkt_buff_ifindex) (pfring *, pfring_pkt_buff *, int);
pfring_pkt_buff* (*alloc_pkt_buff) (pfring *);
void (*release_pkt_buff) (pfring *, pfring_pkt_buff *);
int (*recv_pkt_buff) (pfring *, pfring_pkt_buff *, struct pfring_pkthdr *, u_int8_t);
int (*send_pkt_buff) (pfring *, pfring_pkt_buff *, u_int8_t);
void (*flush_tx_packets) (pfring *);
int (*register_zerocopy_tx_ring) (pfring *, pfring *);
/* DNA only */
int (*dna_init) (pfring *);
void (*dna_term) (pfring *);
int (*dna_enable) (pfring *);
u_int8_t (*dna_check_packet_to_read) (pfring *, u_int8_t);
u_char* (*dna_next_packet) (pfring *, u_char **, u_int, struct pfring_pkthdr *);
u_int (*dna_get_num_tx_slots)(pfring* ring);
u_int (*dna_get_num_rx_slots)(pfring* ring);
u_int (*dna_get_next_free_tx_slot)(pfring* ring);
int (*dna_copy_tx_packet_into_slot)(pfring* ring, u_int32_t tx_slot_id, char* buffer, u_int len);
/* Silicom Redirector Only */
struct {
int8_t device_id, port_id;
} rdi;
filtering_mode ft_mode;
pfring_device_type ft_device_type;
void *qat; /* Intel QAT PM */
/* All devices */
char *buffer, *slots, *device_name;
u_int32_t caplen;
u_int16_t slot_header_len, mtu_len /* 0 = unknown */;
u_int32_t sampling_rate;
u_int8_t kernel_packet_consumer, is_shutting_down, socket_default_accept_policy;
int fd;
FlowSlotInfo *slots_info;
u_int poll_sleep;
u_int16_t poll_duration;
u_int8_t promisc, clear_promisc, reentrant, break_recv_loop;
u_long num_poll_calls;
pthread_rwlock_t rx_lock, tx_lock;
struct sockaddr_ll sock_tx;
/* Reflector socket (copy RX packets onto it) */
pfring *reflector_socket;
};
/* ********************************* */
#define PF_RING_DNA_SYMMETRIC_RSS 1 << 0
#define PF_RING_REENTRANT 1 << 1
#define PF_RING_LONG_HEADER 1 << 2
#define PF_RING_PROMISC 1 << 3
#define PF_RING_TIMESTAMP 1 << 4
#define PF_RING_HW_TIMESTAMP 1 << 5
#define PF_RING_RX_PACKET_BOUNCE 1 << 6
#define PF_RING_DNA_FIXED_RSS_Q_0 1 << 7
#define PF_RING_STRIP_HW_TIMESTAMP 1 << 8
#define PF_RING_DO_NOT_PARSE 1 << 9 /* parsing already disabled in zero-copy */
#define PF_RING_DO_NOT_TIMESTAMP 1 << 10 /* sw timestamp already disabled in zero-copy */
/* ********************************* */
pfring* pfring_open(const char *device_name, u_int32_t caplen, u_int32_t flags);
pfring* pfring_open_consumer(const char *device_name, u_int32_t caplen, u_int32_t flags,
u_int8_t consumer_plugin_id,
char* consumer_data, u_int consumer_data_len);
u_int8_t pfring_open_multichannel(const char *device_name, u_int32_t caplen,
u_int32_t flags, pfring* ring[MAX_NUM_RX_CHANNELS]);
void pfring_shutdown(pfring *ring);
void pfring_config(u_short cpu_percentage);
int pfring_loop(pfring *ring, pfringProcesssPacket looper,
const u_char *user_bytes, u_int8_t wait_for_packet);
void pfring_breakloop(pfring *);
void pfring_close(pfring *ring);
int pfring_stats(pfring *ring, pfring_stat *stats);
int pfring_recv(pfring *ring, u_char** buffer, u_int buffer_len,
struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet);
int pfring_recv_parsed(pfring *ring, u_char** buffer, u_int buffer_len,
struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet,
u_int8_t level /* 1..4 */, u_int8_t add_timestamp, u_int8_t add_hash);
int pfring_set_poll_watermark(pfring *ring, u_int16_t watermark);
int pfring_set_poll_duration(pfring *ring, u_int duration);
int pfring_set_tx_watermark(pfring *ring, u_int16_t watermark);
int pfring_add_hw_rule(pfring *ring, hw_filtering_rule *rule);
int pfring_remove_hw_rule(pfring *ring, u_int16_t rule_id);
int pfring_set_channel_id(pfring *ring, u_int32_t channel_id);
int pfring_set_channel_mask(pfring *ring, u_int32_t channel_mask);
int pfring_set_application_name(pfring *ring, char *name);
int pfring_set_application_stats(pfring *ring, char *stats);
char* pfring_get_appl_stats_file_name(pfring *ring, char *path, u_int path_len);
int pfring_bind(pfring *ring, char *device_name);
int pfring_send(pfring *ring, char *pkt, u_int pkt_len, u_int8_t flush_packet);
int pfring_send_ifindex(pfring *ring, char *pkt, u_int pkt_len, u_int8_t flush_packet, int if_index);
int pfring_send_parsed(pfring *ring, char *pkt, struct pfring_pkthdr *hdr, u_int8_t flush_packet);
int pfring_send_get_time(pfring *ring, char *pkt, u_int pkt_len, struct timespec *ts);
u_int8_t pfring_get_num_rx_channels(pfring *ring);
int pfring_set_sampling_rate(pfring *ring, u_int32_t rate /* 1 = no sampling */);
int pfring_get_selectable_fd(pfring *ring);
int pfring_set_direction(pfring *ring, packet_direction direction);
int pfring_set_socket_mode(pfring *ring, socket_mode mode);
int pfring_set_cluster(pfring *ring, u_int clusterId, cluster_type the_type);
int pfring_remove_from_cluster(pfring *ring);
int pfring_set_master_id(pfring *ring, u_int32_t master_id);
int pfring_set_master(pfring *ring, pfring *master);
u_int16_t pfring_get_ring_id(pfring *ring);
u_int32_t pfring_get_num_queued_pkts(pfring *ring);
u_int8_t pfring_get_packet_consumer_mode(pfring *ring);
int pfring_set_packet_consumer_mode(pfring *ring, u_int8_t plugin_id,
char *plugin_data, u_int plugin_data_len);
int pfring_handle_hash_filtering_rule(pfring *ring,
hash_filtering_rule* rule_to_add,
u_char add_rule);
int pfring_add_filtering_rule(pfring *ring, filtering_rule* rule_to_add);
int pfring_remove_filtering_rule(pfring *ring, u_int16_t rule_id);
int pfring_purge_idle_hash_rules(pfring *ring, u_int16_t inactivity_sec);
int pfring_purge_idle_rules(pfring *ring, u_int16_t inactivity_sec);
int pfring_get_hash_filtering_rule_stats(pfring *ring,
hash_filtering_rule* rule,
char* stats, u_int *stats_len);
int pfring_get_filtering_rule_stats(pfring *ring, u_int16_t rule_id,
char* stats, u_int *stats_len);
int pfring_toggle_filtering_policy(pfring *ring, u_int8_t rules_default_accept_policy);
int pfring_enable_rss_rehash(pfring *ring);
int pfring_poll(pfring *ring, u_int wait_duration);
int pfring_is_pkt_available(pfring *ring);
int pfring_next_pkt_time(pfring *ring, struct timespec *ts);
int pfring_next_pkt_raw_timestamp(pfring *ring, u_int64_t *timestamp_ns);
int pfring_version(pfring *ring, u_int32_t *version);
int pfring_set_reflector_device(pfring *ring, char *device_name);
int pfring_get_bound_device_address(pfring *ring, u_char mac_address[6]);
u_int16_t pfring_get_slot_header_len(pfring *ring);
int pfring_get_bound_device_ifindex(pfring *ring, int *if_index);
int pfring_get_device_ifindex(pfring *ring, char *device_name, int *if_index);
int pfring_set_virtual_device(pfring *ring, virtual_filtering_device_info *info);
int pfring_loopback_test(pfring *ring, char *buffer, u_int buffer_len, u_int test_len);
int pfring_enable_ring(pfring *ring);
int pfring_disable_ring(pfring *ring);
int pfring_set_bpf_filter(pfring *ring, char *filter_buffer);
int pfring_remove_bpf_filter(pfring *ring);
int pfring_set_filtering_mode(pfring *ring, filtering_mode mode);
int pfring_get_device_clock(pfring *ring, struct timespec *ts);
int pfring_set_device_clock(pfring *ring, struct timespec *ts);
int pfring_adjust_device_clock(pfring *ring, struct timespec *offset, int8_t sign);
void pfring_sync_indexes_with_kernel(pfring *ring);
int pfring_send_last_rx_packet(pfring *ring, int tx_interface_id);
u_int pfring_get_num_tx_slots(pfring* ring);
u_int pfring_get_num_rx_slots(pfring* ring);
int pfring_copy_tx_packet_into_slot(pfring* ring, u_int16_t tx_slot_id, char* buffer, u_int len);
u_char* pfring_get_pkt_buff_data(pfring *ring, pfring_pkt_buff *pkt_handle);
int pfring_set_pkt_buff_len(pfring *ring, pfring_pkt_buff *pkt_handle, u_int32_t len);
int pfring_set_pkt_buff_ifindex(pfring *ring, pfring_pkt_buff *pkt_handle, int if_index);
int pfring_add_pkt_buff_ifindex(pfring *ring, pfring_pkt_buff *pkt_handle, int if_index);
pfring_pkt_buff* pfring_alloc_pkt_buff(pfring *ring);
void pfring_release_pkt_buff(pfring *ring, pfring_pkt_buff *pkt_handle);
int pfring_recv_pkt_buff(pfring *ring, pfring_pkt_buff *pkt_handle, struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet); /* Note: this function fills the buffer pointed by pkt_handle */
int pfring_send_pkt_buff(pfring *ring, pfring_pkt_buff *pkt_handle, u_int8_t flush_packet); /* Note: this function reset the buffer pointed by pkt_handle */
int pfring_flush_tx_packets(pfring *ring);
int pfring_search_payload(pfring *ring, char *string_to_search);
int pfring_register_zerocopy_tx_ring(pfring *ring, pfring *tx_ring);
/* PF_RING Socket bundle */
void pfring_bundle_init(pfring_bundle *bundle, bundle_read_policy p);
int pfring_bundle_add(pfring_bundle *bundle, pfring *ring);
int pfring_bundle_poll(pfring_bundle *bundle, u_int wait_duration);
int pfring_bundle_read(pfring_bundle *bundle,
u_char** buffer, u_int buffer_len,
struct pfring_pkthdr *hdr,
u_int8_t wait_for_incoming_packet);
void pfring_bundle_destroy(pfring_bundle *bundle);
void pfring_bundle_close(pfring_bundle *bundle);
/* Utils (defined in pfring_utils.c) */
int pfring_parse_pkt(u_char *pkt, struct pfring_pkthdr *hdr, u_int8_t level /* 2..4 */,
u_int8_t add_timestamp /* 0,1 */, u_int8_t add_hash /* 0,1 */);
int pfring_set_if_promisc(const char *device, int set_promisc);
char* pfring_format_numbers(double val, char *buf, u_int buf_len, u_int8_t add_decimals);
int pfring_enable_hw_timestamp(pfring* ring, char *device_name, u_int8_t enable_rx, u_int8_t enable_tx);
int pfring_get_mtu_size(pfring* ring);
/* ********************************* */
typedef struct {
char *name;
int (*open) (pfring *);
} pfring_module_info;
#ifdef HAVE_ZERO
#include "pfring_zero.h"
#endif
#ifdef __cplusplus
}
#endif
#endif /* _PFRING_H_ */