From 293662fc2e77aa02af0ba51b4ef7347f4fa77f30 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 2 Apr 2026 14:53:42 +0200 Subject: [PATCH] flow: store livedev by id In prep for storing both directions for IPS. --- src/flow-hash.c | 19 +++++++++++-------- src/flow-manager.c | 12 ++++++------ src/flow-timeout.c | 3 ++- src/flow-util.c | 4 +++- src/flow-util.h | 4 ++-- src/flow.h | 2 +- src/output-json-flow.c | 5 +++-- src/output-json-netflow.c | 5 +++-- src/stream-tcp.c | 2 +- src/util-ebpf.c | 4 ++-- 10 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/flow-hash.c b/src/flow-hash.c index 1badf69177..c98a02efc0 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -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) diff --git a/src/flow-manager.c b/src/flow-manager.c index d9ef04da86..1b07674996 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -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++; diff --git a/src/flow-timeout.c b/src/flow-timeout.c index 35aef3d5dc..99ed4262a9 100644 --- a/src/flow-timeout.c +++ b/src/flow-timeout.c @@ -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); diff --git a/src/flow-util.c b/src/flow-util.c index 055161cc3b..6808b852e8 100644 --- a/src/flow-util.c +++ b/src/flow-util.c @@ -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); diff --git a/src/flow-util.h b/src/flow-util.h index 11bddefc85..f8a6ebf368 100644 --- a/src/flow-util.h +++ b/src/flow-util.h @@ -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; \ diff --git a/src/flow.h b/src/flow.h index 03a18dc81c..887eaa39a9 100644 --- a/src/flow.h +++ b/src/flow.h @@ -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 */ diff --git a/src/output-json-flow.c b/src/output-json-flow.c index 4f8c9a5ecf..58c2119632 100644 --- a/src/output-json-flow.c +++ b/src/output-json-flow.c @@ -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"); diff --git a/src/output-json-netflow.c b/src/output-json-netflow.c index dec777b86d..70d1168d3a 100644 --- a/src/output-json-netflow.c +++ b/src/output-json-netflow.c @@ -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"); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 00d6171bf8..a2218c0e23 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -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); diff --git a/src/util-ebpf.c b/src/util-ebpf.c index 86a3f69be5..2ebd65a635 100644 --- a/src/util-ebpf.c +++ b/src/util-ebpf.c @@ -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; }