Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests on filters #502

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions bpf/counters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef __COUNTERS_H__
#define __COUNTERS_H__

#include <bpf_core_read.h>
#include "maps_definition.h"

// Update global counter for hashmap update errors
static inline void increase_counter(u32 key) {
u32 *error_counter_p = NULL;
u32 initVal = 1;
error_counter_p = bpf_map_lookup_elem(&global_counters, &key);
if (!error_counter_p) {
bpf_map_update_elem(&global_counters, &key, &initVal, BPF_ANY);
} else {
__sync_fetch_and_add(error_counter_p, 1);
}
}

#endif // __COUNTERS_H__
7 changes: 4 additions & 3 deletions bpf/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include <bpf_helpers.h>
#include "configs.h"
#include "utils.h"
#include "counters.h"

/* Do flow filtering. Is optional. */
#include "flows_filter.h"

/*
* Defines a packet drops statistics tracker,
Expand All @@ -42,9 +46,6 @@
* It is enabled by setting env var ENABLE_PCA= true. Is Optional
*/
#include "pca.h"

/* Do flow filtering. Is optional. */
#include "flows_filter.h"
/*
* Defines an Network events monitoring tracker,
* which runs inside flow_monitor. Is optional.
Expand Down
57 changes: 55 additions & 2 deletions bpf/flows_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#ifndef __FLOWS_FILTER_H__
#define __FLOWS_FILTER_H__

#include "utils.h"

#define BPF_PRINTK(fmt, args...) \
if (trace_messages) \
bpf_printk(fmt, ##args)
Expand Down Expand Up @@ -266,4 +264,59 @@ static __always_inline int is_flow_filtered(flow_id *id, filter_action *action,
return do_flow_filter_lookup(id, &key, action, len, offset, flags, drop_reason, sampling);
}

static inline bool is_filter_enabled() {
if (enable_flows_filtering || enable_pca) {
return true;
}
return false;
}

/*
* check if flow filter is enabled and if we need to continue processing the packet or not
*/
static inline bool check_and_do_flow_filtering(flow_id *id, u16 flags, u32 drop_reason,
u16 eth_protocol, u32 *sampling) {
// check if this packet need to be filtered if filtering feature is enabled
if (is_filter_enabled()) {
filter_action action = ACCEPT;
if (is_flow_filtered(id, &action, flags, drop_reason, eth_protocol, sampling) != 0 &&
action != MAX_FILTER_ACTIONS) {
// we have matching rules follow through the actions to decide if we should accept or reject the flow
// and update global counter for both cases
bool skip = false;
u32 key = 0;

switch (action) {
case REJECT:
key = FILTER_REJECT;
skip = true;
break;
case ACCEPT:
key = FILTER_ACCEPT;
break;
// should never come here
case MAX_FILTER_ACTIONS:
return true;
}

// update global counter for flows dropped by filter
increase_counter(key);
if (skip) {
return true;
}
} else {
// we have no matching rules so we update global counter for flows that are not matched by any rule
increase_counter(FILTER_NOMATCH);
// we have accept rule but no match so we can't let mismatched flows in the hashmap table or
// we have no match at all and the action is the default value MAX_FILTER_ACTIONS.
if (action == ACCEPT || action == MAX_FILTER_ACTIONS) {
return true;
} else {
// we have reject rule and no match so we can add the flows to the hashmap table.
}
}
}
return false;
}

#endif //__FLOWS_FILTER_H__
114 changes: 114 additions & 0 deletions bpf/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <stdio.h>
#include <assert.h>

#define false 0
#define true 1
#define bpf_printk printf

typedef int bool;
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned long __u32;
typedef unsigned long long __u64;

enum {
IPPROTO_ICMP = 1,
IPPROTO_TCP = 6,
IPPROTO_UDP = 17,
IPPROTO_SCTP = 132,
};

struct bpf_spin_lock {
__u32 val;
};

#include "types.h"

volatile u32 sampling = 0;
volatile u8 trace_messages = 0;
volatile u8 enable_rtt = 0;
volatile u8 enable_pca = 0;
volatile u8 enable_dns_tracking = 0;
volatile u8 enable_flows_filtering = 0;
volatile u16 dns_port = 0;
volatile u8 enable_network_events_monitoring = 0;
volatile u8 network_events_monitoring_groupid = 0;
volatile u8 enable_pkt_translation_tracking = 0;

typedef enum mock_scenario_t {
NO_RULE,
REJECT_1_2_3_4_ALLOW_OTHER,
} mock_scenario;

struct mocked_map {
mock_scenario scen;
};

struct filter_value_t reject_filter = {
.action = REJECT,
};
struct filter_value_t accept_filter = {
.action = ACCEPT,
};

volatile struct mocked_map filter_map;

static struct filter_value_t* bpf_map_lookup_elem(struct mocked_map *map, struct filter_key_t *key) {
if (map->scen == NO_RULE) {
return NULL;
}
u8 ip1234[IP_MAX_LEN] = {1, 2, 3, 4};
if (__builtin_memcmp(ip1234, key->ip_data, IP_MAX_LEN) == 0) {
return &reject_filter;
}
return &accept_filter;
}

