From ce927990187cbcae2eb6f8766cb53f281aafafed Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Thu, 5 Dec 2024 13:10:23 +0000
Subject: [PATCH 01/14] feat(ct-metrics): BPF implementation

---
 pkg/plugin/conntrack/_cprog/conntrack.c       |  78 ++++++++++++++++--
 pkg/plugin/conntrack/conntrack_bpfel_x86.go   |  18 ++--
 pkg/plugin/conntrack/conntrack_bpfel_x86.o    | Bin 0 -> 1856 bytes
 pkg/plugin/packetparser/_cprog/packetparser.c |   4 +
 .../packetparser/packetparser_bpfel_x86.go    |  38 ++++++---
 .../packetparser/packetparser_bpfel_x86.o     | Bin 0 -> 59240 bytes
 6 files changed, 111 insertions(+), 27 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index c078ff78ab..dc05f1c64e 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -15,6 +15,21 @@ struct tcpmetadata {
 	__u32 tsecr; // TCP timestamp echo reply
 };
 
+struct conntrackmetadata {
+    __u8 traffic_direction; // This is the inital direction of the connection. It is set to egress if the connection is initiated from the host and ingress otherwise.
+    /*
+        bytes_*_count indicates the number of bytes sent and received in the forward and reply direction.
+        These will be reset to 0 every time an event is reported.
+    */
+    __u64 bytes_forward_count;
+    __u64 bytes_reply_count;
+    /*
+        packets_*_count indicates the number of packets sent and received in the forward and reply direction.
+        These will be reset to 0 every time an event is reported.
+    */
+    __u64 packets_forward_count;
+    __u64 packets_reply_count;
+};
 
 struct packet
 {
@@ -30,6 +45,7 @@ struct packet
 	__u8 proto;
 	__u8 flags; // For TCP packets, this is the TCP flags. For UDP packets, this is will always be 1 for conntrack purposes.
 	bool is_reply;
+    struct conntrackmetadata conntrack_metadata;
 };
 
 
@@ -68,6 +84,18 @@ struct ct_entry {
      * before retina deployment and the SYN packet was not captured.
      */
     bool is_direction_unknown;
+        /*
+        bytes_*_count indicates the number of bytes sent and received in the forward and reply direction.
+        These will be reset to 0 every time an event is reported.
+    */
+    __u64 bytes_forward_count;
+    __u64 bytes_reply_count;
+    /*
+        packets_*_count indicates the number of packets sent and received in the forward and reply direction.
+        These will be reset to 0 every time an event is reported.
+    */
+    __u64 packets_forward_count;
+    __u64 packets_reply_count;
 };
 
 struct {
@@ -110,11 +138,11 @@ static __always_inline __u8 _ct_get_traffic_direction(__u8 observation_point) {
 
 /**
  * Create a new TCP connection.
+ * @arg *p pointer to the packet to be processed.
  * @arg key The key to be used to create the new connection.
- * @arg flags The flags of the packet.
  * @arg observation_point The point in the network stack where the packet is observed.
  */
-static __always_inline bool _ct_create_new_tcp_connection(struct ct_v4_key key, __u8 flags, __u8 observation_point) {
+static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, struct ct_v4_key key,  __u8 observation_point) {
     struct ct_entry new_value;
     __builtin_memset(&new_value, 0, sizeof(struct ct_entry));
     __u64 now = bpf_mono_now();
@@ -123,10 +151,22 @@ static __always_inline bool _ct_create_new_tcp_connection(struct ct_v4_key key,
         return false;
     }
     new_value.eviction_time = now + CT_SYN_TIMEOUT;
-    new_value.flags_seen_tx_dir = flags;
+    new_value.flags_seen_tx_dir = p->flags;
     new_value.is_direction_unknown = false;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
+    new_value.packets_forward_count = 1;
+    new_value.bytes_forward_count = p->bytes;
     bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
+    // Update packet
+    p->is_reply = false;
+    p->traffic_direction = new_value.traffic_direction;
+    // Update initial conntrack metadata for the connection.
+    p->conntrack_metadata.bytes_forward_count = new_value.packets_forward_count;
+    p->conntrack_metadata.packets_forward_count = new_value.bytes_forward_count;
+    // The initial SYN is captured. Set the traffic direction of the connection.
+    // This is important for the case where the SYN packet is not captured
+    // and the connection is created with unknown direction.
+    p->conntrack_metadata.traffic_direction = new_value.traffic_direction;
     return true;
 }
 
@@ -148,10 +188,16 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     new_value.flags_seen_tx_dir = p->flags;
     new_value.last_report_tx_dir = now;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
+    new_value.packets_forward_count = 1;
+    new_value.bytes_forward_count = p->bytes;
     bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     // Update packet
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
+    // Update packet's conntrack metadata.
+    p->conntrack_metadata.bytes_forward_count = new_value.bytes_forward_count;
+    p->conntrack_metadata.packets_forward_count = new_value.packets_forward_count;
+    p->conntrack_metadata.traffic_direction = new_value.traffic_direction;
     return true;
 }
 
@@ -165,11 +211,8 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
 static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct ct_v4_key key, struct ct_v4_key reverse_key, __u8 observation_point) {
     // Check if the packet is a SYN packet.
     if (p->flags & TCP_SYN) {
-        // Update packet accordingly.
-        p->is_reply = false;
-        p->traffic_direction = _ct_get_traffic_direction(observation_point);
         // Create a new connection with a timeout of CT_SYN_TIMEOUT.
-        return _ct_create_new_tcp_connection(key, p->flags, observation_point);
+        return _ct_create_new_tcp_connection(p, key, observation_point);
     }
 
     // The packet is not a SYN packet and the connection corresponding to this packet is not found.
@@ -193,13 +236,22 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         p->is_reply = true;
         new_value.flags_seen_rx_dir = p->flags;
         new_value.last_report_rx_dir = now;
+        new_value.bytes_reply_count = p->bytes;
+        new_value.packets_reply_count = 1;
         bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
     } else { // Otherwise, the packet is considered as a packet in the send direction.
         p->is_reply = false;
         new_value.flags_seen_tx_dir = p->flags;
         new_value.last_report_tx_dir = now;
+        new_value.bytes_forward_count = p->bytes;
+        new_value.packets_forward_count = 1;
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
+    // Update packet's conntrack metadata.
+    p->conntrack_metadata.bytes_forward_count = new_value.bytes_forward_count;
+    p->conntrack_metadata.bytes_reply_count = new_value.bytes_reply_count;
+    p->conntrack_metadata.packets_forward_count = new_value.packets_forward_count;
+    p->conntrack_metadata.packets_reply_count = new_value.packets_reply_count;
     return true;
 }
 
@@ -318,6 +370,12 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = false;
         p->traffic_direction = entry->traffic_direction;
+        // Update packet count and bytes count on conntrack entry.
+        WRITE_ONCE(entry->packets_forward_count, READ_ONCE(entry->packets_forward_count) + 1);
+        WRITE_ONCE(entry->bytes_forward_count, READ_ONCE(entry->bytes_forward_count) + p->bytes);
+        // Update packet's conntract metadata.
+        p->conntrack_metadata.bytes_forward_count = entry->bytes_forward_count;
+        p->conntrack_metadata.packets_forward_count = entry->packets_forward_count;
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
     
@@ -333,6 +391,12 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = true;
         p->traffic_direction = entry->traffic_direction;
