ebpf: fix percpu hash handling

An alignement issue was preventing the code to work properly.
We introduce macros taken from Linux source code sample to get
something that should work on the long term.
pull/3952/head
Eric Leblond 6 years ago committed by Victor Julien
parent 142c69e1ef
commit 651a27e4fb

@ -2299,7 +2299,7 @@ static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
uint64_t pkts_cnt, uint64_t bytes_cnt,
unsigned int nr_cpus)
{
struct pair value[nr_cpus];
BPF_DECLARE_PERCPU(struct pair, value, nr_cpus);
unsigned int i;
if (mapd == -1) {
@ -2310,12 +2310,13 @@ static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
* is not duplicating the data on each CPU by itself. We set the first entry to
* the actual flow pkts and bytes count as we need to continue from actual point
* to detect an absence of packets in the future. */
value[0].packets = pkts_cnt;
value[0].bytes = bytes_cnt;
value[0].hash = hash;
BPF_PERCPU(value,0).packets = pkts_cnt;
BPF_PERCPU(value,0).bytes = bytes_cnt;
BPF_PERCPU(value,0).hash = hash;
for (i = 1; i < nr_cpus; i++) {
value[i].packets = 0;
value[i].bytes = 0;
BPF_PERCPU(value, i).packets = 0;
BPF_PERCPU(value, i).bytes = 0;
BPF_PERCPU(value, i).hash = hash;
}
if (bpf_map_update_elem(mapd, key, value, BPF_NOEXIST) != 0) {
switch (errno) {

@ -560,7 +560,7 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
pkts_cnt = 0;
/* We use a per CPU structure so we will get a array of values. But if nr_cpus
* is 1 then we have a global hash. */
struct pair values_array[tcfg->cpus_count];
BPF_DECLARE_PERCPU(struct pair, values_array, tcfg->cpus_count);
memset(values_array, 0, sizeof(values_array));
int res = bpf_map_lookup_elem(mapfd, &next_key, values_array);
if (res < 0) {
@ -572,9 +572,10 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
for (i = 0; i < tcfg->cpus_count; i++) {
/* let's start accumulating value so we can compute the counters */
SCLogDebug("%d: Adding pkts %lu bytes %lu", i,
values_array[i].packets, values_array[i].bytes);
pkts_cnt += values_array[i].packets;
bytes_cnt += values_array[i].bytes;
BPF_PERCPU(values_array, i).packets,
BPF_PERCPU(values_array, i).bytes);
pkts_cnt += BPF_PERCPU(values_array, i).packets;
bytes_cnt += BPF_PERCPU(values_array, i).bytes;
}
/* Get the corresponding Flow in the Flow table to compare and update
* its counters and lastseen if needed */
@ -600,7 +601,8 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
flow_key.vlan_id[1] = next_key.vlan_id[1];
flow_key.proto = next_key.ip_proto;
flow_key.recursion_level = 0;
pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, values_array[0].hash,
pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key,
BPF_PERCPU(values_array, 0).hash,
ctime, pkts_cnt, bytes_cnt);
if (pkts_cnt > 0) {
found = 1;
@ -656,7 +658,7 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
pkts_cnt = 0;
/* We use a per CPU structure so we will get a array of values. But if nr_cpus
* is 1 then we have a global hash. */
struct pair values_array[tcfg->cpus_count];
BPF_DECLARE_PERCPU(struct pair, values_array, tcfg->cpus_count);
memset(values_array, 0, sizeof(values_array));
int res = bpf_map_lookup_elem(mapfd, &next_key, values_array);
if (res < 0) {
@ -667,9 +669,10 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
for (i = 0; i < tcfg->cpus_count; i++) {
/* let's start accumulating value so we can compute the counters */
SCLogDebug("%d: Adding pkts %lu bytes %lu", i,
values_array[i].packets, values_array[i].bytes);
pkts_cnt += values_array[i].packets;
bytes_cnt += values_array[i].bytes;
BPF_PERCPU(values_array, i).packets,
BPF_PERCPU(values_array, i).bytes);
pkts_cnt += BPF_PERCPU(values_array, i).packets;
bytes_cnt += BPF_PERCPU(values_array, i).bytes;
}
/* Get the corresponding Flow in the Flow table to compare and update
* its counters and lastseen if needed */
@ -695,7 +698,7 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
flow_key.vlan_id[1] = next_key.vlan_id[1];
flow_key.proto = next_key.ip_proto;
flow_key.recursion_level = 0;
pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, values_array[0].hash,
pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, BPF_PERCPU(values_array, 0).hash,
ctime, pkts_cnt, bytes_cnt);
if (pkts_cnt > 0) {
found = 1;

@ -88,6 +88,14 @@ int EBPFUpdateFlow(Flow *f, Packet *p, void *data);
TmEcode EBPFGetBypassedStats(json_t *cmd, json_t *answer, void *data);
#endif
#define __bpf_percpu_val_align __attribute__((__aligned__(8)))
#define BPF_DECLARE_PERCPU(type, name, nr_cpus) \
struct { type v; /* padding */ } __bpf_percpu_val_align \
name[nr_cpus]
#define BPF_PERCPU(name, cpu) name[(cpu)].v
#endif
#endif

Loading…
Cancel
Save