From a86ef865f47b99b41e426e621cb3b5e3416a70ff Mon Sep 17 00:00:00 2001
From: hantwofish <hankangkang5@huawei.com>
Date: Thu, 27 Jun 2024 19:53:07 +0800
Subject: [PATCH] [virtio]: distribute pkg by dst_port

---
 src/lstack/core/lstack_protocol_stack.c | 27 ++++++++++++++----
 src/lstack/core/lstack_virtio.c         |  9 ++++++
 src/lstack/include/lstack_virtio.h      |  2 ++
 src/lstack/netif/lstack_ethdev.c        | 37 +++++++++++++++++++++++--
 src/lstack/netif/lstack_vdev.c          |  2 ++
 5 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c
index d6e3c86..e272a04 100644
--- a/src/lstack/core/lstack_protocol_stack.c
+++ b/src/lstack/core/lstack_protocol_stack.c
@@ -34,6 +34,7 @@
 #include "lstack_control_plane.h"
 #include "posix/lstack_epoll.h"
 #include "lstack_stack_stat.h"
+#include "lstack_virtio.h"
 #include "lstack_protocol_stack.h"
 
 #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0)
@@ -509,6 +510,9 @@ int stack_polling(uint32_t wakeup_tick)
         }
     }
 #endif
+    if (get_global_cfg_params()->flow_bifurcation) {
+        virtio_tap_process_rx(stack->port_id, stack->queue_id);
+    }
     return force_quit;
 }
 
@@ -979,14 +983,25 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack
         }
     }
 #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0)
-    ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true);
-    if (ret != 0) {
-        cur_stack->stats.rx_allocmbuf_fail++;
-        return;
+    if (get_global_cfg_params()->kni_switch) {
+        ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true);
+        if (ret != 0) {
+            cur_stack->stats.rx_allocmbuf_fail++;
+            return;
+        }
+        copy_mbuf(mbuf_copy, mbuf);
+        kni_handle_tx(mbuf_copy);
     }
-    copy_mbuf(mbuf_copy, mbuf);
-    kni_handle_tx(mbuf_copy);
 #endif
+    if (get_global_cfg_params()->flow_bifurcation) {
+        ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true);
+        if (ret != 0) {
+            cur_stack->stats.rx_allocmbuf_fail++;
+            return;
+        }
+        copy_mbuf(mbuf_copy, mbuf);
+        virtio_tap_process_tx(stack->queue_id, mbuf_copy);
+    }
     return;
 }
 
diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c
index c3b3511..ad3088d 100644
--- a/src/lstack/core/lstack_virtio.c
+++ b/src/lstack/core/lstack_virtio.c
@@ -331,3 +331,12 @@ int virtio_port_create(int lstack_net_port)
     }
     return 0;
 }
+
+bool virtio_distribute_pkg_to_kernel(uint16_t dst_port)
+{
+    if (dst_port == VIRTIO_PORT_INVALID) {
+        return false;
+    }
+
+    return (port_map_get(dst_port) == 0);
+}
\ No newline at end of file
diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h
index d40c754..615d9c9 100644
--- a/src/lstack/include/lstack_virtio.h
+++ b/src/lstack/include/lstack_virtio.h
@@ -14,6 +14,7 @@
 
 #include <stdint.h>
 
+#define VIRTIO_PORT_INVALID 0xffff
 #define VIRTIO_MAX_QUEUE_NUM 8
 
 // RTE_ETHER_ADDR_PRT_FMT RTE_ETHER_ADDR_BYTES are defined in dpdk 21.11
@@ -48,4 +49,5 @@ void virtio_tap_process_tx(uint16_t queue_id, struct rte_mbuf *mbuf_copy);
 int virtio_port_create(int lstack_net_port);
 
 struct virtio_instance* virtio_instance_get(void);
+bool virtio_distribute_pkg_to_kernel(uint16_t dst_port);
 #endif
\ No newline at end of file
diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c
index 3bfa8af..933c3e8 100644
--- a/src/lstack/netif/lstack_ethdev.c
+++ b/src/lstack/netif/lstack_ethdev.c
@@ -35,6 +35,7 @@
 #include "lstack_thread_rpc.h"
 #include "lstack_flow.h"
 #include "lstack_tx_cache.h"
