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

Update loading and chaining of the ipfix flow exporter #67

Merged
merged 1 commit into from
Nov 2, 2023
Merged
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
70 changes: 28 additions & 42 deletions ipfix-flow-exporter/bpf_ipfix_egress_kern.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright Contributors to the L3AF Project.
// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)

#define KBUILD_MODNAME "foo"

#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
Expand All @@ -16,49 +18,9 @@
#include "bpf_ipfix_kern_common.h"

#define DEBUG 1

#define EGRESS 1

#define ICMP 1

#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})

#define PIN_GLOBAL_NS 2
#define PIN_OBJECT_NS 1


/* EGRESS MAP FOR FLOW RECORD INFO */
struct bpf_elf_map SEC("maps") egress_flow_record_info_map = {
.type = BPF_MAP_TYPE_HASH,
.size_key = sizeof(u32),
.size_value = sizeof(flow_record_t),
.pinning = PIN_GLOBAL_NS,
.max_elem = 30000,
};

/* EGRESS MAP FOR LAST RECORD PACKET INFO */
struct bpf_elf_map SEC("maps") last_egress_flow_record_info_map = {
.type = BPF_MAP_TYPE_HASH,
.size_key = sizeof(u32),
.size_value = sizeof(flow_record_t),
.pinning = PIN_GLOBAL_NS,
.max_elem = 30000,
};

/* EGRESS MAP FOR CHAINING */
struct bpf_elf_map SEC("maps") ipfix_egress_jmp_table = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.size_key = sizeof(u32),
.size_value = sizeof(u32),
.pinning = PIN_GLOBAL_NS,
.max_elem = 1
};

#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
Expand All @@ -79,12 +41,36 @@ struct bpf_elf_map SEC("maps") ipfix_egress_jmp_table = {

#define TCP_FLAGS (TCP_FIN|TCP_SYN|TCP_RST|TCP_ACK|TCP_URG|TCP_ECE|TCP_CWR)

/* EGRESS MAP FOR FLOW RECORD INFO */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, flow_record_t);
__uint(max_entries, MAX_RECORDS);
} egress_flow_record_info_map SEC(".maps");

/* EGRESS MAP FOR LAST RECORD PACKET INFO */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, flow_record_t);
__uint(max_entries, MAX_RECORDS);
} last_egress_flow_record_info_map SEC(".maps");

/* EGRESS MAP FOR CHAINING */
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__type(key, u32);
__type(value, u32);
__uint(max_entries, 1);
} ipfix_egress_jmp_table SEC(".maps");

static u32 flow_key_hash (const flow_key_t f) {
u32 hash_val = (((u32)f.sa * 0xef6e15aa)
^((u32)f.da * 0x65cd52a0)
^ ((u32)f.sp * 0x8216)
^ ((u32)f.dp * 0xdda37)
^ ((u32)f.prot * 0xbc06)) ;
^ ((u32)f.prot * 0xbc06));
return hash_val;
}

Expand Down Expand Up @@ -305,7 +291,7 @@ static __always_inline bool parse_egress_eth(struct ethhdr *eth, void *data_end,
return true;
}

