struct pair {
__u32 packets;
__u32 bytes;
- __u32 hash;
};
struct bpf_map_def SEC("maps") flow_table_v4 = {
return hash;
}
+/**
+ * Basic hashing function for FlowKey
+ *
+ * \note Function only used for bypass
+ *
+ * \note this is only used at start to create Flow from pinned maps
+ * so fairness is not an issue
+ */
+uint32_t FlowKeyGetHash(FlowKey *fk)
+{
+ return hashword((uint32_t *)fk, sizeof(*fk)/4, flow_config.hash_rand);
+}
+
/* Since two or more flows can have the same hash key, we need to compare
* the flow with the current flow key. */
#define CMP_FLOW(f1,f2) \
Flow *FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t hash);
Flow *FlowGetExistingFlowFromHash(FlowKey * key, uint32_t hash);
+uint32_t FlowKeyGetHash(FlowKey *flow_key);
void FlowDisableTcpReuseHandling(void);
* \param key data to use as key in the table
* \return 0 in case of error, 1 if success
*/
-static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
- unsigned int nr_cpus)
+static int AFPInsertHalfFlow(int mapd, void *key, unsigned int nr_cpus)
{
BPF_DECLARE_PERCPU(struct pair, value, nr_cpus);
unsigned int i;
for (i = 0; i < nr_cpus; i++) {
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) {
keys[0]->vlan_id[1] = p->vlan_id[1];
keys[0]->ip_proto = IPV4_GET_IPPROTO(p);
- if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
return 0;
keys[1]->vlan_id[1] = p->vlan_id[1];
keys[1]->ip_proto = IPV4_GET_IPPROTO(p);
- if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
SCFree(keys[1]);
keys[0]->vlan_id[0] = p->vlan_id[0];
keys[0]->vlan_id[1] = p->vlan_id[1];
keys[0]->ip_proto = IPV6_GET_NH(p);
- if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
return 0;
keys[1]->vlan_id[0] = p->vlan_id[0];
keys[1]->vlan_id[1] = p->vlan_id[1];
keys[1]->ip_proto = IPV6_GET_NH(p);
- if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
SCFree(keys[1]);
keys[0]->vlan_id[0] = p->vlan_id[0];
keys[0]->vlan_id[1] = p->vlan_id[1];
keys[0]->ip_proto = IPV4_GET_IPPROTO(p);
- if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
return 0;
keys[1]->vlan_id[0] = p->vlan_id[0];
keys[1]->vlan_id[1] = p->vlan_id[1];
keys[1]->ip_proto = IPV4_GET_IPPROTO(p);
- if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
SCFree(keys[1]);
keys[0]->vlan_id[0] = p->vlan_id[0];
keys[0]->vlan_id[1] = p->vlan_id[1];
keys[0]->ip_proto = IPV6_GET_NH(p);
- if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
return 0;
keys[1]->vlan_id[0] = p->vlan_id[0];
keys[1]->vlan_id[1] = p->vlan_id[1];
keys[1]->ip_proto = IPV6_GET_NH(p);
- if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->flow_hash,
+ if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {
SCFree(keys[0]);
SCFree(keys[1]);
*
* \return false (this create function never returns true)
*/
-static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, FlowKey *flow_key,
- uint32_t hash, struct timespec *ctime,
- uint64_t pkts_cnt, uint64_t bytes_cnt)
+static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, void *key,
+ FlowKey *flow_key, struct timespec *ctime,
+ uint64_t pkts_cnt, uint64_t bytes_cnt,
+ int mapfd, int cpus_count)
{
- Flow *f = FlowGetFromFlowKey(flow_key, ctime, hash);
+ Flow *f = NULL;
+ uint32_t hash = FlowKeyGetHash(flow_key);
+
+ f = FlowGetFromFlowKey(flow_key, ctime, hash);
if (f == NULL)
return false;
fc->BypassFree = EBPFBypassFree;
fc->todstpktcnt = pkts_cnt;
fc->todstbytecnt = bytes_cnt;
+ EBPFBypassData *eb = SCCalloc(1, sizeof(EBPFBypassData));
+ if (eb == NULL) {
+ SCFree(fc);
+ FLOWLOCK_UNLOCK(f);
+ return false;
+ }
+ eb->key[0] = key;
+ eb->mapfd = mapfd;
+ eb->cpus_count = cpus_count;
+ fc->bypass_data = eb;
} else {
FLOWLOCK_UNLOCK(f);
return false;
} else {
fc->tosrcpktcnt = pkts_cnt;
fc->tosrcbytecnt = bytes_cnt;
+ EBPFBypassData *eb = (EBPFBypassData *) fc->bypass_data;
+ if (eb) {
+ eb->key[1] = key;
+ }
}
FLOWLOCK_UNLOCK(f);
return false;
return false;
}
-typedef bool (*OpFlowForKey)(struct flows_stats *flowstats, FlowKey *flow_key,
- uint32_t hash, struct timespec *ctime,
- uint64_t pkts_cnt, uint64_t bytes_cnt);
+typedef bool (*OpFlowForKey)(struct flows_stats *flowstats, void *key,
+ FlowKey *flow_key, struct timespec *ctime,
+ uint64_t pkts_cnt, uint64_t bytes_cnt,
+ int mapfd, int cpus_count);
/**
* Bypassed flows cleaning for IPv4
flow_key.vlan_id[1] = next_key.vlan_id[1];
flow_key.proto = next_key.ip_proto;
flow_key.recursion_level = 0;
- dead_flow = EBPFOpFlowForKey(flowstats, &flow_key,
- BPF_PERCPU(values_array, 0).hash,
- ctime, pkts_cnt, bytes_cnt);
+ dead_flow = EBPFOpFlowForKey(flowstats, &next_key, &flow_key,
+ ctime, pkts_cnt, bytes_cnt,
+ mapfd, tcfg->cpus_count);
if (dead_flow) {
found = 1;
}
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, BPF_PERCPU(values_array, 0).hash,
- ctime, pkts_cnt, bytes_cnt);
+ pkts_cnt = EBPFOpFlowForKey(flowstats, &next_key, &flow_key,
+ ctime, pkts_cnt, bytes_cnt,
+ mapfd, tcfg->cpus_count);
if (pkts_cnt > 0) {
found = 1;
}
struct pair {
uint32_t packets;
uint32_t bytes;
- uint32_t hash;
};
typedef struct EBPFBypassData_ {