+        // Update packet count and bytes count on conntrack entry.
+        WRITE_ONCE(entry->packets_reply_count, READ_ONCE(entry->packets_reply_count) + 1);
+        WRITE_ONCE(entry->bytes_reply_count, READ_ONCE(entry->bytes_reply_count) + p->bytes);
+        // Update packet's conntract metadata.
+        p->conntrack_metadata.bytes_reply_count = entry->bytes_reply_count;
+        p->conntrack_metadata.packets_reply_count = entry->packets_reply_count;
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
 
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
index 9dede98e2c..7fe4957c18 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
@@ -13,13 +13,17 @@ import (
 )
 
 type conntrackCtEntry struct {
-	EvictionTime       uint32
-	LastReportTxDir    uint32
-	LastReportRxDir    uint32
-	TrafficDirection   uint8
-	FlagsSeenTxDir     uint8
-	FlagsSeenRxDir     uint8
-	IsDirectionUnknown bool
+	EvictionTime        uint32
+	LastReportTxDir     uint32
+	LastReportRxDir     uint32
+	TrafficDirection    uint8
+	FlagsSeenTxDir      uint8
+	FlagsSeenRxDir      uint8
+	IsDirectionUnknown  bool
+	BytesForwardCount   uint64
+	BytesReplyCount     uint64
+	PacketsForwardCount uint64
+	PacketsReplyCount   uint64
 }
 
 type conntrackCtV4Key struct {
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.o b/pkg/plugin/conntrack/conntrack_bpfel_x86.o
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4a2afcd828401cec9c84b820f22099fa65e3f4fe 100644
GIT binary patch
literal 1856
zcmbtVy>1gh5FR@Q41}NXPlGJcAcU+WL=i$1mmo(3MIs7mf+8(vdu^X`zB}&Lj$M%g
zBq$IMkb;7qiULuEXW$u-ka&PV1>fxLo}J^TVU%y@o7tJ2x!v{VX>DbxSSXN{0`1et
zvR)$R&=}X$q4FOiM{(oq&9?$wGLAu!i1Be$s5pT+V-`x_mCPibB7_tBj{>F@8wZb;
z;$f)E0Om`lp|1i*0G8_j^9nEn@H!4~+wfKByTEbaF|Z6k%4G}>G^MQGW@?v@LD$V3
z_s2D#q;`1{x}S2ryS$E(;z^Ka0BV({p<e;E&t1bS(C-X)pg#e&x6g)mpuZR%LGJ^n
zfB`Ux&76YX0V;;?fzKLF(Dw{?pf>?XnZLnJx$V2uHgjh%*EMteJq}=`c+N69cwXtL
z>B-`Szr>_VrssAIF*|Tr-*XT?ZwGh@euC$L*WhQN_kdmS^U$317J!_*n40t+HvV{9
zvirw1$O{w+v9Pwbupu5UKdOoKjn$eE)KH>7C${8}lDHwfh?<FF#a0x?O52)5ai~J9
z(YrZIy&&=0foxXNWqUL8BUjSlG{oH+`5GNJ=29|H@sMQSYbY-agz~zQd>0jC$u)!;
zh^7}GaK))h#cr$RHF#R;WNP_tI}wSLSSO7c^O!6z86}8buoZ;c0o8{}CZZL_+iu(x
zjj)HUNqy+T9~w{OHnyb7$64=qWIYUh5{r5iz4^J(XZvB$uJAx=7)jz??z?_ZQr8{m
zz3^m0krxCWLSm`Bz(w@{n}p(2?YdFIXZH```!SVXK^>*f8teuCKq35w@D(XjRmp)e
zYyMu!_xoMpHk&cdm8yw~m0O1%cD0VBUtL^Z;syUxZXjPjaJhAUaHEh~s<JV?-kGVt
zg?;??jf*pGjB&GU=HYjT^YcA8Cc^HYF|lt4#etdci6c5ZK<?)X=1jVS82c9M1T%a!
zf&3n^aG&h5^{xL3d=o1_L#Q1flkX-!-&@|ELx#B;SuT?gCV$#^IgerM+y7<103Dg-
A$^ZZW

literal 0
HcmV?d00001

diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c
index 0243ffadcb..b607e24165 100644
--- a/pkg/plugin/packetparser/_cprog/packetparser.c
+++ b/pkg/plugin/packetparser/_cprog/packetparser.c
@@ -201,6 +201,10 @@ static void parse(struct __sk_buff *skb, __u8 obs)
 		return;
 	}
 
+	// Initialize the conntrack metadata.
+	struct conntrackmetadata conntrack_metadata;
+	__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
+	p.conntrack_metadata = conntrack_metadata;
 
 	// Process the packet in ct
 	bool report __attribute__((unused));
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
index 6d3cb0bfe0..92cbd5cd4d 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
@@ -13,13 +13,17 @@ import (
 )
 
 type packetparserCtEntry struct {
-	EvictionTime       uint32
-	LastReportTxDir    uint32
-	LastReportRxDir    uint32
-	TrafficDirection   uint8
-	FlagsSeenTxDir     uint8
-	FlagsSeenRxDir     uint8
-	IsDirectionUnknown bool
+	EvictionTime        uint32
+	LastReportTxDir     uint32
+	LastReportRxDir     uint32
+	TrafficDirection    uint8
+	FlagsSeenTxDir      uint8
+	FlagsSeenRxDir      uint8
+	IsDirectionUnknown  bool
+	BytesForwardCount   uint64
+	BytesReplyCount     uint64
+	PacketsForwardCount uint64
+	PacketsReplyCount   uint64
 }
 
 type packetparserCtV4Key struct {
@@ -49,12 +53,20 @@ type packetparserPacket struct {
 		Tsval  uint32
 		Tsecr  uint32
 	}
-	ObservationPoint uint8
-	TrafficDirection uint8
-	Proto            uint8
-	Flags            uint8
-	IsReply          bool
-	_                [3]byte
+	ObservationPoint  uint8
+	TrafficDirection  uint8
+	Proto             uint8
+	Flags             uint8
+	IsReply           bool
+	_                 [3]byte
+	ConntrackMetadata struct {
+		TrafficDirection    uint8
+		_                   [7]byte
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+	}
 }
 
 // loadPacketparser returns the embedded CollectionSpec for packetparser.
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.o b/pkg/plugin/packetparser/packetparser_bpfel_x86.o
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2002b5e4f3eb79925e5018887f1a13b0e4c3f313 100644
GIT binary patch
literal 59240
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

literal 0
HcmV?d00001


From 9642697d5f66f4f1553b9cc0720c8aeed68d3cc3 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 6 Dec 2024 13:53:23 +0000
Subject: [PATCH 02/14] feat(ct-metrics): group counters in ct meta and use
 memcpy

---
 pkg/plugin/conntrack/_cprog/conntrack.c       |  74 +++++++-----------
 pkg/plugin/conntrack/conntrack_bpfel_x86.go   |  26 +++---
 pkg/plugin/conntrack/conntrack_bpfel_x86.o    | Bin 1856 -> 1928 bytes
 pkg/plugin/dropreason/kprobe_bpfel_x86.o      | Bin 0 -> 24384 bytes
 pkg/plugin/filter/filter_bpfel_x86.o          | Bin 0 -> 2144 bytes
 pkg/plugin/mock/plugin.go                     |  29 ++++---
 .../packetforward/packetforward_bpfel_x86.o   | Bin 0 -> 4504 bytes
 .../packetparser/packetparser_bpfel_x86.go    |  30 ++++---
 .../packetparser/packetparser_bpfel_x86.o     | Bin 59240 -> 57968 bytes
 9 files changed, 76 insertions(+), 83 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index dc05f1c64e..ad17ebb90b 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -7,6 +7,7 @@
 #include "compiler.h"
 #include "bpf_helpers.h"
 #include "conntrack.h"
+#include "string.h"
 
 struct tcpmetadata {
 	__u32 seq; // TCP sequence number
@@ -16,19 +17,23 @@ struct tcpmetadata {
 };
 
 struct conntrackmetadata {
-    __u8 traffic_direction; // This is the inital direction of the connection. It is set to egress if the connection is initiated from the host and ingress otherwise.
     /*
         bytes_*_count indicates the number of bytes sent and received in the forward and reply direction.
-        These will be reset to 0 every time an event is reported.
+        These values will be based on the conntrack entry.
     */
     __u64 bytes_forward_count;
     __u64 bytes_reply_count;
     /*
         packets_*_count indicates the number of packets sent and received in the forward and reply direction.
-        These will be reset to 0 every time an event is reported.
+        These values will be based on the conntrack entry.
     */
     __u64 packets_forward_count;
     __u64 packets_reply_count;
+    /*
+        This is the inital direction of the connection.
+        It is set to egress if the connection is initiated from the host and ingress otherwise.
+    */
+    __u8 traffic_direction;
 };
 
 struct packet
@@ -84,18 +89,7 @@ struct ct_entry {
      * before retina deployment and the SYN packet was not captured.
      */
     bool is_direction_unknown;
-        /*
-        bytes_*_count indicates the number of bytes sent and received in the forward and reply direction.
-        These will be reset to 0 every time an event is reported.
-    */
-    __u64 bytes_forward_count;
-    __u64 bytes_reply_count;
-    /*
-        packets_*_count indicates the number of packets sent and received in the forward and reply direction.
-        These will be reset to 0 every time an event is reported.
-    */
-    __u64 packets_forward_count;
-    __u64 packets_reply_count;
+    struct conntrackmetadata conntrack_metadata;
 };
 
 struct {
@@ -154,19 +148,18 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     new_value.flags_seen_tx_dir = p->flags;
     new_value.is_direction_unknown = false;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
-    new_value.packets_forward_count = 1;
-    new_value.bytes_forward_count = p->bytes;
+    new_value.conntrack_metadata.packets_forward_count = 1;
+    new_value.conntrack_metadata.bytes_forward_count = p->bytes;
+    // The initial SYN is captured. Set the traffic direction of the connection.
+    // This is important for the case where the SYN packet is not captured
+    // and the connection is created with unknown direction.
+    new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
     bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     // Update packet
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
     // Update initial conntrack metadata for the connection.
-    p->conntrack_metadata.bytes_forward_count = new_value.packets_forward_count;
-    p->conntrack_metadata.packets_forward_count = new_value.bytes_forward_count;
-    // The initial SYN is captured. Set the traffic direction of the connection.
-    // This is important for the case where the SYN packet is not captured
-    // and the connection is created with unknown direction.
-    p->conntrack_metadata.traffic_direction = new_value.traffic_direction;
+    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
     return true;
 }
 
@@ -188,16 +181,14 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     new_value.flags_seen_tx_dir = p->flags;
     new_value.last_report_tx_dir = now;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
-    new_value.packets_forward_count = 1;
-    new_value.bytes_forward_count = p->bytes;
+    new_value.conntrack_metadata.packets_forward_count = 1;
+    new_value.conntrack_metadata.bytes_forward_count = p->bytes;
     bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     // Update packet
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
     // Update packet's conntrack metadata.
-    p->conntrack_metadata.bytes_forward_count = new_value.bytes_forward_count;
-    p->conntrack_metadata.packets_forward_count = new_value.packets_forward_count;
-    p->conntrack_metadata.traffic_direction = new_value.traffic_direction;
+    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
     return true;
 }
 
@@ -236,22 +227,19 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         p->is_reply = true;
         new_value.flags_seen_rx_dir = p->flags;
         new_value.last_report_rx_dir = now;
-        new_value.bytes_reply_count = p->bytes;
-        new_value.packets_reply_count = 1;
+        new_value.conntrack_metadata.bytes_reply_count = p->bytes;
+        new_value.conntrack_metadata.packets_reply_count = 1;
         bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
     } else { // Otherwise, the packet is considered as a packet in the send direction.
         p->is_reply = false;
         new_value.flags_seen_tx_dir = p->flags;
         new_value.last_report_tx_dir = now;
-        new_value.bytes_forward_count = p->bytes;
-        new_value.packets_forward_count = 1;
+        new_value.conntrack_metadata.bytes_forward_count = p->bytes;
+        new_value.conntrack_metadata.packets_forward_count = 1;
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
     // Update packet's conntrack metadata.
-    p->conntrack_metadata.bytes_forward_count = new_value.bytes_forward_count;
-    p->conntrack_metadata.bytes_reply_count = new_value.bytes_reply_count;
-    p->conntrack_metadata.packets_forward_count = new_value.packets_forward_count;
-    p->conntrack_metadata.packets_reply_count = new_value.packets_reply_count;
+    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
     return true;
 }
 
@@ -371,11 +359,10 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         p->is_reply = false;
         p->traffic_direction = entry->traffic_direction;
         // Update packet count and bytes count on conntrack entry.
-        WRITE_ONCE(entry->packets_forward_count, READ_ONCE(entry->packets_forward_count) + 1);
-        WRITE_ONCE(entry->bytes_forward_count, READ_ONCE(entry->bytes_forward_count) + p->bytes);
+        WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
+        WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
         // Update packet's conntract metadata.
-        p->conntrack_metadata.bytes_forward_count = entry->bytes_forward_count;
-        p->conntrack_metadata.packets_forward_count = entry->packets_forward_count;
+        memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
     
@@ -392,11 +379,10 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         p->is_reply = true;
         p->traffic_direction = entry->traffic_direction;
         // Update packet count and bytes count on conntrack entry.
-        WRITE_ONCE(entry->packets_reply_count, READ_ONCE(entry->packets_reply_count) + 1);
-        WRITE_ONCE(entry->bytes_reply_count, READ_ONCE(entry->bytes_reply_count) + p->bytes);
+        WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
+        WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
         // Update packet's conntract metadata.
-        p->conntrack_metadata.bytes_reply_count = entry->bytes_reply_count;
-        p->conntrack_metadata.packets_reply_count = entry->packets_reply_count;
+        memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
 
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
index 7fe4957c18..a3a3a07951 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
@@ -13,17 +13,21 @@ import (
 )
 
 type conntrackCtEntry struct {
-	EvictionTime        uint32
-	LastReportTxDir     uint32
-	LastReportRxDir     uint32
-	TrafficDirection    uint8
-	FlagsSeenTxDir      uint8
-	FlagsSeenRxDir      uint8
-	IsDirectionUnknown  bool
-	BytesForwardCount   uint64
-	BytesReplyCount     uint64
-	PacketsForwardCount uint64
-	PacketsReplyCount   uint64
+	EvictionTime       uint32
+	LastReportTxDir    uint32
+	LastReportRxDir    uint32
+	TrafficDirection   uint8
+	FlagsSeenTxDir     uint8
+	FlagsSeenRxDir     uint8
+	IsDirectionUnknown bool
+	ConntrackMetadata  struct {
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+		TrafficDirection    uint8
+		_                   [7]byte
+	}
 }
 
 type conntrackCtV4Key struct {
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.o b/pkg/plugin/conntrack/conntrack_bpfel_x86.o
index 4a2afcd828401cec9c84b820f22099fa65e3f4fe..ebe86751b01c3579f40e19a3906f1010af4680d3 100644
GIT binary patch
delta 384
zcmX|*zb^zq6vy9;owXO-T^#mkG{Vx*Q3!il4W(+$EfsewvV}&R?usj%*NIjmLct%f
z8c}LhYK6pq!1raBm-)W$=lz(;WaVz<B2eA_{ATG|6Nx_hr$5Fca#r|U#b?usB)lrp
zOwLM7HWmN|9-v+YkHRIk3J$@|f;-@of-~?lGz1ZPJqY2|kS=ppc%MQdUe_fx&Mocp
zt{zrCXl~~QJNX*XEdYOzUAhO4z&p?rcnqG2z!Pw}^a>%$^}M8a)HoGsPCkBVUoFN-
zyPY1}_#kTSr*_Y#mYPX&NYRGm|LNb52b^t=oFjg7>gtX^od?}8d}Uq~vvrsC5(;<C
Tgz`&nxHbNE15Jjf24{Z(Yxh7t

delta 316
zcmeC+KfpIZgVAB4rZ;B=69WSX@0wWqpOu?|fyH2QBV%%^0wV*1AOi!#0U$PlvKfH1
z2bApqq+@^>2si|QL?VRE2%<QErldpVgn;~9s2ot7!2yV&fJtQXL?&@wpkla)7*Iq#
zvH_?bqJ@E>706%($~ypYCy)(P&d>nF{Xn)bkUjv!vw>_;APv&A7>I#@PaMK!*aGAO
z5kE*!VzVH#IOF69mH@7#{QMk-cqbq^c{xkrWN}tW#*WE`tm~P6vP^!&dW_L)@=7*y
ZrWZgCn;p{+mdQ%&c1$~1CMU700RT^TEHnTB

diff --git a/pkg/plugin/dropreason/kprobe_bpfel_x86.o b/pkg/plugin/dropreason/kprobe_bpfel_x86.o
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a0098ede38482561f4961ac10fc98c79ff9e3792 100644
GIT binary patch
literal 24384
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

literal 0
HcmV?d00001

diff --git a/pkg/plugin/filter/filter_bpfel_x86.o b/pkg/plugin/filter/filter_bpfel_x86.o
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bf6c879c816f34c58c39471bdebc664f91e53879 100644
GIT binary patch
literal 2144
zcmbtVJ8KkC6h6C&W;I4lREUwtfFM!ACL{>45H<^mh$-T$(89@NcQzR^nH^?lL*fI2
zAXwUnji6X*Wf{9ziG@GFA7CL^T4*7x-*@NU$?g~s@gv_ok9*F!=RS7wU}kPMpUa6s
zPJYOaWxOIU_w48;rIw@@k(HreEt*?MvLGu%Kb5`xie8bPyvWa1t2LM@`UrD$ZEOFQ
zwr}WOXcJEp@z3LnZ#fy%S?{n0c}lMZcfJdQHgnz3t<)4w3ECF=dqKT*69<n%elNsv
z5V73_NDJ%%iL)Se3mgN10%Oi8RsN{8AO3POSKyi#bsT$So<_dUXwumy<23SzjFyQ}
z7lS$U-8~L@12lQJpmU!k@HV&)+ytxO0q{K-fCoV)-GQLL1pOg>m^zHX)Pw9h0{aQb
zb9e><g`*grD^=7@V{hHBU?cv(0OT+f{HZPUCvn1F#S3Dw?dhvmr*GQVF5Q~3uiu=X
zv29s(!prW4gpphG)_pgSsuMeiY)(!{GiZ2Afm^kb<mS|lr?Tus5^sdAtRQ>M@tZD7
z*)`u;YCv1J-5`!Uw;`by1YWQtksEt~W7j-Cb|djZr&^6<v0nGZE_3wj^_6BQ#n@d(
zr<E|OFO7BN6f0tBG~%dPiLIn}3msS&th?!~SF=VI!<x;0lB%}ryQ?FoJIak(r;&K(
zjNF$ZA{!!n^Oim{o-;WIE`S8z(Hjuwt8fe>?~Fdab>c1f0UTZyRg1R42o&01z`lD)
zUD_v5F!vbBU(ls~Rh>b6cl-q{D7iC?LLF#}M>`59G4`k3O7b?~V{Zia#=U&ho1{*%
z9zmT`C6F-od}5~dLdFg=cApd@*H126Y31v)Mc#aJ7acd1J`LYrTebOa@GPZ>M-V%U
zkQ=K?vL33)T)8}MPw4gjS4^XT`k-YBo!1{VC*#-0mU<aRAHQ|&C~3poi<v7JMN8)L
zTT;@t5g&Q*0N)?M?_VA?`Nq$0IBR70@ESg1JQ3+=@{ObY8)tl!pSAIwi?%_xm3po~
z+pYi4yY$bqGV7cE55bo`Qx^ZEH?&Ek4cYbizhJlZzv{qwoy+s%cQ(8JBz#?StvbXe
gm|{xbf3~-*eF+(vBT_Zy_4@0&qPZipzWLw#8+^aPQ~&?~

literal 0
HcmV?d00001

diff --git a/pkg/plugin/mock/plugin.go b/pkg/plugin/mock/plugin.go
index 888d9267dd..403a472c3c 100644
--- a/pkg/plugin/mock/plugin.go
+++ b/pkg/plugin/mock/plugin.go
@@ -5,11 +5,11 @@
 //
 
 // Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/microsoft/retina/pkg/plugin/ (interfaces: Plugin)
+// Source: github.com/microsoft/retina/pkg/plugin (interfaces: Plugin)
 //
 // Generated by this command:
 //
-//	mockgen -destination=mock/plugin.go -copyright_file=../lib/ignore_headers.txt -package=plugin github.com/microsoft/retina/pkg/plugin/ Plugin
+//	mockgen -destination=mock/plugin.go -copyright_file=../lib/ignore_headers.txt -package=plugin github.com/microsoft/retina/pkg/plugin Plugin
 //
 
 // Package plugin is a generated GoMock package.
@@ -27,7 +27,6 @@ import (
 type MockPlugin struct {
 	ctrl     *gomock.Controller
 	recorder *MockPluginMockRecorder
-	isgomock struct{}
 }
 
 // MockPluginMockRecorder is the mock recorder for MockPlugin.
@@ -48,31 +47,31 @@ func (m *MockPlugin) EXPECT() *MockPluginMockRecorder {
 }
 
 // Compile mocks base method.
-func (m *MockPlugin) Compile(ctx context.Context) error {
+func (m *MockPlugin) Compile(arg0 context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Compile", ctx)
+	ret := m.ctrl.Call(m, "Compile", arg0)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Compile indicates an expected call of Compile.
-func (mr *MockPluginMockRecorder) Compile(ctx any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Compile(arg0 any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compile", reflect.TypeOf((*MockPlugin)(nil).Compile), ctx)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compile", reflect.TypeOf((*MockPlugin)(nil).Compile), arg0)
 }
 
 // Generate mocks base method.
-func (m *MockPlugin) Generate(ctx context.Context) error {
+func (m *MockPlugin) Generate(arg0 context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Generate", ctx)
+	ret := m.ctrl.Call(m, "Generate", arg0)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Generate indicates an expected call of Generate.
-func (mr *MockPluginMockRecorder) Generate(ctx any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Generate(arg0 any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockPlugin)(nil).Generate), ctx)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockPlugin)(nil).Generate), arg0)
 }
 
 // Init mocks base method.
@@ -118,17 +117,17 @@ func (mr *MockPluginMockRecorder) SetupChannel(arg0 any) *gomock.Call {
 }
 
 // Start mocks base method.
-func (m *MockPlugin) Start(ctx context.Context) error {
+func (m *MockPlugin) Start(arg0 context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Start", ctx)
+	ret := m.ctrl.Call(m, "Start", arg0)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Start indicates an expected call of Start.
-func (mr *MockPluginMockRecorder) Start(ctx any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Start(arg0 any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockPlugin)(nil).Start), ctx)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockPlugin)(nil).Start), arg0)
 }
 
 // Stop mocks base method.
diff --git a/pkg/plugin/packetforward/packetforward_bpfel_x86.o b/pkg/plugin/packetforward/packetforward_bpfel_x86.o
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5f175500269f66b9fa5956441e65ccf97025395a 100644
GIT binary patch
literal 4504
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
EKhp6_`2YX_

literal 0
HcmV?d00001

diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
index 92cbd5cd4d..440a4ccc59 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
@@ -13,17 +13,21 @@ import (
 )
 
 type packetparserCtEntry struct {
-	EvictionTime        uint32
-	LastReportTxDir     uint32
-	LastReportRxDir     uint32
-	TrafficDirection    uint8
-	FlagsSeenTxDir      uint8
-	FlagsSeenRxDir      uint8
-	IsDirectionUnknown  bool
-	BytesForwardCount   uint64
-	BytesReplyCount     uint64
-	PacketsForwardCount uint64
-	PacketsReplyCount   uint64
+	EvictionTime       uint32
+	LastReportTxDir    uint32
+	LastReportRxDir    uint32
+	TrafficDirection   uint8
+	FlagsSeenTxDir     uint8
+	FlagsSeenRxDir     uint8
+	IsDirectionUnknown bool
+	ConntrackMetadata  struct {
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+		TrafficDirection    uint8
+		_                   [7]byte
+	}
 }
 
 type packetparserCtV4Key struct {
@@ -60,12 +64,12 @@ type packetparserPacket struct {
 	IsReply           bool
 	_                 [3]byte
 	ConntrackMetadata struct {
-		TrafficDirection    uint8
-		_                   [7]byte
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
 		PacketsForwardCount uint64
 		PacketsReplyCount   uint64
+		TrafficDirection    uint8
+		_                   [7]byte
 	}
 }
 
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.o b/pkg/plugin/packetparser/packetparser_bpfel_x86.o
index 2002b5e4f3eb79925e5018887f1a13b0e4c3f313..d57a7d4a51f4f6e9a5e390dd25324dccdabe35fb 100644
GIT binary patch
literal 57968
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
J^J|da{{<rJ-t+(f

literal 59240
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


From 15d85f6f0709c7c60bc824edff71c8a48f44e7ae Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Mon, 9 Dec 2024 09:11:19 +0000
Subject: [PATCH 03/14] feat(ct-metrics): use __builtin_memcpy

---
 pkg/plugin/conntrack/_cprog/conntrack.c         |  11 +++++------
 pkg/plugin/conntrack/conntrack_bpfel_x86.o      | Bin 1928 -> 0 bytes
 .../packetparser/packetparser_bpfel_x86.o       | Bin 57968 -> 0 bytes
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index ad17ebb90b..ef2005d9fa 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -7,7 +7,6 @@
 #include "compiler.h"
 #include "bpf_helpers.h"
 #include "conntrack.h"
-#include "string.h"
 
 struct tcpmetadata {
 	__u32 seq; // TCP sequence number
@@ -159,7 +158,7 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
     // Update initial conntrack metadata for the connection.
-    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
     return true;
 }
 
@@ -188,7 +187,7 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
     // Update packet's conntrack metadata.
-    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
+    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
     return true;
 }
 
@@ -239,7 +238,7 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
     // Update packet's conntrack metadata.
-    memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
     return true;
 }
 
@@ -362,7 +361,7 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
         WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
         // Update packet's conntract metadata.
-        memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
     
@@ -382,7 +381,7 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
         WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
         // Update packet's conntract metadata.
-        memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
 
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.o b/pkg/plugin/conntrack/conntrack_bpfel_x86.o
index ebe86751b01c3579f40e19a3906f1010af4680d3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001

literal 1928
zcmbtVJ#Q015FI-P4hVtpO#_yoKoPPMh@uFkxCA*;q)0>|O%T#@KCk0b&UfZ+?bsDA
zC@7$T5+o`bgi`SXl8&B=ii(OKkP_bP?fIO8RE+X=-ptPI%<Zl>&#SA;#X^BnDbN9B
zR_Y~sc`W0$rZ!psjLhOj*@s^Rx@sKni$shcS)t+>=8Rb=ftQCS@f0DP*nbi*t)y}A
zXel0tx&~mrbPoC^Z~|bN0+^S98GzTZf%}H9K|cUa15be!0Ag7f9%@R%dQTGDIt5)b
zbKD=-e3sbOICMARdUtspBgF}j7XW;vdFa<b+UGmN%h0=q+tB+!+S@n7o6tWEZ$lpd
zXMr9tj?J8e9soDMAr|*{E8%HRr776FU$-&00Dhh$A!~-);5EYs;620l!1n>}i4X1-
z0I@D$c$4q~f3po3DPBq$9X`|KWc6h6$`LWil3A}G;YfX-K=@ABz%KY1=mGEr{37%o
z1N<^HCw&DV6MP?;e#d}6-a37MSo4067bp^9aeaMpQ#@LETooIeYgHl0RiZm9wq>8<
z$Q53j>ak+QRy&N8wl!%-p$f4^=iXiF1hKaj$a*<hwlg!Ax#A|LA#OhNxlJeHQZi6c
zpJdl_l@|s=c`Zr4gNl*l8bb9%-HQ&nqQs>lr_u0So|Zb98osj?i&#pmlf;a8OqLgC
z38E8h2jNaYZWy2q$K4h!shql_9IAz(PhyG3;cPb9S27ljFxqjVx^Tk|wz8&u=-Tfa
zPa6wLm5)okqmkH}x!G)Q{4m%m^FXTKmc&QVb^MN`mebQ4=E<1aUJ!T)iKOxZ2PMrX
zP^IOxV?N-ch40X0a!qxRz7JrZ`G*eSw}|hKMHMA`$}IVJCExG1gj26aID4wZDpF1j
zy5G_|l73}rW0@EHPq~A9{ZQuCS>zuEq?)MV$i0sW+YEj~N5vjBMmT@}sPOy6`S~7f
z6O`_sG5PH~BsQ#kPaM$X0rECiFlW*NV$wHVCzxT{d_TW^EZisOru9?*b@;|se}_;5
gU?{f9&-a$MXOUs9#xPeClRs^|oX1G(r~ecG0I1CM-v9sr

diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.o b/pkg/plugin/packetparser/packetparser_bpfel_x86.o
index d57a7d4a51f4f6e9a5e390dd25324dccdabe35fb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001

literal 57968
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
J^J|da{{<rJ-t+(f


From 87848a5d83572e500b6d87989f26406f9036362d Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Mon, 9 Dec 2024 16:06:28 +0000
Subject: [PATCH 04/14] feat(ct-metrics): process metrics within IFDEF

---
 .../retina/templates/agent/configmap.yaml     |  1 +
 .../helm/retina/templates/configmap.yaml      |  1 +
 .../controller/helm/retina/values.yaml        |  1 +
 pkg/config/config.go                          |  1 +
 pkg/plugin/conntrack/_cprog/conntrack.c       | 92 +++++++++++++------
 pkg/plugin/conntrack/_cprog/dynamic.h         |  1 +
 pkg/plugin/conntrack/conntrack_linux.go       | 21 +++++
 pkg/plugin/conntrack/types_linux.go           |  5 +-
 pkg/plugin/packetparser/_cprog/dynamic.h      |  1 +
 pkg/plugin/packetparser/_cprog/packetparser.c | 12 ++-
 pkg/plugin/packetparser/packetparser_linux.go | 15 ++-
 11 files changed, 115 insertions(+), 36 deletions(-)
 create mode 100644 pkg/plugin/conntrack/_cprog/dynamic.h

diff --git a/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml b/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml
index 0e80cefed2..704cf5a9c5 100644
--- a/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml
+++ b/deploy/hubble/manifests/controller/helm/retina/templates/agent/configmap.yaml
@@ -108,6 +108,7 @@ data:
     metricsIntervalDuration: {{ .Values.metricsIntervalDuration }}
     enableTelemetry: {{ .Values.enableTelemetry }}
     enablePodLevel: {{ .Values.enablePodLevel }}
+    enableConntrackMetrics: {{ .Values.enableConntrackMetrics }}
     remoteContext: {{ .Values.remoteContext }}
     enableAnnotations: {{ .Values.enableAnnotations }}
     bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }}
diff --git a/deploy/legacy/manifests/controller/helm/retina/templates/configmap.yaml b/deploy/legacy/manifests/controller/helm/retina/templates/configmap.yaml
index 6218bc62b3..a53b8537a6 100644
--- a/deploy/legacy/manifests/controller/helm/retina/templates/configmap.yaml
+++ b/deploy/legacy/manifests/controller/helm/retina/templates/configmap.yaml
@@ -19,6 +19,7 @@ data:
     metricsIntervalDuration: {{ .Values.metricsIntervalDuration }}
     enableTelemetry: {{ .Values.enableTelemetry }}
     enablePodLevel: {{ .Values.enablePodLevel }}
+    enableConntrackMetrics: {{ .Values.enableConntrackMetrics }}
     remoteContext: {{ .Values.remoteContext }}
     enableAnnotations: {{ .Values.enableAnnotations }}
     bypassLookupIPOfInterest: {{ .Values.bypassLookupIPOfInterest }}
diff --git a/deploy/legacy/manifests/controller/helm/retina/values.yaml b/deploy/legacy/manifests/controller/helm/retina/values.yaml
index f95da03629..7dee8c519e 100644
--- a/deploy/legacy/manifests/controller/helm/retina/values.yaml
+++ b/deploy/legacy/manifests/controller/helm/retina/values.yaml
@@ -35,6 +35,7 @@ image:
   # Overrides the image tag whose default is the chart appVersion.
   tag: "v0.0.2"
 
+enableConntrackMetrics: false
 enablePodLevel: false
 remoteContext: false
 enableAnnotations: false
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 8ee4798ea2..5a5098456e 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -61,6 +61,7 @@ type Config struct {
 	EnableTelemetry          bool          `yaml:"enableTelemetry"`
 	EnableRetinaEndpoint     bool          `yaml:"enableRetinaEndpoint"`
 	EnablePodLevel           bool          `yaml:"enablePodLevel"`
+	EnableConntrackMetrics   bool          `yaml:"enableConntrackMetrics"`
 	RemoteContext            bool          `yaml:"remoteContext"`
 	EnableAnnotations        bool          `yaml:"enableAnnotations"`
 	BypassLookupIPOfInterest bool          `yaml:"bypassLookupIPOfInterest"`
diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index ef2005d9fa..7e24d2fa3a 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -7,6 +7,7 @@
 #include "compiler.h"
 #include "bpf_helpers.h"
 #include "conntrack.h"
+#include "dynamic.h"
 
 struct tcpmetadata {
 	__u32 seq; // TCP sequence number
@@ -147,18 +148,24 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     new_value.flags_seen_tx_dir = p->flags;
     new_value.is_direction_unknown = false;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
-    new_value.conntrack_metadata.packets_forward_count = 1;
-    new_value.conntrack_metadata.bytes_forward_count = p->bytes;
-    // The initial SYN is captured. Set the traffic direction of the connection.
-    // This is important for the case where the SYN packet is not captured
-    // and the connection is created with unknown direction.
-    new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
-    bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
+
+    #ifdef CONNTRACK_METRICS
+    #if CONNTRACK_METRICS == 1
+        new_value.conntrack_metadata.packets_forward_count = 1;
+        new_value.conntrack_metadata.bytes_forward_count = p->bytes;
+        // The initial SYN is captured. Set the traffic direction of the connection.
+        // This is important for the case where the SYN packet is not captured
+        // and the connection is created with unknown direction.
+        new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
+        // Update initial conntrack metadata for the connection.
+        __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    #endif
+    #endif // CONNTRACK_METRICS
+
     // Update packet
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
-    // Update initial conntrack metadata for the connection.
-    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     return true;
 }
 
@@ -180,14 +187,19 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     new_value.flags_seen_tx_dir = p->flags;
     new_value.last_report_tx_dir = now;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
-    new_value.conntrack_metadata.packets_forward_count = 1;
-    new_value.conntrack_metadata.bytes_forward_count = p->bytes;
-    bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
+    #ifdef CONNTRACK_METRICS
+    #if CONNTRACK_METRICS == 1
+        new_value.conntrack_metadata.packets_forward_count = 1;
+        new_value.conntrack_metadata.bytes_forward_count = p->bytes;
+        // Update packet's conntrack metadata.
+        __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
+    #endif
+    #endif // CONNTRACK_METRICS    
+
     // Update packet
     p->is_reply = false;
     p->traffic_direction = new_value.traffic_direction;
-    // Update packet's conntrack metadata.
-    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
+    bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     return true;
 }
 
@@ -226,19 +238,31 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         p->is_reply = true;
         new_value.flags_seen_rx_dir = p->flags;
         new_value.last_report_rx_dir = now;
-        new_value.conntrack_metadata.bytes_reply_count = p->bytes;
-        new_value.conntrack_metadata.packets_reply_count = 1;
+        #ifdef CONNTRACK_METRICS
+        #if CONNTRACK_METRICS == 1
+            new_value.conntrack_metadata.bytes_reply_count = p->bytes;
+            new_value.conntrack_metadata.packets_reply_count = 1;
+        #endif
+        #endif // CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
     } else { // Otherwise, the packet is considered as a packet in the send direction.
         p->is_reply = false;
         new_value.flags_seen_tx_dir = p->flags;
         new_value.last_report_tx_dir = now;
-        new_value.conntrack_metadata.bytes_forward_count = p->bytes;
-        new_value.conntrack_metadata.packets_forward_count = 1;
+        #ifdef CONNTRACK_METRICS
+        #if CONNTRACK_METRICS == 1
+            new_value.conntrack_metadata.bytes_forward_count = p->bytes;
+            new_value.conntrack_metadata.packets_forward_count = 1;
+        #endif
+        #endif // CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
-    // Update packet's conntrack metadata.
-    __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    #ifdef CONNTRACK_METRICS
+    #if CONNTRACK_METRICS == 1
+        // Update packet's conntrack metadata.
+        __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
+    #endif
+    #endif // CONNTRACK_METRICS
     return true;
 }
 
@@ -357,11 +381,15 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = false;
         p->traffic_direction = entry->traffic_direction;
-        // Update packet count and bytes count on conntrack entry.
-        WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
-        WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
-        // Update packet's conntract metadata.
-        __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        #ifdef CONNTRACK_METRICS
+        #if CONNTRACK_METRICS == 1
+            // Update packet count and bytes count on conntrack entry.
+            WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
+            WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
+            // Update packet's conntract metadata.
+            __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        #endif
+        #endif // CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
     
@@ -377,11 +405,15 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = true;
         p->traffic_direction = entry->traffic_direction;
-        // Update packet count and bytes count on conntrack entry.
-        WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
-        WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
-        // Update packet's conntract metadata.
-        __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        #ifdef CONNTRACK_METRICS
+        #if CONNTRACK_METRICS == 1
+            // Update packet count and bytes count on conntrack entry.
+            WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
+            WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
+            // Update packet's conntract metadata.
+            __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
+        #endif
+        #endif // CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
 
diff --git a/pkg/plugin/conntrack/_cprog/dynamic.h b/pkg/plugin/conntrack/_cprog/dynamic.h
new file mode 100644
index 0000000000..965f8f2bea
--- /dev/null
+++ b/pkg/plugin/conntrack/_cprog/dynamic.h
@@ -0,0 +1 @@
+#define CONNTRACK_METRICS 0
\ No newline at end of file
diff --git a/pkg/plugin/conntrack/conntrack_linux.go b/pkg/plugin/conntrack/conntrack_linux.go
index 0f67b427ef..2ed6db731b 100644
--- a/pkg/plugin/conntrack/conntrack_linux.go
+++ b/pkg/plugin/conntrack/conntrack_linux.go
@@ -6,11 +6,15 @@ package conntrack
 
 import (
 	"context"
+	"fmt"
+	"path"
+	"runtime"
 	"time"
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/rlimit"
 	"github.com/microsoft/retina/internal/ktime"
+	"github.com/microsoft/retina/pkg/loader"
 	"github.com/microsoft/retina/pkg/log"
 	plugincommon "github.com/microsoft/retina/pkg/plugin/common"
 	_ "github.com/microsoft/retina/pkg/plugin/conntrack/_cprog" // nolint // This is needed so cprog is included when vendoring
@@ -66,6 +70,23 @@ func New() (*Conntrack, error) {
 	return ct, nil
 }
 
+// Generate dynamic header file for conntrack eBPF program.
+func GenerateDynamic(ctx context.Context, conntrackMetrics int) error {
+	// Get absolute path to this file during runtime.
+	_, filename, _, ok := runtime.Caller(0)
+	if !ok {
+		return errors.New("unable to get absolute path for conntrack file")
+	}
+	dir := path.Dir(filename)
+	dynamicHeaderPath := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName)
+	st := fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
+	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
+	if err != nil {
+		return errors.Wrap(err, "failed to write conntrack dynamic header")
+	}
+	return nil
+}
+
 // Run starts the Conntrack garbage collection loop.
 func (ct *Conntrack) Run(ctx context.Context) error {
 	ticker := time.NewTicker(ct.gcFrequency)
diff --git a/pkg/plugin/conntrack/types_linux.go b/pkg/plugin/conntrack/types_linux.go
index 637fcade4a..63fa7e90a9 100644
--- a/pkg/plugin/conntrack/types_linux.go
+++ b/pkg/plugin/conntrack/types_linux.go
@@ -9,7 +9,10 @@ import (
 )
 
 const (
-	defaultGCFrequency = 15 * time.Second
+	defaultGCFrequency    = 15 * time.Second
+	bpfSourceDir          = "_cprog"
+	bpfSourceFileName     = "conntrack.c"
+	dynamicHeaderFileName = "dynamic.h"
 )
 
 type Conntrack struct {
diff --git a/pkg/plugin/packetparser/_cprog/dynamic.h b/pkg/plugin/packetparser/_cprog/dynamic.h
index ecadc42211..ac14b29aab 100644
--- a/pkg/plugin/packetparser/_cprog/dynamic.h
+++ b/pkg/plugin/packetparser/_cprog/dynamic.h
@@ -1,2 +1,3 @@
 #define BYPASS_LOOKUP_IP_OF_INTEREST 0
 #define DATA_AGGREGATION_LEVEL 0
+#define CONNTRACK_METRICS 0
diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c
index b607e24165..3603d83a73 100644
--- a/pkg/plugin/packetparser/_cprog/packetparser.c
+++ b/pkg/plugin/packetparser/_cprog/packetparser.c
@@ -201,10 +201,14 @@ static void parse(struct __sk_buff *skb, __u8 obs)
 		return;
 	}
 
-	// Initialize the conntrack metadata.
-	struct conntrackmetadata conntrack_metadata;
-	__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
-	p.conntrack_metadata = conntrack_metadata;
+	#ifdef CONNTRACK_METRICS
+	#if CONNTRACK_METRICS == 1
+		// Initialize conntrack metadata in packet struct.
+		struct conntrackmetadata conntrack_metadata;
+		__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
+		p.conntrack_metadata = conntrack_metadata;
+	#endif
+	#endif // CONNTRACK_METRICS
 
 	// Process the packet in ct
 	bool report __attribute__((unused));
diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go
index 5a8dd690dd..28106cf08e 100644
--- a/pkg/plugin/packetparser/packetparser_linux.go
+++ b/pkg/plugin/packetparser/packetparser_linux.go
@@ -32,6 +32,7 @@ import (
 	"github.com/microsoft/retina/pkg/log"
 	"github.com/microsoft/retina/pkg/metrics"
 	plugincommon "github.com/microsoft/retina/pkg/plugin/common"
+	"github.com/microsoft/retina/pkg/plugin/conntrack"
 	_ "github.com/microsoft/retina/pkg/plugin/lib/_amd64"                            // nolint
 	_ "github.com/microsoft/retina/pkg/plugin/lib/_arm64"                            // nolint
 	_ "github.com/microsoft/retina/pkg/plugin/lib/common/libbpf/_include/asm"        // nolint
@@ -82,8 +83,20 @@ func (p *packetParser) Generate(ctx context.Context) error {
 		p.l.Info("bypassing lookup IP of interest")
 		bypassLookupIPOfInterest = 1
 	}
+	conntrackMetrics := 0
+	// Check if packetparser has Conntrack metrics enabled.
+	if p.cfg.EnableConntrackMetrics {
+		p.l.Info("conntrack metrics enabled")
+		conntrackMetrics = 1
+		// Generate dynamic header for conntrack.
+		err := conntrack.GenerateDynamic(ctx, conntrackMetrics)
+		if err != nil {
+			return errors.Wrap(err, "failed to generate dynamic header for conntrack")
+		}
+		p.l.Info("Conntrack header generated")
+	}
 	p.l.Info("data aggregation level", zap.String("level", p.cfg.DataAggregationLevel.String()))
-	st := fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n#define DATA_AGGREGATION_LEVEL %d\n", bypassLookupIPOfInterest, p.cfg.DataAggregationLevel)
+	st := fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n#define DATA_AGGREGATION_LEVEL %d\n#define CONNTRACK_METRICS %d\n", bypassLookupIPOfInterest, p.cfg.DataAggregationLevel, conntrackMetrics)
 	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
 	if err != nil {
 		return errors.Wrap(err, "failed to write dynamic header")

From acc3ffd4fbff6f79e198446dec9d000bc5cf4034 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Mon, 9 Dec 2024 16:32:17 +0000
Subject: [PATCH 05/14] feat(ct-metrics): update TestPacketParseGenerate

---
 .../packetparser/packetparser_linux_test.go   | 67 +++++++++++++------
 1 file changed, 45 insertions(+), 22 deletions(-)

diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go
index 1a7a1bc350..47a82f6f38 100644
--- a/pkg/plugin/packetparser/packetparser_linux_test.go
+++ b/pkg/plugin/packetparser/packetparser_linux_test.go
@@ -49,6 +49,9 @@ var (
 		EnablePodLevel:       true,
 		DataAggregationLevel: kcfg.High,
 	}
+	cfgConntrackMetricsEnabled = &kcfg.Config{
+		EnableConntrackMetrics: true,
+	}
 )
 
 func TestCleanAll(t *testing.T) {
@@ -533,30 +536,50 @@ func TestPacketParseGenerate(t *testing.T) {
 	currDir := path.Dir(filename)
 	dynamicHeaderPath := fmt.Sprintf("%s/%s/%s", currDir, bpfSourceDir, dynamicHeaderFileName)
 
-	// Instantiate the packetParser struct with a mocked logger and context.
-	p := &packetParser{
-		cfg: cfgPodLevelEnabled,
-		l:   log.Logger().Named(name),
-	}
-	ctx := context.Background()
-
-	// Call the Generate function and check if it returns an error.
-	if err := p.Generate(ctx); err != nil {
-		t.Fatalf("failed to generate PacketParser header: %v", err)
-	}
-
-	// Verify that the dynamic header file was created in the expected location and contains the expected contents.
-	if _, err := os.Stat(dynamicHeaderPath); os.IsNotExist(err) {
-		t.Fatalf("dynamic header file does not exist: %v", err)
+	tests := []struct {
+		name             string
+		cfg              *kcfg.Config
+		expectedContents string
+	}{
+		{
+			name:             "PodLevelEnabled",
+			cfg:              cfgPodLevelEnabled,
+			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n#define CONNTRACK_METRICS 0\n",
+		},
+		{
+			name:             "ConntrackMetricsEnabled",
+			cfg:              cfgConntrackMetricsEnabled,
+			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 0\n#define CONNTRACK_METRICS 1\n",
+		},
 	}
 
-	expectedContents := "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n"
-	actualContents, err := os.ReadFile(dynamicHeaderPath)
-	if err != nil {
-		t.Fatalf("failed to read dynamic header file: %v", err)
-	}
-	if string(actualContents) != expectedContents {
-		t.Errorf("unexpected dynamic header file contents: got %q, want %q", string(actualContents), expectedContents)
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			// Instantiate the packetParser struct with a mocked logger and context.
+			p := &packetParser{
+				cfg: tt.cfg,
+				l:   log.Logger().Named(name),
+			}
+			ctx := context.Background()
+
+			// Call the Generate function and check if it returns an error.
+			if err := p.Generate(ctx); err != nil {
+				t.Fatalf("failed to generate PacketParser header: %v", err)
+			}
+
+			// Verify that the dynamic header file was created in the expected location and contains the expected contents.
+			if _, err := os.Stat(dynamicHeaderPath); os.IsNotExist(err) {
+				t.Fatalf("dynamic header file does not exist: %v", err)
+			}
+
+			actualContents, err := os.ReadFile(dynamicHeaderPath)
+			if err != nil {
+				t.Fatalf("failed to read dynamic header file: %v", err)
+			}
+			if string(actualContents) != tt.expectedContents {
+				t.Errorf("unexpected dynamic header file contents: got %q, want %q", string(actualContents), tt.expectedContents)
+			}
+		})
 	}
 }
 

From ed2706cfe2c8a0368210984ec8c3b6d7f8f0d703 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Tue, 10 Dec 2024 15:41:00 +0000
Subject: [PATCH 06/14] feat(ct-metrics): remove traffic_direction from
 conntrackmetadata

---
 pkg/plugin/conntrack/_cprog/conntrack.c          |   9 ---------
 pkg/plugin/conntrack/conntrack_bpfel_x86.go      |   2 --
 .../packetforward/packetforward_bpfel_x86.o      | Bin 4504 -> 0 bytes
 .../packetparser/packetparser_bpfel_x86.go       |   4 ----
 4 files changed, 15 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index 7e24d2fa3a..5c4f3b15db 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -29,11 +29,6 @@ struct conntrackmetadata {
     */
     __u64 packets_forward_count;
     __u64 packets_reply_count;
-    /*
-        This is the inital direction of the connection.
-        It is set to egress if the connection is initiated from the host and ingress otherwise.
-    */
-    __u8 traffic_direction;
 };
 
 struct packet
@@ -153,10 +148,6 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     #if CONNTRACK_METRICS == 1
         new_value.conntrack_metadata.packets_forward_count = 1;
         new_value.conntrack_metadata.bytes_forward_count = p->bytes;
-        // The initial SYN is captured. Set the traffic direction of the connection.
-        // This is important for the case where the SYN packet is not captured
-        // and the connection is created with unknown direction.
-        new_value.conntrack_metadata.traffic_direction = new_value.traffic_direction;
         // Update initial conntrack metadata for the connection.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
     #endif
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
index a3a3a07951..964ea4179e 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
@@ -25,8 +25,6 @@ type conntrackCtEntry struct {
 		BytesReplyCount     uint64
 		PacketsForwardCount uint64
 		PacketsReplyCount   uint64
-		TrafficDirection    uint8
-		_                   [7]byte
 	}
 }
 
diff --git a/pkg/plugin/packetforward/packetforward_bpfel_x86.o b/pkg/plugin/packetforward/packetforward_bpfel_x86.o
index 5f175500269f66b9fa5956441e65ccf97025395a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001

literal 4504
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
EKhp6_`2YX_

diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
index 440a4ccc59..8843327040 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
@@ -25,8 +25,6 @@ type packetparserCtEntry struct {
 		BytesReplyCount     uint64
 		PacketsForwardCount uint64
 		PacketsReplyCount   uint64
-		TrafficDirection    uint8
-		_                   [7]byte
 	}
 }
 
@@ -68,8 +66,6 @@ type packetparserPacket struct {
 		BytesReplyCount     uint64
 		PacketsForwardCount uint64
 		PacketsReplyCount   uint64
-		TrafficDirection    uint8
-		_                   [7]byte
 	}
 }
 

From 14f219c67ad4894630299f1ad0b2acb1fb9cf23a Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Wed, 11 Dec 2024 09:11:35 +0000
Subject: [PATCH 07/14] feat(ct-metrics): simplify preprocessor for
 CONNTRACK_METRICS

---
 pkg/plugin/conntrack/_cprog/conntrack.c | 14 --------------
 pkg/plugin/conntrack/_cprog/dynamic.h   |  3 ++-
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index 5c4f3b15db..01ed2d223c 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -145,12 +145,10 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
 
     #ifdef CONNTRACK_METRICS
-    #if CONNTRACK_METRICS == 1
         new_value.conntrack_metadata.packets_forward_count = 1;
         new_value.conntrack_metadata.bytes_forward_count = p->bytes;
         // Update initial conntrack metadata for the connection.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
-    #endif
     #endif // CONNTRACK_METRICS
 
     // Update packet
@@ -179,12 +177,10 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     new_value.last_report_tx_dir = now;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
     #ifdef CONNTRACK_METRICS
-    #if CONNTRACK_METRICS == 1
         new_value.conntrack_metadata.packets_forward_count = 1;
         new_value.conntrack_metadata.bytes_forward_count = p->bytes;
         // Update packet's conntrack metadata.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
-    #endif
     #endif // CONNTRACK_METRICS    
 
     // Update packet
@@ -230,10 +226,8 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         new_value.flags_seen_rx_dir = p->flags;
         new_value.last_report_rx_dir = now;
         #ifdef CONNTRACK_METRICS
-        #if CONNTRACK_METRICS == 1
             new_value.conntrack_metadata.bytes_reply_count = p->bytes;
             new_value.conntrack_metadata.packets_reply_count = 1;
-        #endif
         #endif // CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
     } else { // Otherwise, the packet is considered as a packet in the send direction.
@@ -241,18 +235,14 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         new_value.flags_seen_tx_dir = p->flags;
         new_value.last_report_tx_dir = now;
         #ifdef CONNTRACK_METRICS
-        #if CONNTRACK_METRICS == 1
             new_value.conntrack_metadata.bytes_forward_count = p->bytes;
             new_value.conntrack_metadata.packets_forward_count = 1;
-        #endif
         #endif // CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
     #ifdef CONNTRACK_METRICS
-    #if CONNTRACK_METRICS == 1
         // Update packet's conntrack metadata.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
-    #endif
     #endif // CONNTRACK_METRICS
     return true;
 }
