Skip to content

Commit

Permalink
Merge pull request #13 from gospo/master
Browse files Browse the repository at this point in the history
samples/bpf: cleanup JSON output and count TCP and UDP drops separately
  • Loading branch information
netoptimizer committed Mar 30, 2017
2 parents 329aaaa + 54c4717 commit d09e43e
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 47 deletions.
81 changes: 51 additions & 30 deletions kernel/samples/bpf/xdp_ddos01_blacklist_cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,9 @@ static const char *xdp_action_names[XDP_ACTION_MAX] = {
[XDP_TX] = "XDP_TX",
};

#define FILTER_TCP 0
#define FILTER_UDP 1
#define XDP_PROTO_FILTER_MAX 2
static const char *xdp_proto_filter_names[XDP_PROTO_FILTER_MAX] = {
[FILTER_TCP] = "TCP",
[FILTER_UDP] = "UDP",
static const char *xdp_proto_filter_names[DDOS_FILTER_MAX] = {
[DDOS_FILTER_TCP] = "TCP",
[DDOS_FILTER_UDP] = "UDP",
};

static const char *action2str(int action)
Expand Down Expand Up @@ -197,7 +194,7 @@ static void stats_poll(int interval)
close(fd);
}

static void blacklist_print_ip(__u32 ip, __u64 count)
static void blacklist_print_ipv4(__u32 ip, __u64 count)
{
char ip_txt[INET_ADDRSTRLEN] = {0};

Expand All @@ -207,52 +204,67 @@ static void blacklist_print_ip(__u32 ip, __u64 count)
"ERR: Cannot convert u32 IP:0x%X to IP-txt\n", ip);
exit(EXIT_FAIL_IP);
}
printf("\"%s\" : %llu\n", ip_txt, count);
printf("\n \"%s\" : %llu", ip_txt, count);
}

static void blacklist_print_port(int key, u32 val, __u64 count)
static void blacklist_print_proto(int key, __u64 count)
{
printf("\n\t\"%s\" : %llu", xdp_proto_filter_names[key], count);
}

static void blacklist_print_port(int key, u32 val, int countfds[])
{
int i;
printf(" %d: ", key);
for (i = 0; i < XDP_PROTO_FILTER_MAX; i++)
if (val & (1 << i))
printf("%s ",xdp_proto_filter_names[i]);
printf(": %llu\n", count);
__u64 count;
bool started = false;

printf("\n \"%d\" : ", key);
for (i = 0; i < DDOS_FILTER_MAX; i++) {
if (val & (1 << i)) {
printf("%s", started ? "," : "{");
started = true;
count = get_key32_value64_percpu(countfds[i], key);
blacklist_print_proto(i, count);
}
}
if (started)
printf("\n }");
}

static void blacklist_list_all(int fd)
static void blacklist_list_all_ipv4(int fd)
{
__u32 key = 0, next_key;
__u64 value;

printf("{\n");
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
printf("%s", key ? "," : "" );
key = next_key;
value = get_key32_value64_percpu(fd, key);
blacklist_print_ip(key, value);
blacklist_print_ipv4(key, value);
}
printf("}\n");
printf("%s", key ? "," : "");
}

static void blacklist_list_all_ports(int portfd, int countfd)
static void blacklist_list_all_ports(int portfd, int countfds[])
{
__u32 key = 0, next_key;
__u64 value;
__u64 count;
bool started = false;

printf("{\n");
/* printf("{\n"); */
while (bpf_map_get_next_key(portfd, &key, &next_key) == 0) {
if ((bpf_map_lookup_elem(portfd, &key, &value)) != 0) {
fprintf(stderr,
"ERR: bpf_map_lookup_elem(%d) failed key:0x%X\n", portfd, key);
}
count = get_key32_value64_percpu(countfd, key);
if (value)
blacklist_print_port(key, value, count);

if (value) {
printf("%s", started ? "," : "");
started = true;
blacklist_print_port(key, value, countfds);
}
key = next_key;
}
printf("}\n");
}

int main(int argc, char **argv)
Expand All @@ -273,6 +285,7 @@ int main(int argc, char **argv)
int opt;
int dport = 0;
int proto = IPPROTO_TCP;
int filter = DDOS_FILTER_TCP;

