From d2f5b2ccabf74e89fb1e64fbf94f21c6a8af5f4e Mon Sep 17 00:00:00 2001
From: Guvenc Gulce <guevenc.guelce@sap.com>
Date: Mon, 4 Nov 2024 18:02:41 +0100
Subject: [PATCH] Do not delete conntrack reply direction keys

Do not delete conntrack reply direction keys to satisfy the assumption
that conntrack entries have two references.

Signed-off-by: Guvenc Gulce <guevenc.guelce@sap.com>
---
 include/dp_flow.h     |  6 +++++-
 src/dp_cntrack.c      |  7 +++++++
 src/nodes/dnat_node.c | 10 ++++++----
 src/nodes/lb_node.c   |  1 -
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/include/dp_flow.h b/include/dp_flow.h
index 0c341dac..a2770433 100644
--- a/include/dp_flow.h
+++ b/include/dp_flow.h
@@ -35,12 +35,16 @@ extern "C" {
 #define DP_FLOW_FLAG_FIREWALL			0x08
 #define DP_FLOW_FLAG_SRC_NAT64			0x10
 #define DP_FLOW_FLAG_DEFAULT			0x20
+#define DP_FLOW_FLAG_DST_NAT_FWD		0x40
 
-#define DP_FLOW_FLAG_NF					(DP_FLOW_FLAG_SRC_NAT64 | DP_FLOW_FLAG_SRC_NAT | DP_FLOW_FLAG_DST_NAT | DP_FLOW_FLAG_DST_LB)
+#define DP_FLOW_FLAG_NF                 (DP_FLOW_FLAG_SRC_NAT64 | DP_FLOW_FLAG_SRC_NAT | \
+										 DP_FLOW_FLAG_DST_NAT | DP_FLOW_FLAG_DST_LB | \
+										 DP_FLOW_FLAG_DST_NAT_FWD)
 
 #define DP_FLOW_HAS_NO_FLAGS(flag)			(!(flag))
 #define DP_FLOW_HAS_FLAG_SRC_NAT(flag)		((flag) & DP_FLOW_FLAG_SRC_NAT)
 #define DP_FLOW_HAS_FLAG_DST_NAT(flag)		((flag) & DP_FLOW_FLAG_DST_NAT)
+#define DP_FLOW_HAS_FLAG_DST_NAT_FWD(flag)	((flag) & DP_FLOW_FLAG_DST_NAT_FWD)
 #define DP_FLOW_HAS_FLAG_DST_LB(flag)		((flag) & DP_FLOW_FLAG_DST_LB)
 #define DP_FLOW_HAS_FLAG_FIREWALL(flag)		((flag) & DP_FLOW_FLAG_FIREWALL)
 #define DP_FLOW_HAS_FLAG_SRC_NAT64(flag)	((flag) & DP_FLOW_FLAG_SRC_NAT64)
diff --git a/src/dp_cntrack.c b/src/dp_cntrack.c
index aed71a39..bf911576 100644
--- a/src/dp_cntrack.c
+++ b/src/dp_cntrack.c
@@ -297,6 +297,13 @@ int dp_cntrack_handle(struct rte_mbuf *m, struct dp_flow *df)
 		dp_cntrack_tcp_state(flow_val, tcp_hdr);
 		dp_cntrack_set_timeout_tcp_flow(m, flow_val, df);
 	}
+
+	// Network neighbour and LB forward flows are not allowed to have reply flows
+	if (unlikely((flow_val->nf_info.nat_type == DP_FLOW_NAT_TYPE_NETWORK_NEIGH
+				  || flow_val->nf_info.nat_type == DP_FLOW_LB_TYPE_FORWARD)
+				 && (df->flow_dir == DP_FLOW_DIR_REPLY)))
+		return DP_ERROR;
+
 	df->conntrack = flow_val;
 	dp_cntrack_set_pkt_offload_decision(df);
 
diff --git a/src/nodes/dnat_node.c b/src/nodes/dnat_node.c
index f7fd7777..26c1383b 100644
--- a/src/nodes/dnat_node.c
+++ b/src/nodes/dnat_node.c
@@ -34,7 +34,10 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
 	if (!cntrack)
 		goto out;
 
-	if (DP_FLOW_HAS_NO_FLAGS(cntrack->flow_flags) && df->flow_dir == DP_FLOW_DIR_ORG && df->l3_type == RTE_ETHER_TYPE_IPV4) {
+	if (DP_FLOW_HAS_NO_FLAGS(cntrack->flow_flags)
+		&& df->flow_dir == DP_FLOW_DIR_ORG
+		&& df->l3_type == RTE_ETHER_TYPE_IPV4
+	) {
 		dst_ip = ntohl(df->dst.dst_addr);
 		vni = df->tun_info.dst_vni;
 		if (vni == 0)
@@ -57,8 +60,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
 					df->nat_type = DP_CHG_UL_DST_IP;
 					cntrack->nf_info.l4_type = df->l4_type;
 					dp_copy_ipv6(&cntrack->nf_info.underlay_dst, underlay_dst);
-
-					dp_delete_flow(&cntrack->flow_key[DP_FLOW_DIR_REPLY], cntrack); // no reverse traffic for relaying pkts
+					cntrack->flow_flags |= DP_FLOW_FLAG_DST_NAT_FWD;
 					return DNAT_NEXT_PACKET_RELAY;
 				}
 
@@ -88,7 +90,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
 		return DNAT_NEXT_IPV4_LOOKUP;
 	}
 
-	if (cntrack->nf_info.nat_type == DP_FLOW_NAT_TYPE_NETWORK_NEIGH) {
+	if (DP_FLOW_HAS_FLAG_DST_NAT_FWD(cntrack->flow_flags)) {
 		df->nat_type = DP_CHG_UL_DST_IP;
 		return DNAT_NEXT_PACKET_RELAY;
 	}
diff --git a/src/nodes/lb_node.c b/src/nodes/lb_node.c
index 644a3e01..b0636912 100644
--- a/src/nodes/lb_node.c
+++ b/src/nodes/lb_node.c
@@ -79,7 +79,6 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod
 
 		if (df->nat_type != DP_LB_RECIRC) {
 			cntrack->nf_info.nat_type = DP_FLOW_LB_TYPE_FORWARD;
-			dp_delete_flow(&cntrack->flow_key[DP_FLOW_DIR_REPLY], cntrack); // no reverse traffic for relaying pkts
 		} else
 			cntrack->nf_info.nat_type = DP_FLOW_LB_TYPE_RECIRC;