summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorLu Qiuwen <[email protected]>2022-03-01 13:29:11 +0800
committerLu Qiuwen <[email protected]>2022-04-02 07:11:49 -0400
commit597c1210553625c80d8dbb0e67a0ea3c7147c3d1 (patch)
tree04d5d468e61e519c1afb8e0e4cfb1799c598ea02 /examples
parenta508b24e6c214d9353433f57c69f1db9384597ce (diff)
增加APP的SmartOffload接口并修正了编译和调试中发现的若干问题。
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt5
-rw-r--r--examples/smartoffload.cc267
2 files changed, 271 insertions, 1 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 6746f31..f5e44b6 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -19,4 +19,7 @@ add_executable(mrtest-vxlan-encap vxlan-encap.c)
target_link_libraries(mrtest-vxlan-encap marsio pthread)
add_executable(mrtest-vxlan-link-id-inject vxlan-virtual-link-id.cc)
-target_link_libraries(mrtest-vxlan-link-id-inject marsio pthread pcap) \ No newline at end of file
+target_link_libraries(mrtest-vxlan-link-id-inject marsio pthread pcap)
+
+add_executable(mrtest-smartoffload smartoffload.cc)
+target_link_libraries(mrtest-smartoffload marsio pthread pcap)
diff --git a/examples/smartoffload.cc b/examples/smartoffload.cc
new file mode 100644
index 0000000..87d19f5
--- /dev/null
+++ b/examples/smartoffload.cc
@@ -0,0 +1,267 @@
+
+extern "C" {
+#include <assert.h>
+#include <marsio.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+}
+
+#include <algorithm>
+
+static char appsym[64] = "smartoffload";
+static char dev_symbol[64] = "vxlan_user";
+
+uint64_t cpu_mask = 0x1;
+unsigned int nr_thread = 1;
+
+struct mr_instance * mr_instance = NULL;
+struct mr_vdev * dev_handler = NULL;
+struct mr_sendpath * sendpath = NULL;
+
+#define BURST_MAX 64
+unsigned int nr_burst = 1;
+unsigned int self_loop = 0;
+
+int __is_bfd_pkt_and_make_answer(char * pkt_ptr, unsigned int pkt_len, bool make_answer)
+{
+ struct rte_ether_hdr * eth_hdr = (struct rte_ether_hdr *)pkt_ptr;
+
+ /* must be ipv4 pkt for vxlan overlay */
+ if (eth_hdr->ether_type != ntohs(RTE_ETHER_TYPE_IPV4))
+ {
+ return 0;
+ }
+
+ pkt_ptr += sizeof(struct rte_ether_hdr);
+ pkt_len -= sizeof(struct rte_ether_hdr);
+
+ /* ipv4 header */
+ struct rte_ipv4_hdr * ipv4_hdr = (struct rte_ipv4_hdr *)pkt_ptr;
+ if (ipv4_hdr->next_proto_id != IPPROTO_UDP)
+ {
+ return 0;
+ }
+
+ pkt_ptr += sizeof(struct rte_ipv4_hdr);
+ pkt_len -= sizeof(struct rte_ipv4_hdr);
+
+ struct rte_udp_hdr * udp_hdr = (struct rte_udp_hdr *)pkt_ptr;
+ if (udp_hdr->dst_port != ntohs(3784))
+ {
+ return 0;
+ }
+
+ if (make_answer)
+ {
+
+ /* at here, this pkt must be a vxlan pkt,
+ we need to swap the mac addresses and ipv4 addresses */
+
+ struct rte_ether_addr swap_tmp;
+ rte_ether_addr_copy(&eth_hdr->d_addr, &swap_tmp);
+ rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ rte_ether_addr_copy(&swap_tmp, &eth_hdr->s_addr);
+
+ /* ipv4 src, dst and udp's ports must be swap */
+ rte_be32_t ipv4_addr_swap_tmp;
+ ipv4_addr_swap_tmp = ipv4_hdr->dst_addr;
+ ipv4_hdr->dst_addr = ipv4_hdr->src_addr;
+ ipv4_hdr->src_addr = ipv4_addr_swap_tmp;
+
+ rte_be16_t udp_port_swap_tmp;
+ udp_port_swap_tmp = udp_hdr->dst_port;
+ udp_hdr->dst_port = udp_hdr->src_port;
+ udp_hdr->src_port = udp_port_swap_tmp;
+ }
+
+ return 1;
+}
+
+int __is_g_vxlan_and_make_inject(char * pkt_ptr, unsigned int pkt_len, bool do_inject)
+{
+ struct rte_ether_hdr * eth_hdr = (struct rte_ether_hdr *)pkt_ptr;
+
+ /* must be ipv4 pkt for vxlan overlay */
+ if (eth_hdr->ether_type != ntohs(RTE_ETHER_TYPE_IPV4))
+ {
+ return 0;
+ }
+
+ pkt_ptr += sizeof(struct rte_ether_hdr);
+ pkt_len -= sizeof(struct rte_ether_hdr);
+
+ /* ipv4 header */
+ struct rte_ipv4_hdr * ipv4_hdr = (struct rte_ipv4_hdr *)pkt_ptr;
+ if (ipv4_hdr->next_proto_id != IPPROTO_UDP)
+ {
+ return 0;
+ }
+
+ pkt_ptr += sizeof(struct rte_ipv4_hdr);
+ pkt_len -= sizeof(struct rte_ipv4_hdr);
+
+ struct rte_udp_hdr * udp_hdr = (struct rte_udp_hdr *)pkt_ptr;
+ if (udp_hdr->dst_port != ntohs(4789))
+ {
+ return 0;
+ }
+
+ /* at here, this pkt must be a vxlan pkt,
+ we need to swap the mac addresses and ipv4 addresses */
+
+ if (do_inject)
+ {
+ struct rte_ether_addr swap_tmp;
+ rte_ether_addr_copy(&eth_hdr->d_addr, &swap_tmp);
+ rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ rte_ether_addr_copy(&swap_tmp, &eth_hdr->s_addr);
+
+ rte_be32_t ipv4_addr_swap_tmp;
+ ipv4_addr_swap_tmp = ipv4_hdr->dst_addr;
+ ipv4_hdr->dst_addr = ipv4_hdr->src_addr;
+ ipv4_hdr->src_addr = ipv4_addr_swap_tmp;
+ }
+
+ return 1;
+}
+
+void * txonly_loop(void * arg)
+{
+ uintptr_t sid = (uintptr_t)arg;
+ marsio_buff_t * rx_buff[BURST_MAX];
+ marsio_thread_init(mr_instance);
+
+ for (;;)
+ {
+ int ret = marsio_recv_burst(dev_handler, sid, rx_buff, 1);
+ if (ret != 1)
+ continue;
+
+ marsio_buff_t * rx_buff_ptr = rx_buff[0];
+ char * pkt_ptr = marsio_buff_mtod(rx_buff_ptr);
+ unsigned int pkt_len = marsio_buff_datalen(rx_buff_ptr);
+ assert(pkt_ptr != NULL && pkt_len != 0);
+
+ bool should_inject = false;
+
+ if (__is_bfd_pkt_and_make_answer(pkt_ptr, pkt_len, 0) > 0)
+ {
+ __is_bfd_pkt_and_make_answer(pkt_ptr, pkt_len, 1);
+ should_inject = true;
+ }
+ else if (__is_g_vxlan_and_make_inject(pkt_ptr, pkt_len, 0) > 0)
+ {
+ /* for all vxlan pkts, create an offload request */
+ marsio_buff_t * offload_request_buf = marsio_buff_malloc_smartoffload(dev_handler, pkt_ptr, pkt_len);
+ assert(offload_request_buf != NULL);
+
+ __is_g_vxlan_and_make_inject(pkt_ptr, pkt_len, 1);
+
+ /* inject the offload request */
+ marsio_send_burst_with_options(sendpath, sid, &offload_request_buf, 1, MARSIO_SEND_OPT_CTRL);
+ should_inject = true;
+ }
+
+ if (should_inject)
+ {
+ marsio_send_burst_with_options(sendpath, sid, &rx_buff_ptr, 1, 0);
+ }
+ else
+ {
+ marsio_buff_free(mr_instance, rx_buff, 1, MARSIO_SOCKET_ID_ANY, MARSIO_LCORE_ID_ANY);
+ }
+ }
+
+ return (void *)NULL;
+}
+
+int help()
+{
+ return 0;
+}
+
+int main(int argc, char * argv[])
+{
+ int opt = 0;
+ while ((opt = getopt(argc, argv, "s:t:a:c:b:d:h?rl")) != -1)
+ {
+ char * endptr = NULL;
+ switch (opt)
+ {
+ case '?':
+ case 'h': {
+ help();
+ break;
+ }
+ case 'd': {
+ snprintf(dev_symbol, sizeof(dev_symbol), "%s", optarg);
+ break;
+ }
+ case 'a': {
+ snprintf(appsym, sizeof(appsym), "%s", optarg);
+ break;
+ }
+ case 'c': {
+ cpu_mask = strtoull(optarg, &endptr, 0);
+ if (cpu_mask == 0 && endptr == optarg)
+ help();
+ break;
+ }
+ case 'b': {
+ nr_burst = strtoull(optarg, &endptr, 0);
+ if (nr_burst == 0 && endptr == optarg)
+ help();
+ break;
+ }
+ case 'l': {
+ self_loop = 1;
+ break;
+ }
+
+ default:
+ help();
+ break;
+ }
+ }
+
+ mr_instance = marsio_create();
+ if (mr_instance == NULL)
+ {
+ fprintf(stderr, "Marsio instance create failed. ");
+ abort();
+ }
+
+ unsigned int opt_value = 1;
+ marsio_option_set(mr_instance, MARSIO_OPT_EXIT_WHEN_ERR, &opt_value, sizeof(opt_value));
+ marsio_option_set(mr_instance, MARSIO_OPT_THREAD_MASK, &cpu_mask, sizeof(cpu_mask));
+ marsio_init(mr_instance, appsym);
+
+ nr_thread = __builtin_popcountll(cpu_mask);
+ dev_handler = marsio_open_device(mr_instance, dev_symbol, nr_thread, nr_thread);
+ fprintf(stdout, "Thread Count = %d\n", nr_thread);
+
+ sendpath = marsio_sendpath_create_by_vdev(dev_handler);
+ assert(sendpath != NULL);
+
+ pthread_t __tmp_pid[nr_thread];
+ for (int i = 0; i < nr_thread; i++)
+ {
+ pthread_create(&__tmp_pid[i], NULL, txonly_loop, (void *)(uintptr_t)i);
+ }
+
+ for (int i = 0; i < nr_thread; i++)
+ {
+ pthread_join(__tmp_pid[i], NULL);
+ }
+
+ marsio_destory(mr_instance);
+ fprintf(stdout, "RXONLY is terminated. ");
+ return 0;
+}