@@ -373,13 +363,11 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         p->is_reply = false;
         p->traffic_direction = entry->traffic_direction;
         #ifdef CONNTRACK_METRICS
-        #if CONNTRACK_METRICS == 1
             // Update packet count and bytes count on conntrack entry.
             WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
             WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
             // Update packet's conntract metadata.
             __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
-        #endif
         #endif // CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
@@ -397,13 +385,11 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         p->is_reply = true;
         p->traffic_direction = entry->traffic_direction;
         #ifdef CONNTRACK_METRICS
-        #if CONNTRACK_METRICS == 1
             // Update packet count and bytes count on conntrack entry.
             WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
             WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
             // Update packet's conntract metadata.
             __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
-        #endif
         #endif // CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
diff --git a/pkg/plugin/conntrack/_cprog/dynamic.h b/pkg/plugin/conntrack/_cprog/dynamic.h
index 965f8f2bea..80abbd931f 100644
--- a/pkg/plugin/conntrack/_cprog/dynamic.h
+++ b/pkg/plugin/conntrack/_cprog/dynamic.h
@@ -1 +1,2 @@
-#define CONNTRACK_METRICS 0
\ No newline at end of file
+// Place holder header file that will be replaced by the actual header file during runtime
+// DO NOT DELETE

From c20e4acb577a18b086a3700b9d745ddd3de36207 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Wed, 11 Dec 2024 11:12:21 +0000
Subject: [PATCH 08/14] feat(ct-metrics): add generated arm64 bpf go wrappers

