From: Eric Leblond Date: Sun, 9 Dec 2018 22:22:08 +0000 (+0100) Subject: util-ebpf: implement pinned maps loading X-Git-Tag: suricata-5.0.0-rc1~384 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1769d5f8fa219f137fdc4e8a064a4d2d08e75e8;p=thirdparty%2Fsuricata.git util-ebpf: implement pinned maps loading Load flow tables at start if asked to. --- diff --git a/doc/userguide/capture-hardware/ebpf-xdp.rst b/doc/userguide/capture-hardware/ebpf-xdp.rst index bab638929b..92fdb7e9c1 100644 --- a/doc/userguide/capture-hardware/ebpf-xdp.rst +++ b/doc/userguide/capture-hardware/ebpf-xdp.rst @@ -359,7 +359,7 @@ Confirm you have the XDP filter engaged in the output (example):: Pinned maps usage ----------------- -Pnned maps stay attached to the system if the creating process disappear and +Pinned maps stay attached to the system if the creating process disappear and they can also be accessed by external tools. In Suricata bypass case, this can be used to keep active bypassed flow tables so Suricata is not hit by previsouly bypassed flows when restarting. In the socket filter case, this can be used to maintain a map from tools outside diff --git a/src/runmode-af-packet.c b/src/runmode-af-packet.c index 64ac73b956..920fac8a33 100644 --- a/src/runmode-af-packet.c +++ b/src/runmode-af-packet.c @@ -457,6 +457,7 @@ static void *ParseAFPConfig(const char *iface) aconf->ebpf_t_config.mode = AFP_MODE_XDP_BYPASS; aconf->ebpf_t_config.flags |= EBPF_XDP_CODE; aconf->xdp_filter_file = ebpf_file; + /* TODO FIXME Do we really have a usage of setting XDP and not bypassing ? */ ConfGetChildValueBoolWithDefault(if_root, if_default, "bypass", &conf_val); if (conf_val) { #ifdef HAVE_PACKET_XDP diff --git a/src/util-ebpf.c b/src/util-ebpf.c index 2b8def0da5..0bb1b4ffac 100644 --- a/src/util-ebpf.c +++ b/src/util-ebpf.c @@ -153,9 +153,57 @@ int EBPFGetMapFDByName(const char *iface, const char *name) return bpf_maps->array[i].fd; } } + + /* Fallback by getting pinned maps ? */ + return -1; } +static int EBPFLoadPinnedMapsFile(LiveDevice *livedev, const char *file) +{ + char pinnedpath[1024]; + snprintf(pinnedpath, sizeof(pinnedpath), + "/sys/fs/bpf/suricata-%s-%s", + livedev->dev, + file); + + return bpf_obj_get(pinnedpath); +} + +static int EBPFLoadPinnedMaps(LiveDevice *livedev, uint8_t flags) +{ + int fd_v4 = -1, fd_v6 = -1; + + /* Get flow v4 table */ + fd_v4 = EBPFLoadPinnedMapsFile(livedev, "flow_table_v4"); + if (fd_v4 < 0) { + return fd_v4; + } + + /* Get flow v6 table */ + fd_v6 = EBPFLoadPinnedMapsFile(livedev, "flow_table_v6"); + if (fd_v6 < 0) { + SCLogWarning(SC_ERR_INVALID_ARGUMENT, + "Found a flow_table_v4 map but no flow_table_v6 map"); + return fd_v6; + } + + struct bpf_maps_info *bpf_map_data = SCCalloc(1, sizeof(*bpf_map_data)); + if (bpf_map_data == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate bpf map array"); + return -1; + } + SC_ATOMIC_INIT(bpf_map_data->ipv4_hash_count); + SC_ATOMIC_INIT(bpf_map_data->ipv6_hash_count); + bpf_map_data->array[0].fd = fd_v4; + bpf_map_data->array[0].name = SCStrdup("flow_table_v4"); + bpf_map_data->array[1].fd = fd_v6; + bpf_map_data->array[1].name = SCStrdup("flow_table_v6"); + bpf_map_data->last = 2; + + return 0; +} + /** * Load a section of an eBPF file * @@ -183,6 +231,13 @@ int EBPFLoadFile(const char *iface, const char *path, const char * section, if (livedev == NULL) return -1; + if (flags & EBPF_XDP_CODE) { + /* We try to get our flow table maps and if we have them we can simply return */ + if (EBPFLoadPinnedMaps(livedev, flags) == 0) { + return 0; + } + } + if (! path) { SCLogError(SC_ERR_INVALID_VALUE, "No file defined to load eBPF from"); return -1;