+#include "lstack_virtio.h"
 #include "lstack_ethdev.h"
 
 /* FRAME_MTU + 14byte header */
@@ -149,6 +150,25 @@ void kni_handle_tx(struct rte_mbuf *mbuf)
         ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \
         (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
 
+#define IS_ICMPV6_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \
+        ((ptype & RTE_PTYPE_L4_ICMP) == RTE_PTYPE_L4_ICMP) && \
+        (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
+
+static uint16_t eth_dev_get_dst_port(struct rte_mbuf *pkt)
+{
+    uint16_t dst_port = VIRTIO_PORT_INVALID;
+    uint32_t packet_type = pkt->packet_type;
+
+    void *l4_hdr = rte_pktmbuf_mtod_offset(pkt, void *, pkt->l2_len + pkt->l3_len);
+
+    if (IS_IPV4_TCP_PKT(packet_type) || IS_IPV6_TCP_PKT(packet_type)) {
+        dst_port = rte_be_to_cpu_16(((struct rte_tcp_hdr *)l4_hdr)->dst_port);
+    } else if (IS_IPV4_UDP_PKT(packet_type) || IS_IPV6_UDP_PKT(packet_type)) {
+        dst_port = rte_be_to_cpu_16(((struct rte_udp_hdr *)l4_hdr)->dst_port);
+    }
+    return dst_port;
+}
+
 int32_t eth_dev_poll(void)
 {
     uint32_t nr_pkts;
@@ -170,7 +190,8 @@ int32_t eth_dev_poll(void)
         int transfer_type = TRANSFER_CURRENT_THREAD;
         /* copy arp into other stack */
         if (!use_ltran()) {
-            if (unlikely(IS_ARP_PKT(stack->pkts[i]->packet_type))) {
+            if (unlikely(IS_ARP_PKT(stack->pkts[i]->packet_type)) ||
+                unlikely(IS_ICMPV6_PKT(stack->pkts[i]->packet_type))) {
                 stack_broadcast_arp(stack->pkts[i], stack);
                 /* copy arp into other process */
                 transfer_arp_to_other_process(stack->pkts[i]);
@@ -178,17 +199,27 @@ int32_t eth_dev_poll(void)
                 if (get_global_cfg_params()->tuple_filter && stack->queue_id == 0) {
                     transfer_type = distribute_pakages(stack->pkts[i]);
                 }
+                if (get_global_cfg_params()->flow_bifurcation) {
+                    uint16_t dst_port = eth_dev_get_dst_port(stack->pkts[i]);
+                    if (virtio_distribute_pkg_to_kernel(dst_port)) {
+                        transfer_type = TRANSFER_KERNEL;
+                    }
+                }
             }
         }
 
         if (likely(transfer_type == TRANSFER_CURRENT_THREAD)) {
             eth_dev_recv(stack->pkts[i], stack);
         } else if (transfer_type == TRANSFER_KERNEL) {
+            if (get_global_cfg_params()->flow_bifurcation) {
+                virtio_tap_process_tx(stack->queue_id, stack->pkts[i]);
+            } else {
 #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0)
-            kni_handle_tx(stack->pkts[i]);
+                kni_handle_tx(stack->pkts[i]);
 #else
-            rte_pktmbuf_free(stack->pkts[i]);
+                rte_pktmbuf_free(stack->pkts[i]);
 #endif
+            }
         } else {
             /* transfer to other thread */
         }
diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c
index 5ce69a9..cb3953e 100644
--- a/src/lstack/netif/lstack_vdev.c
+++ b/src/lstack/netif/lstack_vdev.c
@@ -115,6 +115,8 @@ static inline void vdev_pkts_parse(struct rte_mbuf **pkts, int pkt_num)
             } else if (iph6->proto == IPPROTO_UDP) {
                 pkts[i]->l4_len = sizeof(struct rte_udp_hdr);
                 pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP;
+            } else if (iph6->proto == IPPROTO_ICMPV6) {
+                pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP;
             }
         } else if (type == RTE_BE16(RTE_ETHER_TYPE_ARP)) {
             pkts[i]->packet_type = RTE_PTYPE_L2_ETHER_ARP;
-- 
2.33.0

