bypass: generalize iface bypass stats

Introduce functions in util-device.c to be able to manage the
flow bypassed count stats.
pull/3952/head
Eric Leblond 6 years ago committed by Victor Julien
parent 7e8f4b70f0
commit 4e6add7faa

@ -2703,6 +2703,7 @@ static int PostConfLoadedSetup(SCInstance *suri)
StorageInit();
#ifdef HAVE_PACKET_EBPF
EBPFRegisterExtension();
LiveDevRegisterExtension();
#endif
AppLayerSetup();

@ -1190,10 +1190,12 @@ void UnixManagerThreadSpawnNonRunmode(void)
UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
UnixManagerRegisterCommand("iface-bypassed-stat",
LiveDeviceGetBypassedStats, NULL, 0);
/* For backward compatibility */
UnixManagerRegisterCommand("ebpf-bypassed-stat",
LiveDeviceGetBypassedStats, NULL, 0);
UnixManagerThreadSpawn(0);
#ifdef HAVE_PACKET_EBPF
UnixManagerRegisterCommand("ebpf-bypassed-stats", EBPFGetBypassedStats, NULL, 0);
#endif
}
}
}

@ -24,6 +24,8 @@
#define MAX_DEVNAME 10
static int g_bypass_storage_id = -1;
/**
* \file
*
@ -45,9 +47,15 @@ static TAILQ_HEAD(, LiveDevice_) live_devices =
static TAILQ_HEAD(, LiveDeviceName_) pre_live_devices =
TAILQ_HEAD_INITIALIZER(pre_live_devices);
typedef struct BypassInfo_ {
SC_ATOMIC_DECLARE(uint64_t, ipv4_hash_count);
SC_ATOMIC_DECLARE(uint64_t, ipv6_hash_count);
} BypassInfo;
/** if set to 0 when we don't have real devices */
static int live_devices_stats = 1;
static int LiveSafeDeviceName(const char *devname,
char *newdevname, size_t destlen);
@ -452,3 +460,91 @@ void LiveDeviceFinalize(void)
SCFree(ld);
}
}
static void LiveDevExtensionFree(void *x)
{
if (x)
SCFree(x);
}
/**
* Register bypass stats storage
*/
void LiveDevRegisterExtension(void)
{
g_bypass_storage_id = LiveDevStorageRegister("bypass_stats", sizeof(void *),
NULL, LiveDevExtensionFree);
}
/**
* Prepare a LiveDevice so we can set bypass stats
*/
int LiveDevUseBypass(LiveDevice *dev)
{
BypassInfo *bpinfo = SCCalloc(1, sizeof(*bpinfo));
if (bpinfo == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate bypass info structure");
return -1;
}
SC_ATOMIC_INIT(bpinfo->ipv4_hash_count);
SC_ATOMIC_INIT(bpinfo->ipv4_hash_count);
LiveDevSetStorageById(dev, g_bypass_storage_id, bpinfo);
return 0;
}
/**
* Set number of currently bypassed flows for a protocol family
*
* \param dev pointer to LiveDevice to set stats for
* \param cnt number of currently bypassed flows
* \param family AF_INET to set IPv4 count or AF_INET6 to set IPv6 count
*/
void LiveDevSetBypassStats(LiveDevice *dev, uint64_t cnt, int family)
{
BypassInfo *bpfdata = LiveDevGetStorageById(dev, g_bypass_storage_id);
if (bpfdata) {
if (family == AF_INET) {
SC_ATOMIC_SET(bpfdata->ipv4_hash_count, cnt);
} else if (family == AF_INET6) {
SC_ATOMIC_SET(bpfdata->ipv6_hash_count, cnt);
}
}
}
#ifdef BUILD_UNIX_SOCKET
TmEcode LiveDeviceGetBypassedStats(json_t *cmd, json_t *answer, void *data)
{
LiveDevice *ldev = NULL, *ndev;
json_t *ifaces = NULL;
while(LiveDeviceForEach(&ldev, &ndev)) {
BypassInfo *bpinfo = LiveDevGetStorageById(ldev, g_bypass_storage_id);
if (bpinfo) {
uint64_t ipv4_hash_count = SC_ATOMIC_GET(bpinfo->ipv4_hash_count);
uint64_t ipv6_hash_count = SC_ATOMIC_GET(bpinfo->ipv6_hash_count);
json_t *iface = json_object();
if (ifaces == NULL) {
ifaces = json_object();
if (ifaces == NULL) {
json_object_set_new(answer, "message",
json_string("internal error at json object creation"));
return TM_ECODE_FAILED;
}
}
json_object_set_new(iface, "ipv4_count", json_integer(ipv4_hash_count));
json_object_set_new(iface, "ipv6_count", json_integer(ipv6_hash_count));
json_object_set_new(ifaces, ldev->dev, iface);
}
}
if (ifaces) {
json_object_set_new(answer, "message", ifaces);
SCReturnInt(TM_ECODE_OK);
}
json_object_set_new(answer, "message",
json_string("No interface using bypass"));
SCReturnInt(TM_ECODE_FAILED);
}
#endif