fd_verdict = open_bpf_map(file_verdict);

Expand All @@ -295,6 +308,7 @@ int main(int argc, char **argv)
break;
case 'u':
proto = IPPROTO_UDP;
filter = DDOS_FILTER_UDP;
case 't':
if (optarg)
dport = atoi(optarg);
Expand Down Expand Up @@ -333,7 +347,7 @@ int main(int argc, char **argv)

if (dport) {
fd_port_blacklist = open_bpf_map(file_port_blacklist);
fd_port_blacklist_count = open_bpf_map(file_port_blacklist_count);
fd_port_blacklist_count = open_bpf_map(file_port_blacklist_count[filter]);
res = blacklist_port_modify(fd_port_blacklist, fd_port_blacklist_count, dport, action, proto);
close(fd_port_blacklist);
close(fd_port_blacklist_count);
Expand All @@ -349,15 +363,22 @@ int main(int argc, char **argv)
}

if (do_list) {
printf("{");
int fd_port_blacklist_count_array[DDOS_FILTER_MAX];
int i;

fd_blacklist = open_bpf_map(file_blacklist);
blacklist_list_all(fd_blacklist);
blacklist_list_all_ipv4(fd_blacklist);
close(fd_blacklist);

fd_port_blacklist = open_bpf_map(file_port_blacklist);
fd_port_blacklist_count = open_bpf_map(file_port_blacklist_count);
blacklist_list_all_ports(fd_port_blacklist, fd_port_blacklist_count);
for (i = 0; i < DDOS_FILTER_MAX; i++)
fd_port_blacklist_count_array[i] = open_bpf_map(file_port_blacklist_count[i]);
blacklist_list_all_ports(fd_port_blacklist, fd_port_blacklist_count_array);
close(fd_port_blacklist);
close(fd_port_blacklist_count);
printf("\n}\n");
for (i = 0; i < DDOS_FILTER_MAX; i++)
close(fd_port_blacklist_count_array[i]);
}

/* Show statistics by polling */
Expand Down
10 changes: 7 additions & 3 deletions kernel/samples/bpf/xdp_ddos01_blacklist_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ static const char *file_blacklist = "/sys/fs/bpf/ddos_blacklist";
static const char *file_verdict = "/sys/fs/bpf/ddos_blacklist_stat_verdict";

static const char *file_port_blacklist = "/sys/fs/bpf/ddos_port_blacklist";
static const char *file_port_blacklist_count = "/sys/fs/bpf/ddos_port_blacklist_count";
static const char *file_port_blacklist_count[] = {
"/sys/fs/bpf/ddos_port_blacklist_count_tcp",
"/sys/fs/bpf/ddos_port_blacklist_count_udp"
};


// TODO: create subdir per ifname, to allow more XDP progs
Expand Down Expand Up @@ -56,8 +59,9 @@ uint64_t gettime(void)
#define ACTION_DEL (1 << 1)

enum {
DDOS_FILTER_TCP = 0,
DDOS_FILTER_UDP,
DDOS_FILTER_TCP = 0,
DDOS_FILTER_UDP,
DDOS_FILTER_MAX
};

static int blacklist_modify(int fd, char *ip_string, unsigned int action)
Expand Down
34 changes: 30 additions & 4 deletions kernel/samples/bpf/xdp_ddos01_blacklist_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,36 @@ struct bpf_map_def SEC("maps") port_blacklist = {
};

/* Counter per XDP "action" verdict */
struct bpf_map_def SEC("maps") port_blacklist_drop_count = {

/* TCP Drop counter */
struct bpf_map_def SEC("maps") port_blacklist_drop_count_tcp = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u64),
.max_entries = 65536,
};

/* UDP Drop counter */
struct bpf_map_def SEC("maps") port_blacklist_drop_count_udp = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u64),
.max_entries = 65536,
};

static inline struct bpf_map_def *drop_count_by_fproto(int fproto) {

switch (fproto) {
case DDOS_FILTER_UDP:
return &port_blacklist_drop_count_udp;
break;
case DDOS_FILTER_TCP:
return &port_blacklist_drop_count_tcp;
break;
}
return NULL;
}