sanfern marked this conversation as resolved.
Show resolved Hide resolved
SEC("egress_flow_monitoring")
SEC("tc_egress_flow_monitoring")
int _egress_flow_monitoring(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
Expand Down
88 changes: 22 additions & 66 deletions ipfix-flow-exporter/bpf_ipfix_egress_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,39 @@ static const char *__doc__=" BPF IPFIX : To get packet flow data by handling the
#define EXIT_OK 0
#define EXIT_FAIL 1

const char egress[] = "egress_flow_monitoring";

/* Ingress Specific variables */
bool attach_tc_egress_filter = false;
char if_name[IF_NAMESIZE];
char *egress_log_file_path = "/var/log/tb/l3af/egress_ipfix.log";
char *egress_log_file_path = "/var/log/l3af/egress_ipfix.log";

void sig_handler(int signo)
{
log_info("Received shutdown signal, cleaning up");
flow_record_poll(egress_fd, last_egress_fd, EGRESS);
if (attach_tc_egress_filter)
tc_cleanup(chain, if_name, EGRESS, egress_bpf_map, last_egress_bpf_map, bpf_map_file_path, ipfix_egress_jmp_table);
log_info("Cleaned up");
close_logfile();
exit(EXIT_SUCCESS);
}

int populate_egress_fds(void) {
egress_fd = bpf_obj_get(egress_bpf_map);
char map_file[MAP_PATH_SIZE];
if (get_bpf_map_file(if_name, egress_bpf_map, map_file) < 0) {
fprintf(stderr, "ERROR: map file path (%s) doesn't exists", map_file);
return EXIT_FAILURE;
}

egress_fd = bpf_obj_get(&map_file);
if (egress_fd < 0) {
fprintf(stderr, "ERROR: cannot open bpf_obj_get(%s)",
egress_bpf_map);
close_logfile();
return EXIT_FAILURE;
}

last_egress_fd = bpf_obj_get(last_egress_bpf_map);
if (get_bpf_map_file(if_name, last_egress_bpf_map, map_file) < 0) {
fprintf(stderr, "ERROR: map file path (%s) doesn't exists", map_file);
return EXIT_FAILURE;
}
last_egress_fd = bpf_obj_get(&map_file);
if (last_egress_fd < 0) {
fprintf(stderr, "ERROR: cannot open bpf_obj_get(%s)", last_egress_bpf_map);
close_logfile();
Expand All @@ -51,25 +56,14 @@ int populate_egress_fds(void) {

int main(int argc, char **argv)
{
char filename[256];
int opt = 0, long_index = 0, l = 0;
bool remove_egress_tc_filter = false;
verbosity = LOG_INFO;
long flow_timeout = 0;
char *eptr;
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hq",
long_options, &long_index)) != -1) {
switch (opt) {
case 'm':
if(optarg){
bpf_map_file_path = (char *) malloc(1 + strnlen(optarg, MAX_FILENAME_LENGTH));
cpy(optarg, bpf_map_file_path);
if(!validate_map_name(bpf_map_file_path))
return EXIT_FAILURE;
chain = true;
}
break;
case 'q':
if(optarg)
verbosity = (int)(strtol(optarg, &eptr, 10));
Expand All @@ -85,31 +79,15 @@ int main(int argc, char **argv)
if_name);
return EXIT_FAILURE;
}
attach_tc_egress_filter = true;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
l = get_length(filename);
filename[l] = '\0';
break;
case 'c':
if(optarg)
remote_ip = optarg;
break;
case 'r':
if (optarg &&
(!validate_ifname(optarg, (char *)&if_name))) {
log_err("ERR: input --remove=ifname invalid");
return EXIT_FAILURE;
}
if (get_length(if_name) == 0) {
log_err("ERR: need input --list=ifname");
return EXIT_FAILURE;
}
remove_egress_tc_filter = true;
break;
case 't':
if(optarg) {
flow_timeout = strtol(optarg, &eptr, 10);
flow_timeout_counter = flow_timeout / 10;
flow_timeout_counter = flow_timeout / 10;
}
break;
case 'p':
Expand All @@ -132,37 +110,15 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}

if(attach_tc_egress_filter) {
if(chain == true){
if (tc_chain_bpf(bpf_map_file_path, filename, egress) != 1) {
fprintf(stderr, "ERR: tc chain egress failed \n");
close_logfile();
return EXIT_FAILURE;
}
}
else {
if (tc_attach_filter(if_name, filename, EGRESS, egress) != 1) {
fprintf(stderr, "ERR: TC EGRESS filter attach failed\n");
close_logfile();
return EXIT_FAILURE;
}
}
if (populate_egress_fds() == EXIT_FAILURE) {
fprintf(stderr, "ERR: Fetching TC EGRESS maps failed\n");
close_logfile();
return EXIT_FAILURE;
}
if (remote_ip == NULL) {
log_info("Remote IP is not configured by user, so configuring localhost as remote_ip");
remote_ip = "127.0.0.1" ;
}
if (populate_egress_fds() == EXIT_FAILURE) {
fprintf(stderr, "ERR: Fetching TC EGRESS maps failed\n");
close_logfile();
return EXIT_FAILURE;
}

if (remove_egress_tc_filter) {
log_debug("TC remove egress filters on device %s",
if_name);
tc_remove_filter(if_name, EGRESS);
return EXIT_SUCCESS;
if (remote_ip == NULL) {
log_err("Remote IP is not configured by user, Please provide the remote ip");
close_logfile();
return EXIT_FAILURE;
}

if (signal(SIGINT, sig_handler) ||
Expand Down
69 changes: 29 additions & 40 deletions ipfix-flow-exporter/bpf_ipfix_ingress_kern.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright Contributors to the L3AF Project.
// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)

#define KBUILD_MODNAME "foo"

#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
Expand All @@ -19,44 +21,6 @@
#define INGRESS 0
#define ICMP 1

#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})

#define PIN_GLOBAL_NS 2
#define PIN_OBJECT_NS 1


/* INGRESS MAP FOR FLOW RECORD INFO */
struct bpf_elf_map SEC("maps") ingress_flow_record_info_map = {
.type = BPF_MAP_TYPE_HASH,
.size_key = sizeof(u32),
.size_value = sizeof(flow_record_t),
.pinning = PIN_GLOBAL_NS,
.max_elem = 30000,
};

/* INGRESS MAP FOR LAST RECORD PACKET INFO */
struct bpf_elf_map SEC("maps") last_ingress_flow_record_info_map = {
.type = BPF_MAP_TYPE_HASH,
.size_key = sizeof(u32),
.size_value = sizeof(flow_record_t),
.pinning = PIN_GLOBAL_NS,
.max_elem = 30000,
};

/* INGRESS MAP FOR CHAINING */
struct bpf_elf_map SEC("maps") ipfix_ingress_jmp_table = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.size_key = sizeof(u32),
.size_value = sizeof(u32),
.pinning = PIN_GLOBAL_NS,
.max_elem = 1
};

#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
Expand All @@ -77,12 +41,37 @@ struct bpf_elf_map SEC("maps") ipfix_ingress_jmp_table = {

#define TCP_FLAGS (TCP_FIN|TCP_SYN|TCP_RST|TCP_ACK|TCP_URG|TCP_ECE|TCP_CWR)

/* INGRESS MAP FOR FLOW RECORD INFO */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, flow_record_t);
__uint(max_entries, MAX_RECORDS);
} ingress_flow_record_info_map SEC(".maps");


/* INGRESS MAP FOR LAST RECORD PACKET INFO */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, flow_record_t);
__uint(max_entries, MAX_RECORDS);
} last_ingress_flow_record_info_map SEC(".maps");

/* INGRESS MAP FOR CHAINING */
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__type(key, u32);
__type(value, u32);
__uint(max_entries, 1);
} ipfix_ingress_jmp_table SEC(".maps");

static u32 flow_key_hash (const flow_key_t f) {
u32 hash_val = (((u32)f.sa * 0xef6e15aa)
^((u32)f.da * 0x65cd52a0)
^ ((u32)f.sp * 0x8216)
^ ((u32)f.dp * 0xdda37)
^ ((u32)f.prot * 0xbc06)) ;
^ ((u32)f.prot * 0xbc06));
return hash_val;
}

Expand Down Expand Up @@ -303,7 +292,7 @@ static __always_inline bool parse_ingress_eth(struct ethhdr *eth, void *data_end
return true;
}

SEC("ingress_flow_monitoring")
SEC("tc_ingress_flow_monitoring")
int _ingress_flow_monitoring(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
Expand Down
Loading