flow: store livedev by id

In prep for storing both directions for IPS.
This commit is contained in:
Victor Julien 2026-04-02 14:53:42 +02:00
parent 10367750f1
commit 293662fc2e
10 changed files with 34 additions and 26 deletions

View file

@ -409,6 +409,11 @@ static inline bool CmpLiveDevIds(const LiveDevice *livedev, const uint16_t id)
return (((devid ^ id) & g_livedev_mask) == 0);
}
static inline bool CmpLiveDevIds2(const uint16_t id1, const uint16_t id2)
{
return (((id1 ^ id2) & g_livedev_mask) == 0);
}
/* Since two or more flows can have the same hash key, we need to compare
* the flow with the current packet or flow key. */
static inline bool CmpFlowPacket(const Flow *f, const Packet *p)
@ -420,7 +425,7 @@ static inline bool CmpFlowPacket(const Flow *f, const Packet *p)
return CmpAddrsAndPorts(f_src, f_dst, f->sp, f->dp, p_src, p_dst, p->sp, p->dp) &&
f->proto == p->proto &&
(f->recursion_level == p->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, p->vlan_id) && (f->livedev == p->livedev || g_livedev_mask == 0);
CmpVlanIds(f->vlan_id, p->vlan_id) && CmpLiveDevIds(p->livedev, f->livedev_id);
}
static inline bool CmpFlowKey(const Flow *f, const FlowKey *k)
@ -432,7 +437,7 @@ static inline bool CmpFlowKey(const Flow *f, const FlowKey *k)
return CmpAddrsAndPorts(f_src, f_dst, f->sp, f->dp, k_src, k_dst, k->sp, k->dp) &&
f->proto == k->proto &&
(f->recursion_level == k->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, k->vlan_id) && CmpLiveDevIds(f->livedev, k->livedev_id);
CmpVlanIds(f->vlan_id, k->vlan_id) && CmpLiveDevIds2(f->livedev_id, k->livedev_id);
}
static inline bool CmpAddrsAndICMPTypes(const uint32_t src1[4],
@ -459,7 +464,7 @@ static inline bool CmpFlowICMPPacket(const Flow *f, const Packet *p)
p->icmp_s.type, p->icmp_d.type) &&
f->proto == p->proto &&
(f->recursion_level == p->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, p->vlan_id) && (f->livedev == p->livedev || g_livedev_mask == 0);
CmpVlanIds(f->vlan_id, p->vlan_id) && CmpLiveDevIds(p->livedev, f->livedev_id);
}
/**
@ -483,8 +488,7 @@ static inline int FlowCompareICMPv4(Flow *f, const Packet *p)
f->sp == p->l4.vars.icmpv4.emb_sport && f->dp == p->l4.vars.icmpv4.emb_dport &&
f->proto == ICMPV4_GET_EMB_PROTO(p) &&
(f->recursion_level == p->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, p->vlan_id) &&
(f->livedev == p->livedev || g_livedev_mask == 0)) {
CmpVlanIds(f->vlan_id, p->vlan_id) && CmpLiveDevIds(p->livedev, f->livedev_id)) {
return 1;
/* check the less likely case where the ICMP error was a response to
@ -494,8 +498,7 @@ static inline int FlowCompareICMPv4(Flow *f, const Packet *p)
f->dp == p->l4.vars.icmpv4.emb_sport && f->sp == p->l4.vars.icmpv4.emb_dport &&
f->proto == ICMPV4_GET_EMB_PROTO(p) &&
(f->recursion_level == p->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, p->vlan_id) &&
(f->livedev == p->livedev || g_livedev_mask == 0)) {
CmpVlanIds(f->vlan_id, p->vlan_id) && CmpLiveDevIds(p->livedev, f->livedev_id)) {
return 1;
}
@ -527,7 +530,7 @@ static inline int FlowCompareESP(Flow *f, const Packet *p)
return CmpAddrs(f_src, p_src) && CmpAddrs(f_dst, p_dst) && f->proto == p->proto &&
(f->recursion_level == p->recursion_level || g_recurlvl_mask == 0) &&
CmpVlanIds(f->vlan_id, p->vlan_id) && f->esp.spi == ESP_GET_SPI(PacketGetESP(p)) &&
(f->livedev == p->livedev || g_livedev_mask == 0);
CmpLiveDevIds(p->livedev, f->livedev_id);
}
void FlowSetupPacket(Packet *p)

View file

@ -240,6 +240,7 @@ static inline bool FlowBypassedTimeout(Flow *f, SCTime_t ts, FlowTimeoutCounters
FlowBypassInfo *fc = SCFlowGetStorageById(f, GetFlowBypassInfoID());
if (fc && fc->BypassUpdate) {
LiveDevice *dev = LiveDeviceGetById(f->livedev_id);
/* flow will be possibly updated */
uint64_t pkts_tosrc = fc->tosrcpktcnt;
uint64_t bytes_tosrc = fc->tosrcbytecnt;
@ -252,20 +253,19 @@ static inline bool FlowBypassedTimeout(Flow *f, SCTime_t ts, FlowTimeoutCounters
bytes_tosrc = fc->tosrcbytecnt - bytes_tosrc;
pkts_todst = fc->todstpktcnt - pkts_todst;
bytes_todst = fc->todstbytecnt - bytes_todst;
if (f->livedev) {
SC_ATOMIC_ADD(f->livedev->bypassed,
pkts_tosrc + pkts_todst);
if (dev) {
SC_ATOMIC_ADD(dev->bypassed, pkts_tosrc + pkts_todst);
}
counters->bypassed_pkts += pkts_tosrc + pkts_todst;
counters->bypassed_bytes += bytes_tosrc + bytes_todst;
return false;
}
SCLogDebug("No new packet, dead flow %" PRIu64 "", FlowGetId(f));
if (f->livedev) {
if (dev) {
if (FLOW_IS_IPV4(f)) {
LiveDevSubBypassStats(f->livedev, 1, AF_INET);
LiveDevSubBypassStats(dev, 1, AF_INET);
} else if (FLOW_IS_IPV6(f)) {
LiveDevSubBypassStats(f->livedev, 1, AF_INET6);
LiveDevSubBypassStats(dev, 1, AF_INET6);
}
}
counters->bypassed_count++;

View file

@ -54,6 +54,7 @@
#include "util-debug.h"
#include "util-privs.h"
#include "util-datalink.h"
#include "util-device.h"
#include "detect.h"
#include "detect-engine-state.h"
@ -92,7 +93,7 @@ static inline Packet *FlowPseudoPacketSetup(
p->flags |= PKT_PSEUDO_STREAM_END;
memcpy(&p->vlan_id[0], &f->vlan_id[0], sizeof(p->vlan_id));
p->vlan_idx = f->vlan_idx;
p->livedev = (struct LiveDevice_ *)f->livedev;
p->livedev = LiveDeviceGetById(f->livedev_id);
if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
DecodeSetNoPayloadInspectionFlag(p);

View file

@ -44,6 +44,7 @@
#include "decode-icmpv4.h"
#include "util-device-private.h"
#include "util-validate.h"
/** \brief allocate a flow
@ -156,7 +157,8 @@ void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
f->thread_id[0] = (FlowThreadId)tv->id;
f->livedev = p->livedev;
LiveDevice *packet_ld = p->livedev;
f->livedev_id = packet_ld ? packet_ld->id : 0;
if (PacketIsIPv4(p)) {
const IPV4Hdr *ip4h = PacketGetIPv4(p);

View file

@ -40,7 +40,7 @@
(f)->sp = 0; \
(f)->dp = 0; \
(f)->proto = 0; \
(f)->livedev = NULL; \
(f)->livedev_id = 0; \
(f)->timeout_policy = 0; \
(f)->vlan_idx = 0; \
(f)->next = NULL; \
@ -83,7 +83,7 @@
(f)->sp = 0; \
(f)->dp = 0; \
(f)->proto = 0; \
(f)->livedev = NULL; \
(f)->livedev_id = 0; \
(f)->vlan_idx = 0; \
(f)->ffr = 0; \
(f)->next = NULL; \

View file

@ -389,7 +389,7 @@ typedef struct Flow_
uint32_t flow_hash;
/** Incoming interface */
struct LiveDevice_ *livedev;
uint16_t livedev_id;
struct Flow_ *next; /* (hash) list next */

View file

@ -106,8 +106,9 @@ static SCJsonBuilder *CreateEveHeaderFromFlow(const Flow *f, OutputJsonCommonSet
#endif
/* input interface */
if (f->livedev) {
SCJbSetString(jb, "in_iface", f->livedev->dev);
LiveDevice *dev = LiveDeviceGetById(f->livedev_id);
if (dev) {
SCJbSetString(jb, "in_iface", dev->dev);
}
JB_SET_STRING(jb, "event_type", "flow");

View file

@ -110,8 +110,9 @@ static SCJsonBuilder *CreateEveHeaderFromNetFlow(
#endif
/* input interface */
if (f->livedev) {
SCJbSetString(js, "in_iface", f->livedev->dev);
LiveDevice *dev = LiveDeviceGetById(f->livedev_id);
if (dev) {
SCJbSetString(js, "in_iface", dev->dev);
}
JB_SET_STRING(js, "event_type", "netflow");

View file

@ -6935,7 +6935,7 @@ static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
memcpy(&np->vlan_id[0], &f->vlan_id[0], sizeof(np->vlan_id));
np->vlan_idx = f->vlan_idx;
np->livedev = (struct LiveDevice_ *)f->livedev;
np->livedev = LiveDeviceGetById(f->livedev_id);
if (parent->flags & PKT_NOPACKET_INSPECTION) {
DecodeSetNoPacketInspectionFlag(np);

View file

@ -537,7 +537,7 @@ static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, LiveDevice *dev,
fc->BypassFree = EBPFBypassFree;
fc->todstpktcnt = pkts_cnt;
fc->todstbytecnt = bytes_cnt;
f->livedev = dev;
f->livedev_id = dev->id;
EBPFBypassData *eb = SCCalloc(1, sizeof(EBPFBypassData));
if (eb == NULL) {
SCFree(fc);
@ -583,7 +583,7 @@ static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, LiveDevice *dev,
memcpy(mkey, key, skey);
eb->key[1] = mkey;
}
f->livedev = dev;
f->livedev_id = dev->id;
FLOWLOCK_UNLOCK(f);
return false;
}