// TODO: Add map for controlling behavior

//#define DEBUG 1
Expand Down Expand Up @@ -168,9 +191,12 @@ u32 parse_port(struct xdp_md *ctx, u8 proto, void *hdr)

if (value) {
if (*value & fproto) {
drops = bpf_map_lookup_elem(&port_blacklist_drop_count, &dport_idx);
if (drops)
*drops += 1; /* Keep a counter for drop matches */
struct bpf_map_def *drop_counter = drop_count_by_fproto(fproto);
if (drop_counter) {
drops = bpf_map_lookup_elem(drop_counter , &dport_idx);
if (drops)
*drops += 1; /* Keep a counter for drop matches */
}
return XDP_DROP;
}
}
Expand Down
31 changes: 21 additions & 10 deletions kernel/samples/bpf/xdp_ddos01_blacklist_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static int ifindex = -1;

static void remove_xdp_program(int ifindex, const char *ifname)
{
int i;
fprintf(stderr, "Removing XDP program on ifindex:%d device:%s\n",
ifindex, ifname);
if (ifindex > -1)
Expand All @@ -62,9 +63,11 @@ static void remove_xdp_program(int ifindex, const char *ifname)
printf("WARN: cannot remove map file:%s err(%d):%s\n",
file_port_blacklist, errno, strerror(errno));
}
if (unlink(file_port_blacklist_count) < 0) {
printf("WARN: cannot remove map file:%s err(%d):%s\n",
file_port_blacklist_count, errno, strerror(errno));
for (i = 0; i < DDOS_FILTER_MAX; i++) {
if (unlink(file_port_blacklist_count[i]) < 0) {
printf("WARN: cannot remove map file:%s err(%d):%s\n",
file_port_blacklist_count[i], errno, strerror(errno));
}
}
}

Expand Down Expand Up @@ -144,10 +147,14 @@ int export_map_fd(int map_idx, const char *file, uid_t owner, gid_t group)
int fd_existing;

/* Verify input map_fd[map_idx] */
if (map_idx>= MAX_MAPS)
if (map_idx>= MAX_MAPS) {
printf("%s +%d\n",__FILE__,__LINE__);
return EXIT_FAIL_MAP;
if (map_fd[map_idx] <= 0)
}
if (map_fd[map_idx] <= 0) {
printf("%s +%d\n",__FILE__,__LINE__);
return EXIT_FAIL_MAP;
}

if (bpf_fs_check_path(file) < 0) {
exit(EXIT_FAIL_MAP_FS);
Expand Down Expand Up @@ -193,6 +200,7 @@ int main(int argc, char **argv)
struct passwd *pwd = NULL;
int res;
int opt;
int i;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

Expand Down Expand Up @@ -291,11 +299,14 @@ int main(int argc, char **argv)
if (verbose)
printf(" - Blacklist Port map file: %s\n", file_port_blacklist);

if ((res = export_map_fd(3, file_port_blacklist_count, owner, group)))
return res;
for (i = 0; i < DDOS_FILTER_MAX; i++) {

if (verbose)
printf(" - Verdict port stats map file: %s\n", file_port_blacklist_count);
if ((res = export_map_fd(3 + i, file_port_blacklist_count[i], owner, group)))
return res;

if (verbose)
printf(" - Verdict port stats map file: %s\n", file_port_blacklist_count[i]);
}

/* Notice: updated map_fd[i] takes effect now */
if (load_bpf_relocate_maps_and_attach(fd_bpf_prog)) {
Expand All @@ -316,7 +327,7 @@ int main(int argc, char **argv)

/* Add something to the map as a test */
blacklist_modify(map_fd[0], "198.18.50.3", ACTION_ADD);
blacklist_port_modify(map_fd[2], map_fd[3], 80, ACTION_ADD, IPPROTO_UDP);
blacklist_port_modify(map_fd[2], map_fd[4], 80, ACTION_ADD, IPPROTO_UDP);

return EXIT_OK;
}

0 comments on commit d09e43e

Please sign in to comment.