@ -60,8 +60,12 @@ typedef struct LiveDeviceName_ {
TAILQ_ENTRY(LiveDeviceName_) next;
} LiveDeviceName;
void LiveDevRegisterExtension(void);
int LiveRegisterDeviceName(const char *dev);
int LiveRegisterDevice(const char *dev);
int LiveDevUseBypass(LiveDevice *dev);
void LiveDevSetBypassStats(LiveDevice *dev, uint64_t cnt, int family);
int LiveGetDeviceCount(void);
const char *LiveGetDeviceName(int number);
LiveDevice *LiveGetDevice(const char *dev);
@ -78,6 +82,7 @@ void LiveDeviceFinalize(void);
#ifdef BUILD_UNIX_SOCKET
TmEcode LiveDeviceIfaceStat(json_t *cmd, json_t *server_msg, void *data);
TmEcode LiveDeviceIfaceList(json_t *cmd, json_t *server_msg, void *data);
TmEcode LiveDeviceGetBypassedStats(json_t *cmd, json_t *answer, void *data);
#endif
#endif /* __UTIL_DEVICE_H__ */

@ -71,8 +71,6 @@ struct bpf_map_item {
struct bpf_maps_info {
struct bpf_map_item array[BPF_MAP_MAX_COUNT];
SC_ATOMIC_DECLARE(uint64_t, ipv4_hash_count);
SC_ATOMIC_DECLARE(uint64_t, ipv6_hash_count);
int last;
};
@ -221,8 +219,7 @@ static int EBPFLoadPinnedMaps(LiveDevice *livedev, struct ebpf_timeout_config *c
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);
if (config->mode == AFP_MODE_XDP_BYPASS) {
bpf_map_data->array[0].fd = fd_v4;
bpf_map_data->array[0].name = SCStrdup("flow_table_v4");
@ -279,6 +276,8 @@ static int EBPFLoadPinnedMaps(LiveDevice *livedev, struct ebpf_timeout_config *c
/* Attach the bpf_maps_info to the LiveDevice via the device storage */
LiveDevSetStorageById(livedev, g_livedev_storage_id, bpf_map_data);
/* Declare that device will use bypass stats */
LiveDevUseBypass(livedev);
return 0;
@ -411,8 +410,6 @@ int EBPFLoadFile(const char *iface, const char *path, const char * section,
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);
/* Store the maps in bpf_maps_info:: */
bpf_map__for_each(map, bpfobj) {
@ -453,6 +450,7 @@ int EBPFLoadFile(const char *iface, const char *path, const char * section,
/* Attach the bpf_maps_info to the LiveDevice via the device storage */
LiveDevSetStorageById(livedev, g_livedev_storage_id, bpf_map_data);
LiveDevUseBypass(livedev);
/* Finally we get the file descriptor for our eBPF program. We will use
* the fd to attach the program to the socket (eBPF case) or to the device
@ -655,10 +653,7 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
}
SC_ATOMIC_ADD(dev->bypassed, flowstats->packets);
struct bpf_maps_info *bpfdata = LiveDevGetStorageById(dev, g_livedev_storage_id);
if (bpfdata) {
SC_ATOMIC_SET(bpfdata->ipv4_hash_count, hash_cnt);
}
LiveDevSetBypassStats(dev, hash_cnt, AF_INET);
return found;
}
@ -750,10 +745,7 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
}
SC_ATOMIC_ADD(dev->bypassed, flowstats->packets);
struct bpf_maps_info *bpfdata = LiveDevGetStorageById(dev, g_livedev_storage_id);
if (bpfdata) {
SC_ATOMIC_SET(bpfdata->ipv6_hash_count, hash_cnt);
}
LiveDevSetBypassStats(dev, hash_cnt, AF_INET6);
return found;
}
@ -819,42 +811,6 @@ int EBPFCheckBypassedFlowTimeout(struct flows_stats *bypassstats,
return ret;
}
#ifdef BUILD_UNIX_SOCKET
TmEcode EBPFGetBypassedStats(json_t *cmd, json_t *answer, void *data)
{
LiveDevice *ldev = NULL, *ndev;
json_t *ifaces = NULL;
while(LiveDeviceForEach(&ldev, &ndev)) {
struct bpf_maps_info *bpfdata = LiveDevGetStorageById(ldev, g_livedev_storage_id);
if (bpfdata) {
uint64_t ipv4_hash_count = SC_ATOMIC_GET(bpfdata->ipv4_hash_count);
uint64_t ipv6_hash_count = SC_ATOMIC_GET(bpfdata->ipv6_hash_count);
json_t *iface = json_object();
if (ifaces == NULL) {
ifaces = json_object();
if (ifaces == NULL) {
json_object_set_new(answer, "message",
json_string("internal error at json object creation"));
return TM_ECODE_FAILED;
}
}
json_object_set_new(iface, "ipv4_count", json_integer(ipv4_hash_count));
json_object_set_new(iface, "ipv6_count", json_integer(ipv6_hash_count));
json_object_set_new(ifaces, ldev->dev, iface);
}
}
if (ifaces) {
json_object_set_new(answer, "message", ifaces);
SCReturnInt(TM_ECODE_OK);
}
json_object_set_new(answer, "message",
json_string("No interface using eBPF bypass"));
SCReturnInt(TM_ECODE_FAILED);
}
#endif
void EBPFRegisterExtension(void)
{
g_livedev_storage_id = LiveDevStorageRegister("bpfmap", sizeof(void *), NULL, BpfMapsInfoFree);

Loading…
Cancel
Save