static void increase_counter(u32 key) {
}

#include "flows_filter.h"

int main(int argc, char *argv[]) {
flow_id id;
filter_action action;
u32 sampling = 0;
filter_map.scen = NO_RULE;
int skip = check_and_do_flow_filtering(&id, 0, 0, ETH_P_IP, &sampling);
printf("skip=%d\n", skip);
assert(skip == 0);
printf("filter disabled [success]\n");

enable_flows_filtering = 1;
skip = check_and_do_flow_filtering(&id, 0, 0, ETH_P_IP, &sampling);
printf("skip=%d\n", skip);
assert(skip == 1);
printf("filter enabled [success]\n");

filter_map.scen = REJECT_1_2_3_4_ALLOW_OTHER;
__builtin_memcpy(id.src_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, IP_MAX_LEN);
__builtin_memcpy(id.dst_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8}, IP_MAX_LEN);
printf("filter should reject from 1.2.3.4 [...]\n");
skip = check_and_do_flow_filtering(&id, 0, 0, ETH_P_IP, &sampling);
printf("skip=%d\n", skip);
assert(skip == 1);
printf("filter reject from 1.2.3.4 [success]\n");

__builtin_memcpy(id.src_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8}, IP_MAX_LEN);
__builtin_memcpy(id.dst_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, IP_MAX_LEN);
printf("filter should reject to 1.2.3.4 [...]\n");
skip = check_and_do_flow_filtering(&id, 0, 0, ETH_P_IP, &sampling);
printf("skip=%d\n", skip);
assert(skip == 1);
printf("filter reject to 1.2.3.4 [success]\n");

__builtin_memcpy(id.src_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5}, IP_MAX_LEN);
__builtin_memcpy(id.dst_ip, (u8[IP_MAX_LEN]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8}, IP_MAX_LEN);
printf("filter should accept others [...]\n");
skip = check_and_do_flow_filtering(&id, 0, 0, ETH_P_IP, &sampling);
printf("skip=%d\n", skip);
assert(skip == 0);
printf("filter accept others [success]\n");

return 0;
}
69 changes: 0 additions & 69 deletions bpf/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,9 @@

#include <bpf_core_read.h>
#include "types.h"
#include "maps_definition.h"
#include "flows_filter.h"

static u8 do_sampling = 0;

// Update global counter for hashmap update errors
static inline void increase_counter(u32 key) {
u32 *error_counter_p = NULL;
u32 initVal = 1;
error_counter_p = bpf_map_lookup_elem(&global_counters, &key);
if (!error_counter_p) {
bpf_map_update_elem(&global_counters, &key, &initVal, BPF_ANY);
} else {
__sync_fetch_and_add(error_counter_p, 1);
}
}

// sets the TCP header flags for connection information
static inline void set_flags(struct tcphdr *th, u16 *flags) {
//If both ACK and SYN are set, then it is server -> client communication during 3-way handshake.
Expand Down Expand Up @@ -174,61 +160,6 @@ static inline int fill_ethhdr(struct ethhdr *eth, void *data_end, pkt_info *pkt,
return SUBMIT;
}

static inline bool is_filter_enabled() {
if (enable_flows_filtering || enable_pca) {
return true;
}
return false;
}

/*
* check if flow filter is enabled and if we need to continue processing the packet or not
*/
static inline bool check_and_do_flow_filtering(flow_id *id, u16 flags, u32 drop_reason,
u16 eth_protocol, u32 *sampling) {
// check if this packet need to be filtered if filtering feature is enabled
if (is_filter_enabled()) {
filter_action action = ACCEPT;
if (is_flow_filtered(id, &action, flags, drop_reason, eth_protocol, sampling) != 0 &&
action != MAX_FILTER_ACTIONS) {
// we have matching rules follow through the actions to decide if we should accept or reject the flow
// and update global counter for both cases
bool skip = false;
u32 key = 0;

switch (action) {
case REJECT:
key = FILTER_REJECT;
skip = true;
break;
case ACCEPT:
key = FILTER_ACCEPT;
break;
// should never come here
case MAX_FILTER_ACTIONS:
return true;
}

// update global counter for flows dropped by filter
increase_counter(key);
if (skip) {
return true;
}
} else {
// we have no matching rules so we update global counter for flows that are not matched by any rule
increase_counter(FILTER_NOMATCH);
// we have accept rule but no match so we can't let mismatched flows in the hashmap table or
// we have no match at all and the action is the default value MAX_FILTER_ACTIONS.
if (action == ACCEPT || action == MAX_FILTER_ACTIONS) {
return true;
} else {
// we have reject rule and no match so we can add the flows to the hashmap table.
}
}
}
return false;
}

static inline void core_fill_in_l2(struct sk_buff *skb, u16 *eth_protocol, u16 *family) {
struct ethhdr eth;

Expand Down
Loading