Added PPS and BPS options. Cleaned code.
This commit is contained in:
25
src/config.c
25
src/config.c
@@ -39,6 +39,12 @@ void SetConfigDefaults(struct config_map *cfg)
|
|||||||
cfg->filters[i].do_tos = 0;
|
cfg->filters[i].do_tos = 0;
|
||||||
cfg->filters[i].tos = 0;
|
cfg->filters[i].tos = 0;
|
||||||
|
|
||||||
|
cfg->filters[i].do_pps = 0;
|
||||||
|
cfg->filters[i].pps = 0;
|
||||||
|
|
||||||
|
cfg->filters[i].do_bps = 0;
|
||||||
|
cfg->filters[i].bps = 0;
|
||||||
|
|
||||||
cfg->filters[i].tcpopts.enabled = 0;
|
cfg->filters[i].tcpopts.enabled = 0;
|
||||||
cfg->filters[i].tcpopts.do_dport = 0;
|
cfg->filters[i].tcpopts.do_dport = 0;
|
||||||
cfg->filters[i].tcpopts.do_dport = 0;
|
cfg->filters[i].tcpopts.do_dport = 0;
|
||||||
@@ -124,7 +130,6 @@ int ReadConfig(struct config_map *cfg)
|
|||||||
|
|
||||||
cfg->interface = strdup(interface);
|
cfg->interface = strdup(interface);
|
||||||
|
|
||||||
|
|
||||||
// Get auto update time.
|
// Get auto update time.
|
||||||
int updateTime;
|
int updateTime;
|
||||||
|
|
||||||
@@ -255,6 +260,24 @@ int ReadConfig(struct config_map *cfg)
|
|||||||
cfg->filters[i].do_tos = 1;
|
cfg->filters[i].do_tos = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PPS (not required).
|
||||||
|
long long pps;
|
||||||
|
|
||||||
|
if (config_setting_lookup_int64(filter, "pps", &pps))
|
||||||
|
{
|
||||||
|
cfg->filters[i].pps = pps;
|
||||||
|
cfg->filters[i].do_pps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPS (not required).
|
||||||
|
long long bps;
|
||||||
|
|
||||||
|
if (config_setting_lookup_int64(filter, "bps", &bps))
|
||||||
|
{
|
||||||
|
cfg->filters[i].bps = bps;
|
||||||
|
cfg->filters[i].do_bps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Payload match.
|
// Payload match.
|
||||||
const char *payload;
|
const char *payload;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#define MAX_PCKT_LENGTH 65535
|
#define MAX_PCKT_LENGTH 65535
|
||||||
#define MAX_FILTERS 50
|
#define MAX_FILTERS 50
|
||||||
|
#define MAX_CPUS 128
|
||||||
|
#define LRU_MAP_SIZE 16384
|
||||||
|
|
||||||
struct tcpopts
|
struct tcpopts
|
||||||
{
|
{
|
||||||
@@ -84,6 +86,12 @@ struct filter
|
|||||||
unsigned int do_tos : 1;
|
unsigned int do_tos : 1;
|
||||||
int8_t tos;
|
int8_t tos;
|
||||||
|
|
||||||
|
unsigned int do_pps : 1;
|
||||||
|
uint64_t pps;
|
||||||
|
|
||||||
|
unsigned int do_bps : 1;
|
||||||
|
uint64_t bps;
|
||||||
|
|
||||||
uint8_t payloadMatch[MAX_PCKT_LENGTH];
|
uint8_t payloadMatch[MAX_PCKT_LENGTH];
|
||||||
uint16_t payloadLen;
|
uint16_t payloadLen;
|
||||||
|
|
||||||
@@ -98,5 +106,11 @@ struct xdpfw_stats
|
|||||||
uint64_t blocked;
|
uint64_t blocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xdpfw_ip_stats
|
||||||
|
{
|
||||||
|
uint64_t pps;
|
||||||
|
uint64_t bps;
|
||||||
|
uint64_t tracking;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <linux/bpf.h>
|
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
@@ -6,15 +5,17 @@
|
|||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "../libbpf/src/bpf_helpers.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <linux/bpf_common.h>
|
||||||
|
|
||||||
|
#include "../libbpf/src/bpf_helpers.h"
|
||||||
|
|
||||||
#include "include/xdpfw.h"
|
#include "include/xdpfw.h"
|
||||||
|
|
||||||
//#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
@@ -27,7 +28,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SEC(NAME) __attribute__((section(NAME), used))
|
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
@@ -58,6 +58,14 @@ struct bpf_map_def SEC("maps") stats_map =
|
|||||||
.max_entries = 1
|
.max_entries = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bpf_map_def SEC("maps") ip_stats_map =
|
||||||
|
{
|
||||||
|
.type = BPF_MAP_TYPE_PERCPU_HASH,
|
||||||
|
.key_size = sizeof(uint32_t),
|
||||||
|
.value_size = sizeof(struct xdpfw_ip_stats),
|
||||||
|
.max_entries = LRU_MAP_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
SEC("xdp_prog")
|
SEC("xdp_prog")
|
||||||
int xdp_prog_main(struct xdp_md *ctx)
|
int xdp_prog_main(struct xdp_md *ctx)
|
||||||
{
|
{
|
||||||
@@ -105,6 +113,44 @@ int xdp_prog_main(struct xdp_md *ctx)
|
|||||||
return XDP_PASS;
|
return XDP_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update IP stats (PPS/BPS).
|
||||||
|
uint64_t pps = 0;
|
||||||
|
uint64_t bps = 0;
|
||||||
|
uint64_t now = bpf_ktime_get_ns();
|
||||||
|
|
||||||
|
struct xdpfw_ip_stats *ip_stats = bpf_map_lookup_elem(&ip_stats_map, &iph->saddr);
|
||||||
|
|
||||||
|
if (ip_stats)
|
||||||
|
{
|
||||||
|
// Check for reset.
|
||||||
|
if ((now - ip_stats->tracking) > 1e9)
|
||||||
|
{
|
||||||
|
ip_stats->pps = 0;
|
||||||
|
ip_stats->bps = 0;
|
||||||
|
ip_stats->tracking = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_stats->pps++;
|
||||||
|
ip_stats->bps += ctx->data_end - ctx->data;
|
||||||
|
|
||||||
|
pps = ip_stats->pps;
|
||||||
|
bps = ip_stats->bps;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create new entry.
|
||||||
|
struct xdpfw_ip_stats new;
|
||||||
|
|
||||||
|
new.pps = 1;
|
||||||
|
new.bps = ctx->data_end - ctx->data;
|
||||||
|
new.tracking = now;
|
||||||
|
|
||||||
|
pps = new.pps;
|
||||||
|
bps = new.bps;
|
||||||
|
|
||||||
|
bpf_map_update_elem(&ip_stats_map, &iph->saddr, &new, BPF_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
struct tcphdr *tcph;
|
struct tcphdr *tcph;
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
struct icmphdr *icmph;
|
struct icmphdr *icmph;
|
||||||
@@ -211,24 +257,40 @@ int xdp_prog_main(struct xdp_md *ctx)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PPS.
|
||||||
|
if (filter[i]->do_pps && pps <= filter[i]->pps)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPS.
|
||||||
|
if (filter[i]->do_bps && bps <= filter[i]->bps)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Payload match.
|
// Payload match.
|
||||||
/*
|
/*
|
||||||
if (filter[i]->payloadLen > 0)
|
if (filter[i]->payloadLen > 0)
|
||||||
{
|
{
|
||||||
uint8_t found = 1;
|
uint8_t found = 1;
|
||||||
uint16_t len = filter[i]->payloadLen;
|
|
||||||
|
|
||||||
// Initialize packet data.
|
// Initialize packet data.
|
||||||
uint8_t *pcktData = (data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4headerLen);
|
for (uint16_t j = 0; j < MAX_PCKT_LENGTH; j++)
|
||||||
|
|
||||||
if (pcktData + len > (uint8_t *)data_end)
|
|
||||||
{
|
{
|
||||||
continue;
|
if ((j + 1) > filter[i]->payloadLen)
|
||||||
}
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint16_t j = 0; j < filter[i]->payloadLen; j++)
|
uint8_t *byte = (data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4headerLen + j);
|
||||||
{
|
|
||||||
if ((*pcktData++) == filter[i]->payloadMatch[j])
|
if (byte + 1 > (uint8_t *)data_end)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*byte == filter[i]->payloadMatch[j])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -341,7 +403,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
|||||||
|
|
||||||
// Matched.
|
// Matched.
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bpf_printk("Matched rule ID #%" PRIu8 "\n", filter[i]->id);
|
bpf_printk("Matched rule ID #%" PRIu8 ".\n", filter[i]->id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
matched = 1;
|
matched = 1;
|
||||||
@@ -376,7 +438,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bpf_printk("Matched with protocol %" PRIu8 " and sAddr %" PRIu32 "\n", iph->protocol, iph->saddr);
|
//bpf_printk("Matched with protocol %" PRIu8 " and sAddr %" PRIu32 ".\n", iph->protocol, iph->saddr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <linux/if_link.h>
|
#include <linux/if_link.h>
|
||||||
@@ -330,7 +331,9 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stdout, "Min Length => %" PRIu16 "\n", conf->filters[i].min_len);
|
fprintf(stdout, "Min Length => %" PRIu16 "\n", conf->filters[i].min_len);
|
||||||
fprintf(stdout, "Max TTL => %" PRIu8 "\n", conf->filters[i].max_ttl);
|
fprintf(stdout, "Max TTL => %" PRIu8 "\n", conf->filters[i].max_ttl);
|
||||||
fprintf(stdout, "Min TTL => %" PRIu8 "\n", conf->filters[i].min_ttl);
|
fprintf(stdout, "Min TTL => %" PRIu8 "\n", conf->filters[i].min_ttl);
|
||||||
fprintf(stdout, "TOS => %" PRIu8 "\n\n", conf->filters[i].tos);
|
fprintf(stdout, "TOS => %" PRIu8 "\n", conf->filters[i].tos);
|
||||||
|
fprintf(stdout, "PPS => %" PRIu64 "\n", conf->filters[i].pps);
|
||||||
|
fprintf(stdout, "BPS => %" PRIu64 "\n\n", conf->filters[i].bps);
|
||||||
|
|
||||||
// TCP Options.
|
// TCP Options.
|
||||||
fprintf(stdout, "TCP Enabled => %" PRIu8 "\n", conf->filters[i].tcpopts.enabled);
|
fprintf(stdout, "TCP Enabled => %" PRIu8 "\n", conf->filters[i].tcpopts.enabled);
|
||||||
|
|||||||
Reference in New Issue
Block a user