---
 pkg/plugin/conntrack/conntrack_bpfel_arm64.go |  6 +++++
 .../packetparser/packetparser_bpfel_arm64.go  | 24 ++++++++++++++-----
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
index b96504c3e0..94ff4f8b3f 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
@@ -20,6 +20,12 @@ type conntrackCtEntry struct {
 	FlagsSeenTxDir     uint8
 	FlagsSeenRxDir     uint8
 	IsDirectionUnknown bool
+	ConntrackMetadata  struct {
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+	}
 }
 
 type conntrackCtV4Key struct {
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
index 30c6bb43d3..15b5d3e23c 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
@@ -20,6 +20,12 @@ type packetparserCtEntry struct {
 	FlagsSeenTxDir     uint8
 	FlagsSeenRxDir     uint8
 	IsDirectionUnknown bool
+	ConntrackMetadata  struct {
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+	}
 }
 
 type packetparserCtV4Key struct {
@@ -49,12 +55,18 @@ type packetparserPacket struct {
 		Tsval  uint32
 		Tsecr  uint32
 	}
-	ObservationPoint uint8
-	TrafficDirection uint8
-	Proto            uint8
-	Flags            uint8
-	IsReply          bool
-	_                [3]byte
+	ObservationPoint  uint8
+	TrafficDirection  uint8
+	Proto             uint8
+	Flags             uint8
+	IsReply           bool
+	_                 [3]byte
+	ConntrackMetadata struct {
+		BytesForwardCount   uint64
+		BytesReplyCount     uint64
+		PacketsForwardCount uint64
+		PacketsReplyCount   uint64
+	}
 }
 
 // loadPacketparser returns the embedded CollectionSpec for packetparser.

From dc27a722cf6e1cd8d38963d1192f5a9c17afe4af Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Wed, 11 Dec 2024 11:44:55 +0000
Subject: [PATCH 09/14] feat(ct-metrics): use uint32 for packet counters

---
 pkg/plugin/conntrack/_cprog/conntrack.c             | 4 ++--
 pkg/plugin/conntrack/conntrack_bpfel_arm64.go       | 4 ++--
 pkg/plugin/conntrack/conntrack_bpfel_x86.go         | 4 ++--
 pkg/plugin/packetparser/packetparser_bpfel_arm64.go | 8 ++++----
 pkg/plugin/packetparser/packetparser_bpfel_x86.go   | 8 ++++----
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index 01ed2d223c..040fa35394 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -27,8 +27,8 @@ struct conntrackmetadata {
         packets_*_count indicates the number of packets sent and received in the forward and reply direction.
         These values will be based on the conntrack entry.
     */
-    __u64 packets_forward_count;
-    __u64 packets_reply_count;
+    __u32 packets_forward_count;
+    __u32 packets_reply_count;
 };
 
 struct packet
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
index 94ff4f8b3f..efb93738a6 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_arm64.go
@@ -23,8 +23,8 @@ type conntrackCtEntry struct {
 	ConntrackMetadata  struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 
diff --git a/pkg/plugin/conntrack/conntrack_bpfel_x86.go b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
index 964ea4179e..baa46bcbfa 100644
--- a/pkg/plugin/conntrack/conntrack_bpfel_x86.go
+++ b/pkg/plugin/conntrack/conntrack_bpfel_x86.go
@@ -23,8 +23,8 @@ type conntrackCtEntry struct {
 	ConntrackMetadata  struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
index 15b5d3e23c..ebfa05e37f 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_arm64.go
@@ -23,8 +23,8 @@ type packetparserCtEntry struct {
 	ConntrackMetadata  struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 
@@ -64,8 +64,8 @@ type packetparserPacket struct {
 	ConntrackMetadata struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 
diff --git a/pkg/plugin/packetparser/packetparser_bpfel_x86.go b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
index 8843327040..36de41247b 100644
--- a/pkg/plugin/packetparser/packetparser_bpfel_x86.go
+++ b/pkg/plugin/packetparser/packetparser_bpfel_x86.go
@@ -23,8 +23,8 @@ type packetparserCtEntry struct {
 	ConntrackMetadata  struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 
@@ -64,8 +64,8 @@ type packetparserPacket struct {
 	ConntrackMetadata struct {
 		BytesForwardCount   uint64
 		BytesReplyCount     uint64
-		PacketsForwardCount uint64
-		PacketsReplyCount   uint64
+		PacketsForwardCount uint32
+		PacketsReplyCount   uint32
 	}
 }
 

From 004663aa14d5fd9ad6e94ef851b2009d9e450091 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 13 Dec 2024 09:04:45 +0000
Subject: [PATCH 10/14] feat(ct-metrics): add unit test for conntrack
 GenerateDynamic

---
 pkg/plugin/conntrack/conntrack_linux.go       | 15 ++-
 pkg/plugin/conntrack/conntrack_linux_test.go  | 92 +++++++++++++++++++
 pkg/plugin/packetparser/packetparser_linux.go |  3 +-
 3 files changed, 104 insertions(+), 6 deletions(-)
 create mode 100644 pkg/plugin/conntrack/conntrack_linux_test.go

diff --git a/pkg/plugin/conntrack/conntrack_linux.go b/pkg/plugin/conntrack/conntrack_linux.go
index 2ed6db731b..ab7496b880 100644
--- a/pkg/plugin/conntrack/conntrack_linux.go
+++ b/pkg/plugin/conntrack/conntrack_linux.go
@@ -70,15 +70,20 @@ func New() (*Conntrack, error) {
 	return ct, nil
 }
 
-// Generate dynamic header file for conntrack eBPF program.
-func GenerateDynamic(ctx context.Context, conntrackMetrics int) error {
+// Build dynamic header path
+func BuildDynamicHeaderPath() string {
 	// Get absolute path to this file during runtime.
 	_, filename, _, ok := runtime.Caller(0)
 	if !ok {
-		return errors.New("unable to get absolute path for conntrack file")
+		return ""
 	}
-	dir := path.Dir(filename)
-	dynamicHeaderPath := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName)
+	currDir := path.Dir(filename)
+	return fmt.Sprintf("%s/%s/%s", currDir, bpfSourceDir, dynamicHeaderFileName)
+}
+
+// Generate dynamic header file for conntrack eBPF program.
+func GenerateDynamic(ctx context.Context, dynamicHeaderPath string, conntrackMetrics int) error {
+
 	st := fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
 	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
 	if err != nil {
diff --git a/pkg/plugin/conntrack/conntrack_linux_test.go b/pkg/plugin/conntrack/conntrack_linux_test.go
new file mode 100644
index 0000000000..1e16c1c316
--- /dev/null
+++ b/pkg/plugin/conntrack/conntrack_linux_test.go
@@ -0,0 +1,92 @@
+package conntrack
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"path"
+	"runtime"
+	"testing"
+)
+
+func TestBuildDynamicHeaderPath(t *testing.T) {
+	tests := []struct {
+		name         string
+		expectedPath string
+	}{
+		{
+			name:         "ExpectedPath",
+			expectedPath: fmt.Sprintf("%s/%s/%s", path.Dir(getCurrentFilePath(t)), bpfSourceDir, dynamicHeaderFileName),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			actualPath := BuildDynamicHeaderPath()
+			if actualPath != tt.expectedPath {
+				t.Errorf("unexpected dynamic header path: got %q, want %q", actualPath, tt.expectedPath)
+			}
+		})
+	}
+}
+
+func TestGenerateDynamic(t *testing.T) {
+	tests := []struct {
+		name             string
+		conntrackMetrics int
+		expectedContents string
+	}{
+		{
+			name:             "ConntrackMetricsEnabled",
+			conntrackMetrics: 1,
+			expectedContents: "#define CONNTRACK_METRICS 1\n",
+		},
+		{
+			name:             "ConntrackMetricsDisabled",
+			conntrackMetrics: 0,
+			expectedContents: "#define CONNTRACK_METRICS 0\n",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			// Create a temporary directory
+			tempDir, err := os.MkdirTemp("", "conntrack_test")
+			if err != nil {
+				t.Fatalf("failed to create temp directory: %v", err)
+			}
+			// Clean up the temporary directory after the test completes
+			defer os.RemoveAll(tempDir)
+
+			// Override the dynamicHeaderPath to use the temporary directory
+			dynamicHeaderPath := path.Join(tempDir, dynamicHeaderFileName)
+
+			// Call the GenerateDynamic function and check if it returns an error.
+			ctx := context.Background()
+			if err := GenerateDynamic(ctx, dynamicHeaderPath, tt.conntrackMetrics); err != nil {
+				t.Fatalf("failed to generate dynamic header: %v", err)
+			}
+
+			// Verify that the dynamic header file was created in the expected location and contains the expected contents.
+			if _, err := os.Stat(dynamicHeaderPath); os.IsNotExist(err) {
+				t.Fatalf("dynamic header file does not exist: %v", err)
+			}
+
+			actualContents, err := os.ReadFile(dynamicHeaderPath)
+			if err != nil {
+				t.Fatalf("failed to read dynamic header file: %v", err)
+			}
+			if string(actualContents) != tt.expectedContents {
+				t.Errorf("unexpected dynamic header file contents: got %q, want %q", string(actualContents), tt.expectedContents)
+			}
+		})
+	}
+}
+
+func getCurrentFilePath(t *testing.T) string {
+	_, filename, _, ok := runtime.Caller(1)
+	if !ok {
+		t.Fatal("failed to determine test file path")
+	}
+	return filename
+}
diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go
index 28106cf08e..dd4bc46567 100644
--- a/pkg/plugin/packetparser/packetparser_linux.go
+++ b/pkg/plugin/packetparser/packetparser_linux.go
@@ -89,7 +89,8 @@ func (p *packetParser) Generate(ctx context.Context) error {
 		p.l.Info("conntrack metrics enabled")
 		conntrackMetrics = 1
 		// Generate dynamic header for conntrack.
-		err := conntrack.GenerateDynamic(ctx, conntrackMetrics)
+		dynamicHeaderPath := conntrack.BuildDynamicHeaderPath()
+		err := conntrack.GenerateDynamic(ctx, dynamicHeaderPath, conntrackMetrics)
 		if err != nil {
 			return errors.Wrap(err, "failed to generate dynamic header for conntrack")
 		}

From 414ec4faa9425360cc9b892931869db32fa46838 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 13 Dec 2024 09:43:01 +0000
Subject: [PATCH 11/14] feat(ct-metrics): refactor packetparser Generate and
 update tests

---
 pkg/plugin/packetparser/_cprog/dynamic.h      |  1 -
 pkg/plugin/packetparser/_cprog/packetparser.c |  2 --
 pkg/plugin/packetparser/packetparser_linux.go | 33 +++++++++++++++----
 .../packetparser/packetparser_linux_test.go   | 20 +++++++++--
 4 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/pkg/plugin/packetparser/_cprog/dynamic.h b/pkg/plugin/packetparser/_cprog/dynamic.h
index ac14b29aab..ecadc42211 100644
--- a/pkg/plugin/packetparser/_cprog/dynamic.h
+++ b/pkg/plugin/packetparser/_cprog/dynamic.h
@@ -1,3 +1,2 @@
 #define BYPASS_LOOKUP_IP_OF_INTEREST 0
 #define DATA_AGGREGATION_LEVEL 0
-#define CONNTRACK_METRICS 0
diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c
index 3603d83a73..417de742d9 100644
--- a/pkg/plugin/packetparser/_cprog/packetparser.c
+++ b/pkg/plugin/packetparser/_cprog/packetparser.c
@@ -202,12 +202,10 @@ static void parse(struct __sk_buff *skb, __u8 obs)
 	}
 
 	#ifdef CONNTRACK_METRICS
-	#if CONNTRACK_METRICS == 1
 		// Initialize conntrack metadata in packet struct.
 		struct conntrackmetadata conntrack_metadata;
 		__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
 		p.conntrack_metadata = conntrack_metadata;
-	#endif
 	#endif // CONNTRACK_METRICS
 
 	// Process the packet in ct
diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go
index dd4bc46567..3194ef9785 100644
--- a/pkg/plugin/packetparser/packetparser_linux.go
+++ b/pkg/plugin/packetparser/packetparser_linux.go
@@ -69,36 +69,57 @@ func (p *packetParser) Name() string {
 	return name
 }
 
-func (p *packetParser) Generate(ctx context.Context) error {
+func generateDynamicHeaderPath() (string, error) {
+
 	// Get absolute path to this file during runtime.
 	_, filename, _, ok := runtime.Caller(0)
 	if !ok {
-		return errors.New("unable to get absolute path to this file")
+		return "", errors.New("unable to get absolute path to this file")
 	}
 	dir := path.Dir(filename)
-	dynamicHeaderPath := fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName)
+	return fmt.Sprintf("%s/%s/%s", dir, bpfSourceDir, dynamicHeaderFileName), nil
+}
+
+func (p *packetParser) Generate(ctx context.Context) error {
+	// Variable to store content of dynamic header.
+	var st string
+
+	dynamicHeaderPath, err := generateDynamicHeaderPath()
+	if err != nil {
+		return err
+	}
+
 	// Check if packetparser will bypassing lookup IP of interest.
 	bypassLookupIPOfInterest := 0
 	if p.cfg.BypassLookupIPOfInterest {
 		p.l.Info("bypassing lookup IP of interest")
 		bypassLookupIPOfInterest = 1
+		st = fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n", bypassLookupIPOfInterest)
 	}
+
 	conntrackMetrics := 0
 	// Check if packetparser has Conntrack metrics enabled.
 	if p.cfg.EnableConntrackMetrics {
 		p.l.Info("conntrack metrics enabled")
 		conntrackMetrics = 1
+
 		// Generate dynamic header for conntrack.
 		dynamicHeaderPath := conntrack.BuildDynamicHeaderPath()
 		err := conntrack.GenerateDynamic(ctx, dynamicHeaderPath, conntrackMetrics)
 		if err != nil {
 			return errors.Wrap(err, "failed to generate dynamic header for conntrack")
 		}
-		p.l.Info("Conntrack header generated")
+
+		// Process packetparser dynamic.h conntrack metrics definition.
+		st += fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
 	}
+
+	// Process packetparser data aggregation level.
 	p.l.Info("data aggregation level", zap.String("level", p.cfg.DataAggregationLevel.String()))
-	st := fmt.Sprintf("#define BYPASS_LOOKUP_IP_OF_INTEREST %d\n#define DATA_AGGREGATION_LEVEL %d\n#define CONNTRACK_METRICS %d\n", bypassLookupIPOfInterest, p.cfg.DataAggregationLevel, conntrackMetrics)
-	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
+	st += fmt.Sprintf("#define DATA_AGGREGATION_LEVEL %d\n", p.cfg.DataAggregationLevel)
+
+	// Generate dynamic header for packetparser.
+	err = loader.WriteFile(ctx, dynamicHeaderPath, st)
 	if err != nil {
 		return errors.Wrap(err, "failed to write dynamic header")
 	}
diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go
index 47a82f6f38..3f36b6c2f5 100644
--- a/pkg/plugin/packetparser/packetparser_linux_test.go
+++ b/pkg/plugin/packetparser/packetparser_linux_test.go
@@ -37,6 +37,7 @@ var (
 	cfgPodLevelEnabled = &kcfg.Config{
 		EnablePodLevel:           true,
 		BypassLookupIPOfInterest: true,
+		EnableConntrackMetrics:   false,
 	}
 	cfgPodLevelDisabled = &kcfg.Config{
 		EnablePodLevel: false,
@@ -50,7 +51,10 @@ var (
 		DataAggregationLevel: kcfg.High,
 	}
 	cfgConntrackMetricsEnabled = &kcfg.Config{
-		EnableConntrackMetrics: true,
+		EnablePodLevel:           true,
+		DataAggregationLevel:     kcfg.High,
+		BypassLookupIPOfInterest: true,
+		EnableConntrackMetrics:   true,
 	}
 )
 
@@ -544,12 +548,22 @@ func TestPacketParseGenerate(t *testing.T) {
 		{
 			name:             "PodLevelEnabled",
 			cfg:              cfgPodLevelEnabled,
-			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n#define CONNTRACK_METRICS 0\n",
+			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define DATA_AGGREGATION_LEVEL 0\n",
 		},
 		{
 			name:             "ConntrackMetricsEnabled",
 			cfg:              cfgConntrackMetricsEnabled,
-			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 0\n#define DATA_AGGREGATION_LEVEL 0\n#define CONNTRACK_METRICS 1\n",
+			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n",
+		},
+		{
+			name:             "DataAggregationLevelLow",
+			cfg:              cfgDataAggregationLevelLow,
+			expectedContents: "#define DATA_AGGREGATION_LEVEL 0\n",
+		},
+		{
+			name:             "DataAggregationLevelHigh",
+			cfg:              cfgDataAggregationLevelHigh,
+			expectedContents: "#define DATA_AGGREGATION_LEVEL 1\n",
 		},
 	}
 

From d5b9fd5f4f910fb33107779c9fd0107b76bc523c Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 13 Dec 2024 09:55:24 +0000
Subject: [PATCH 12/14] feat(ct-metrics): rename C constant to
 ENABLE_CONNTRACK_METRICS

---
 pkg/plugin/conntrack/_cprog/conntrack.c       | 28 +++++++++----------
 pkg/plugin/conntrack/conntrack_linux.go       |  2 +-
 pkg/plugin/conntrack/conntrack_linux_test.go  |  4 +--
 pkg/plugin/packetparser/_cprog/packetparser.c |  4 +--
 pkg/plugin/packetparser/packetparser_linux.go |  2 +-
 .../packetparser/packetparser_linux_test.go   |  2 +-
 6 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/pkg/plugin/conntrack/_cprog/conntrack.c b/pkg/plugin/conntrack/_cprog/conntrack.c
index 040fa35394..9d415a1eb5 100644
--- a/pkg/plugin/conntrack/_cprog/conntrack.c
+++ b/pkg/plugin/conntrack/_cprog/conntrack.c
@@ -144,12 +144,12 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
     new_value.is_direction_unknown = false;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
 
-    #ifdef CONNTRACK_METRICS
+    #ifdef ENABLE_CONNTRACK_METRICS
         new_value.conntrack_metadata.packets_forward_count = 1;
         new_value.conntrack_metadata.bytes_forward_count = p->bytes;
         // Update initial conntrack metadata for the connection.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
-    #endif // CONNTRACK_METRICS
+    #endif // ENABLE_CONNTRACK_METRICS
 
     // Update packet
     p->is_reply = false;
@@ -176,12 +176,12 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
     new_value.flags_seen_tx_dir = p->flags;
     new_value.last_report_tx_dir = now;
     new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
-    #ifdef CONNTRACK_METRICS
+    #ifdef ENABLE_CONNTRACK_METRICS
         new_value.conntrack_metadata.packets_forward_count = 1;
         new_value.conntrack_metadata.bytes_forward_count = p->bytes;
         // Update packet's conntrack metadata.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));;
-    #endif // CONNTRACK_METRICS    
+    #endif // ENABLE_CONNTRACK_METRICS    
 
     // Update packet
     p->is_reply = false;
@@ -225,25 +225,25 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
         p->is_reply = true;
         new_value.flags_seen_rx_dir = p->flags;
         new_value.last_report_rx_dir = now;
-        #ifdef CONNTRACK_METRICS
+        #ifdef ENABLE_CONNTRACK_METRICS
             new_value.conntrack_metadata.bytes_reply_count = p->bytes;
             new_value.conntrack_metadata.packets_reply_count = 1;
-        #endif // CONNTRACK_METRICS
+        #endif // ENABLE_CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &reverse_key, &new_value, BPF_ANY);
     } else { // Otherwise, the packet is considered as a packet in the send direction.
         p->is_reply = false;
         new_value.flags_seen_tx_dir = p->flags;
         new_value.last_report_tx_dir = now;
-        #ifdef CONNTRACK_METRICS
+        #ifdef ENABLE_CONNTRACK_METRICS
             new_value.conntrack_metadata.bytes_forward_count = p->bytes;
             new_value.conntrack_metadata.packets_forward_count = 1;
-        #endif // CONNTRACK_METRICS
+        #endif // ENABLE_CONNTRACK_METRICS
         bpf_map_update_elem(&retina_conntrack, &key, &new_value, BPF_ANY);
     }
-    #ifdef CONNTRACK_METRICS
+    #ifdef ENABLE_CONNTRACK_METRICS
         // Update packet's conntrack metadata.
         __builtin_memcpy(&p->conntrack_metadata, &new_value.conntrack_metadata, sizeof(struct conntrackmetadata));
-    #endif // CONNTRACK_METRICS
+    #endif // ENABLE_CONNTRACK_METRICS
     return true;
 }
 
@@ -362,13 +362,13 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = false;
         p->traffic_direction = entry->traffic_direction;
-        #ifdef CONNTRACK_METRICS
+        #ifdef ENABLE_CONNTRACK_METRICS
             // Update packet count and bytes count on conntrack entry.
             WRITE_ONCE(entry->conntrack_metadata.packets_forward_count, READ_ONCE(entry->conntrack_metadata.packets_forward_count) + 1);
             WRITE_ONCE(entry->conntrack_metadata.bytes_forward_count, READ_ONCE(entry->conntrack_metadata.bytes_forward_count) + p->bytes);
             // Update packet's conntract metadata.
             __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
-        #endif // CONNTRACK_METRICS
+        #endif // ENABLE_CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
     }
     
@@ -384,13 +384,13 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
         // Update the packet accordingly.
         p->is_reply = true;
         p->traffic_direction = entry->traffic_direction;
-        #ifdef CONNTRACK_METRICS
+        #ifdef ENABLE_CONNTRACK_METRICS
             // Update packet count and bytes count on conntrack entry.
             WRITE_ONCE(entry->conntrack_metadata.packets_reply_count, READ_ONCE(entry->conntrack_metadata.packets_reply_count) + 1);
             WRITE_ONCE(entry->conntrack_metadata.bytes_reply_count, READ_ONCE(entry->conntrack_metadata.bytes_reply_count) + p->bytes);
             // Update packet's conntract metadata.
             __builtin_memcpy(&p->conntrack_metadata, &entry->conntrack_metadata, sizeof(struct conntrackmetadata));
-        #endif // CONNTRACK_METRICS
+        #endif // ENABLE_CONNTRACK_METRICS
         return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &reverse_key);
     }
 
diff --git a/pkg/plugin/conntrack/conntrack_linux.go b/pkg/plugin/conntrack/conntrack_linux.go
index ab7496b880..3dae5c325d 100644
--- a/pkg/plugin/conntrack/conntrack_linux.go
+++ b/pkg/plugin/conntrack/conntrack_linux.go
@@ -84,7 +84,7 @@ func BuildDynamicHeaderPath() string {
 // Generate dynamic header file for conntrack eBPF program.
 func GenerateDynamic(ctx context.Context, dynamicHeaderPath string, conntrackMetrics int) error {
 
-	st := fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
+	st := fmt.Sprintf("#define ENABLE_CONNTRACK_METRICS %d\n", conntrackMetrics)
 	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
 	if err != nil {
 		return errors.Wrap(err, "failed to write conntrack dynamic header")
diff --git a/pkg/plugin/conntrack/conntrack_linux_test.go b/pkg/plugin/conntrack/conntrack_linux_test.go
index 1e16c1c316..5154377426 100644
--- a/pkg/plugin/conntrack/conntrack_linux_test.go
+++ b/pkg/plugin/conntrack/conntrack_linux_test.go
@@ -39,12 +39,12 @@ func TestGenerateDynamic(t *testing.T) {
 		{
 			name:             "ConntrackMetricsEnabled",
 			conntrackMetrics: 1,
-			expectedContents: "#define CONNTRACK_METRICS 1\n",
+			expectedContents: "#define ENABLE_CONNTRACK_METRICS 1\n",
 		},
 		{
 			name:             "ConntrackMetricsDisabled",
 			conntrackMetrics: 0,
-			expectedContents: "#define CONNTRACK_METRICS 0\n",
+			expectedContents: "#define ENABLE_CONNTRACK_METRICS 0\n",
 		},
 	}
 
diff --git a/pkg/plugin/packetparser/_cprog/packetparser.c b/pkg/plugin/packetparser/_cprog/packetparser.c
index 417de742d9..40ec8fb03e 100644
--- a/pkg/plugin/packetparser/_cprog/packetparser.c
+++ b/pkg/plugin/packetparser/_cprog/packetparser.c
@@ -201,12 +201,12 @@ static void parse(struct __sk_buff *skb, __u8 obs)
 		return;
 	}
 
-	#ifdef CONNTRACK_METRICS
+	#ifdef ENABLE_CONNTRACK_METRICS
 		// Initialize conntrack metadata in packet struct.
 		struct conntrackmetadata conntrack_metadata;
 		__builtin_memset(&conntrack_metadata, 0, sizeof(conntrack_metadata));
 		p.conntrack_metadata = conntrack_metadata;
-	#endif // CONNTRACK_METRICS
+	#endif // ENABLE_CONNTRACK_METRICS
 
 	// Process the packet in ct
 	bool report __attribute__((unused));
diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go
index 3194ef9785..cf570de7fd 100644
--- a/pkg/plugin/packetparser/packetparser_linux.go
+++ b/pkg/plugin/packetparser/packetparser_linux.go
@@ -111,7 +111,7 @@ func (p *packetParser) Generate(ctx context.Context) error {
 		}
 
 		// Process packetparser dynamic.h conntrack metrics definition.
-		st += fmt.Sprintf("#define CONNTRACK_METRICS %d\n", conntrackMetrics)
+		st += fmt.Sprintf("#define ENABLE_CONNTRACK_METRICS %d\n", conntrackMetrics)
 	}
 
 	// Process packetparser data aggregation level.
diff --git a/pkg/plugin/packetparser/packetparser_linux_test.go b/pkg/plugin/packetparser/packetparser_linux_test.go
index 3f36b6c2f5..aa27cfa356 100644
--- a/pkg/plugin/packetparser/packetparser_linux_test.go
+++ b/pkg/plugin/packetparser/packetparser_linux_test.go
@@ -553,7 +553,7 @@ func TestPacketParseGenerate(t *testing.T) {
 		{
 			name:             "ConntrackMetricsEnabled",
 			cfg:              cfgConntrackMetricsEnabled,
-			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n",
+			expectedContents: "#define BYPASS_LOOKUP_IP_OF_INTEREST 1\n#define ENABLE_CONNTRACK_METRICS 1\n#define DATA_AGGREGATION_LEVEL 1\n",
 		},
 		{
 			name:             "DataAggregationLevelLow",

From 4d40b6c767f8b5dd9402dfa53c7d3c68ac446c08 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 13 Dec 2024 10:54:12 +0000
Subject: [PATCH 13/14] feat(ct-metrics): fix linting

---
 pkg/plugin/conntrack/conntrack_linux.go       | 1 -
 pkg/plugin/conntrack/conntrack_linux_test.go  | 4 ++--
 pkg/plugin/packetparser/packetparser_linux.go | 5 ++---
 3 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/pkg/plugin/conntrack/conntrack_linux.go b/pkg/plugin/conntrack/conntrack_linux.go
index 3dae5c325d..dc2fb0c449 100644
--- a/pkg/plugin/conntrack/conntrack_linux.go
+++ b/pkg/plugin/conntrack/conntrack_linux.go
@@ -83,7 +83,6 @@ func BuildDynamicHeaderPath() string {
 
 // Generate dynamic header file for conntrack eBPF program.
 func GenerateDynamic(ctx context.Context, dynamicHeaderPath string, conntrackMetrics int) error {
-
 	st := fmt.Sprintf("#define ENABLE_CONNTRACK_METRICS %d\n", conntrackMetrics)
 	err := loader.WriteFile(ctx, dynamicHeaderPath, st)
 	if err != nil {
diff --git a/pkg/plugin/conntrack/conntrack_linux_test.go b/pkg/plugin/conntrack/conntrack_linux_test.go
index 5154377426..971ddaead5 100644
--- a/pkg/plugin/conntrack/conntrack_linux_test.go
+++ b/pkg/plugin/conntrack/conntrack_linux_test.go
@@ -63,12 +63,12 @@ func TestGenerateDynamic(t *testing.T) {
 
 			// Call the GenerateDynamic function and check if it returns an error.
 			ctx := context.Background()
-			if err := GenerateDynamic(ctx, dynamicHeaderPath, tt.conntrackMetrics); err != nil {
+			if err = GenerateDynamic(ctx, dynamicHeaderPath, tt.conntrackMetrics); err != nil {
 				t.Fatalf("failed to generate dynamic header: %v", err)
 			}
 
 			// Verify that the dynamic header file was created in the expected location and contains the expected contents.
-			if _, err := os.Stat(dynamicHeaderPath); os.IsNotExist(err) {
+			if _, err = os.Stat(dynamicHeaderPath); os.IsNotExist(err) {
 				t.Fatalf("dynamic header file does not exist: %v", err)
 			}
 
diff --git a/pkg/plugin/packetparser/packetparser_linux.go b/pkg/plugin/packetparser/packetparser_linux.go
index cf570de7fd..fb54c8bb5e 100644
--- a/pkg/plugin/packetparser/packetparser_linux.go
+++ b/pkg/plugin/packetparser/packetparser_linux.go
@@ -70,7 +70,6 @@ func (p *packetParser) Name() string {
 }
 
 func generateDynamicHeaderPath() (string, error) {
-
 	// Get absolute path to this file during runtime.
 	_, filename, _, ok := runtime.Caller(0)
 	if !ok {
@@ -104,8 +103,8 @@ func (p *packetParser) Generate(ctx context.Context) error {
 		conntrackMetrics = 1
 
 		// Generate dynamic header for conntrack.
-		dynamicHeaderPath := conntrack.BuildDynamicHeaderPath()
-		err := conntrack.GenerateDynamic(ctx, dynamicHeaderPath, conntrackMetrics)
+		ctDynamicHeaderPath := conntrack.BuildDynamicHeaderPath()
+		err = conntrack.GenerateDynamic(ctx, ctDynamicHeaderPath, conntrackMetrics)
 		if err != nil {
 			return errors.Wrap(err, "failed to generate dynamic header for conntrack")
 		}

From 9eec75ca9cf70bf058e5db63f14903f3727f5f83 Mon Sep 17 00:00:00 2001
From: Simone Rodigari <srodigari@microsoft.com>
Date: Fri, 13 Dec 2024 15:31:52 +0000
Subject: [PATCH 14/14] feat(ct-metrics): revert files accidentally committed

---
 pkg/plugin/dropreason/kprobe_bpfel_x86.o | Bin 24384 -> 0 bytes
 pkg/plugin/filter/filter_bpfel_x86.o     | Bin 2144 -> 0 bytes
 pkg/plugin/mock/plugin.go                |  29 ++++++++++++-----------
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/pkg/plugin/dropreason/kprobe_bpfel_x86.o b/pkg/plugin/dropreason/kprobe_bpfel_x86.o
index a0098ede38482561f4961ac10fc98c79ff9e3792..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001

literal 24384
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

diff --git a/pkg/plugin/filter/filter_bpfel_x86.o b/pkg/plugin/filter/filter_bpfel_x86.o
index bf6c879c816f34c58c39471bdebc664f91e53879..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
GIT binary patch
literal 0
HcmV?d00001

literal 2144
zcmbtVJ8KkC6h6C&W;I4lREUwtfFM!ACL{>45H<^mh$-T$(89@NcQzR^nH^?lL*fI2
zAXwUnji6X*Wf{9ziG@GFA7CL^T4*7x-*@NU$?g~s@gv_ok9*F!=RS7wU}kPMpUa6s
zPJYOaWxOIU_w48;rIw@@k(HreEt*?MvLGu%Kb5`xie8bPyvWa1t2LM@`UrD$ZEOFQ
zwr}WOXcJEp@z3LnZ#fy%S?{n0c}lMZcfJdQHgnz3t<)4w3ECF=dqKT*69<n%elNsv
z5V73_NDJ%%iL)Se3mgN10%Oi8RsN{8AO3POSKyi#bsT$So<_dUXwumy<23SzjFyQ}
z7lS$U-8~L@12lQJpmU!k@HV&)+ytxO0q{K-fCoV)-GQLL1pOg>m^zHX)Pw9h0{aQb
zb9e><g`*grD^=7@V{hHBU?cv(0OT+f{HZPUCvn1F#S3Dw?dhvmr*GQVF5Q~3uiu=X
zv29s(!prW4gpphG)_pgSsuMeiY)(!{GiZ2Afm^kb<mS|lr?Tus5^sdAtRQ>M@tZD7
z*)`u;YCv1J-5`!Uw;`by1YWQtksEt~W7j-Cb|djZr&^6<v0nGZE_3wj^_6BQ#n@d(
zr<E|OFO7BN6f0tBG~%dPiLIn}3msS&th?!~SF=VI!<x;0lB%}ryQ?FoJIak(r;&K(
zjNF$ZA{!!n^Oim{o-;WIE`S8z(Hjuwt8fe>?~Fdab>c1f0UTZyRg1R42o&01z`lD)
zUD_v5F!vbBU(ls~Rh>b6cl-q{D7iC?LLF#}M>`59G4`k3O7b?~V{Zia#=U&ho1{*%
z9zmT`C6F-od}5~dLdFg=cApd@*H126Y31v)Mc#aJ7acd1J`LYrTebOa@GPZ>M-V%U
zkQ=K?vL33)T)8}MPw4gjS4^XT`k-YBo!1{VC*#-0mU<aRAHQ|&C~3poi<v7JMN8)L
zTT;@t5g&Q*0N)?M?_VA?`Nq$0IBR70@ESg1JQ3+=@{ObY8)tl!pSAIwi?%_xm3po~
z+pYi4yY$bqGV7cE55bo`Qx^ZEH?&Ek4cYbizhJlZzv{qwoy+s%cQ(8JBz#?StvbXe
gm|{xbf3~-*eF+(vBT_Zy_4@0&qPZipzWLw#8+^aPQ~&?~

diff --git a/pkg/plugin/mock/plugin.go b/pkg/plugin/mock/plugin.go
index 403a472c3c..888d9267dd 100644
--- a/pkg/plugin/mock/plugin.go
+++ b/pkg/plugin/mock/plugin.go
@@ -5,11 +5,11 @@
 //
 
 // Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/microsoft/retina/pkg/plugin (interfaces: Plugin)
+// Source: github.com/microsoft/retina/pkg/plugin/ (interfaces: Plugin)
 //
 // Generated by this command:
 //
-//	mockgen -destination=mock/plugin.go -copyright_file=../lib/ignore_headers.txt -package=plugin github.com/microsoft/retina/pkg/plugin Plugin
+//	mockgen -destination=mock/plugin.go -copyright_file=../lib/ignore_headers.txt -package=plugin github.com/microsoft/retina/pkg/plugin/ Plugin
 //
 
 // Package plugin is a generated GoMock package.
@@ -27,6 +27,7 @@ import (
 type MockPlugin struct {
 	ctrl     *gomock.Controller
 	recorder *MockPluginMockRecorder
+	isgomock struct{}
 }
 
 // MockPluginMockRecorder is the mock recorder for MockPlugin.
@@ -47,31 +48,31 @@ func (m *MockPlugin) EXPECT() *MockPluginMockRecorder {
 }
 
 // Compile mocks base method.
-func (m *MockPlugin) Compile(arg0 context.Context) error {
+func (m *MockPlugin) Compile(ctx context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Compile", arg0)
+	ret := m.ctrl.Call(m, "Compile", ctx)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Compile indicates an expected call of Compile.
-func (mr *MockPluginMockRecorder) Compile(arg0 any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Compile(ctx any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compile", reflect.TypeOf((*MockPlugin)(nil).Compile), arg0)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compile", reflect.TypeOf((*MockPlugin)(nil).Compile), ctx)
 }
 
 // Generate mocks base method.
-func (m *MockPlugin) Generate(arg0 context.Context) error {
+func (m *MockPlugin) Generate(ctx context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Generate", arg0)
+	ret := m.ctrl.Call(m, "Generate", ctx)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Generate indicates an expected call of Generate.
-func (mr *MockPluginMockRecorder) Generate(arg0 any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Generate(ctx any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockPlugin)(nil).Generate), arg0)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockPlugin)(nil).Generate), ctx)
 }
 
 // Init mocks base method.
@@ -117,17 +118,17 @@ func (mr *MockPluginMockRecorder) SetupChannel(arg0 any) *gomock.Call {
 }
 
 // Start mocks base method.
-func (m *MockPlugin) Start(arg0 context.Context) error {
+func (m *MockPlugin) Start(ctx context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Start", arg0)
+	ret := m.ctrl.Call(m, "Start", ctx)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Start indicates an expected call of Start.
-func (mr *MockPluginMockRecorder) Start(arg0 any) *gomock.Call {
+func (mr *MockPluginMockRecorder) Start(ctx any) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockPlugin)(nil).Start), arg0)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockPlugin)(nil).Start), ctx)
 }
 
 // Stop mocks base method.