summaryrefslogtreecommitdiffstats
path: root/common/VIL/pipeline_loadb
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/pipeline_loadb')
-rw-r--r--common/VIL/pipeline_loadb/pipeline_loadb.c493
-rw-r--r--common/VIL/pipeline_loadb/pipeline_loadb.h29
-rw-r--r--common/VIL/pipeline_loadb/pipeline_loadb_be.c1417
-rw-r--r--common/VIL/pipeline_loadb/pipeline_loadb_be.h149
4 files changed, 2088 insertions, 0 deletions
diff --git a/common/VIL/pipeline_loadb/pipeline_loadb.c b/common/VIL/pipeline_loadb/pipeline_loadb.c
new file mode 100644
index 00000000..fdcc17ae
--- /dev/null
+++ b/common/VIL/pipeline_loadb/pipeline_loadb.c
@@ -0,0 +1,493 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+
+#include "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_loadb.h"
+#include "vnf_common.h"
+//#include "lib_arp.h"
+#include "pipeline_arpicmp_be.h"
+//#include "lib_arp.h"
+//#include "interface.h"
+static int
+app_pipeline_loadb_entry_dbg(struct app_params *app,
+ uint32_t pipeline_id, uint8_t *msg)
+{
+ struct pipeline_loadb_entry_dbg_msg_req *req;
+ struct pipeline_loadb_entry_dbg_msg_rsp *rsp;
+
+ /* Check input arguments */
+ if (app == NULL)
+ return -1;
+
+ /* Allocate and write request */
+ req = app_msg_alloc(app);
+ if (req == NULL)
+ return -1;
+
+ req->type = PIPELINE_MSG_REQ_CUSTOM;
+ req->subtype = PIPELINE_LOADB_MSG_REQ_ENTRY_DBG;
+ req->data[0] = msg[0];
+ req->data[1] = msg[1];
+
+ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+ if (rsp == NULL)
+ return -1;
+
+ /* Read response */
+ if (rsp->status) {
+ app_msg_free(app, rsp);
+ printf("Error rsp->status %d\n", rsp->status);
+ return -1;
+ }
+
+ /* Free response */
+ app_msg_free(app, rsp);
+
+ return 0;
+}
+
+/*
+ * entry dbg
+ */
+
+struct cmd_entry_dbg_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t entry_string;
+ cmdline_fixed_string_t dbg_string;
+ uint8_t cmd;
+ uint8_t d1;
+};
+
+static void
+cmd_entry_dbg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, void *data)
+{
+ struct cmd_entry_dbg_result *params = parsed_result;
+ struct app_params *app = data;
+ uint8_t msg[2];
+ int status;
+
+ msg[0] = params->cmd;
+ msg[1] = params->d1;
+ status = app_pipeline_loadb_entry_dbg(app, params->p, msg);
+
+ if (status != 0) {
+ printf("Dbg Command failed\n");
+ return;
+ }
+}
+
+static cmdline_parse_token_string_t lb_cmd_entry_dbg_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result, p_string, "p");
+
+static cmdline_parse_token_num_t lb_cmd_entry_dbg_p =
+TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, p, UINT32);
+
+static cmdline_parse_token_string_t lb_cmd_entry_dbg_entry_string =
+TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result,
+ entry_string, "lbentry");
+
+static cmdline_parse_token_string_t lb_cmd_entry_dbg_dbg_string =
+TOKEN_STRING_INITIALIZER(struct cmd_entry_dbg_result, dbg_string,
+ "dbg");
+
+static cmdline_parse_token_num_t lb_cmd_entry_dbg_cmd =
+TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, cmd, UINT8);
+
+static cmdline_parse_token_num_t lb_cmd_entry_dbg_d1 =
+TOKEN_NUM_INITIALIZER(struct cmd_entry_dbg_result, d1, UINT8);
+
+static cmdline_parse_inst_t lb_cmd_entry_dbg = {
+ .f = cmd_entry_dbg_parsed,
+ .data = NULL,
+ .help_str = "LOADB dbg cmd",
+ .tokens = {
+ (void *)&lb_cmd_entry_dbg_p_string,
+ (void *)&lb_cmd_entry_dbg_p,
+ (void *)&lb_cmd_entry_dbg_entry_string,
+ (void *)&lb_cmd_entry_dbg_dbg_string,
+ (void *)&lb_cmd_entry_dbg_cmd,
+ (void *)&lb_cmd_entry_dbg_d1,
+ NULL,
+ },
+};
+
+/*static void*/
+/*print_arp_entry(const struct app_pipeline_arp_icmp_arp_entry *entry)*/
+/*{*/
+/* printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32*/
+/* ".%" PRIu32 ".%" PRIu32 ") => "*/
+/* "HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32*/
+/* ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",*/
+/* entry->key.key.ipv4.port_id,*/
+/* (entry->key.key.ipv4.ip >> 24) & 0xFF,*/
+/* (entry->key.key.ipv4.ip >> 16) & 0xFF,*/
+/* (entry->key.key.ipv4.ip >> 8) & 0xFF,*/
+/* entry->key.key.ipv4.ip & 0xFF,*/
+
+/* entry->macaddr.addr_bytes[0],*/
+/* entry->macaddr.addr_bytes[1],*/
+/* entry->macaddr.addr_bytes[2],*/
+/* entry->macaddr.addr_bytes[3],*/
+/* entry->macaddr.addr_bytes[4],*/
+/* entry->macaddr.addr_bytes[5]);*/
+/*}*/
+
+#if 0
+/*
+ * arp add
+ */
+
+struct cmd_arp_add_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arpadd_string;
+ uint32_t port_id;
+ cmdline_ipaddr_t ip;
+ struct ether_addr macaddr;
+
+};
+
+static void
+cmd_arp_add_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, __rte_unused void *data)
+{
+ struct cmd_arp_add_result *params = parsed_result;
+ uint8_t ipv6[16];
+
+/* struct pipeline_arp_icmp_arp_key key;*/
+/* key.type = PIPELINE_ARP_ICMP_ARP_IPV4;*/
+/* key.key.ipv4.port_id = params->port_id;*/
+/* key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);*/
+/* populate_arp_entry(&req->macaddr, rte_bswap32(req->key.key.ipv4.ip),
+ * req->key.key.ipv4.port_id);
+ */
+ if (params->ip.family == AF_INET) {
+ populate_arp_entry(&params->macaddr,
+ rte_cpu_to_be_32(params->ip.addr.
+ ipv4.s_addr),
+ params->port_id, STATIC_ARP);
+ } else {
+ memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16);
+ populate_nd_entry(&params->macaddr, ipv6, params->port_id, STATIC_ND);
+ }
+}
+
+static cmdline_parse_token_string_t cmd_arp_add_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_add_p =
+TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_add_arp_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arpadd_string, "arpadd");
+
+static cmdline_parse_token_num_t cmd_arp_add_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, port_id, UINT32);
+
+static cmdline_parse_token_ipaddr_t cmd_arp_add_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_arp_add_result, ip);
+
+static cmdline_parse_token_etheraddr_t cmd_arp_add_macaddr =
+TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, macaddr);
+
+static cmdline_parse_inst_t cmd_arp_add = {
+ .f = cmd_arp_add_parsed,
+ .data = NULL,
+ .help_str = "ARP add",
+ .tokens = {
+ (void *)&cmd_arp_add_p_string,
+ (void *)&cmd_arp_add_p,
+ (void *)&cmd_arp_add_arp_string,
+ (void *)&cmd_arp_add_port_id,
+ (void *)&cmd_arp_add_ip,
+ (void *)&cmd_arp_add_macaddr,
+ NULL,
+ },
+};
+
+/*
+ * arp del
+ */
+
+struct cmd_arp_del_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+ uint32_t port_id;
+ cmdline_ipaddr_t ip;
+};
+
+static void
+cmd_arp_del_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, __rte_unused void *data)
+{
+ struct cmd_arp_del_result *params = parsed_result;
+ uint8_t ipv6[16];
+
+/* struct pipeline_arp_icmp_arp_key key;*/
+/* key.type = PIPELINE_ARP_ICMP_ARP_IPV4;*/
+/* key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);*/
+/* key.key.ipv4.port_id = params->port_id;*/
+/* remove_arp_entry(rte_bswap32(req->key.key.ipv4.ip),
+ * req->key.key.ipv4.port_id);
+ */
+ if (params->ip.family == AF_INET) {
+ remove_arp_entry(rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr),
+ params->port_id, NULL);
+ } else {
+ memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16);
+ remove_nd_entry_ipv6(ipv6, params->port_id);
+ }
+}
+
+static cmdline_parse_token_string_t cmd_arp_del_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_del_p =
+TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_del_arp_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arpdel");
+
+static cmdline_parse_token_num_t cmd_arp_del_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, port_id, UINT32);
+
+static cmdline_parse_token_ipaddr_t cmd_arp_del_ip =
+TOKEN_IPADDR_INITIALIZER(struct cmd_arp_del_result, ip);
+
+static cmdline_parse_inst_t cmd_arp_del = {
+ .f = cmd_arp_del_parsed,
+ .data = NULL,
+ .help_str = "ARP delete",
+ .tokens = {
+ (void *)&cmd_arp_del_p_string,
+ (void *)&cmd_arp_del_p,
+ (void *)&cmd_arp_del_arp_string,
+ (void *)&cmd_arp_del_port_id,
+ (void *)&cmd_arp_del_ip,
+ NULL,
+ },
+};
+
+/*
+ * arp req
+ */
+
+/*Re-uses delete structures*/
+
+static void
+cmd_arp_req_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, __rte_unused void *data)
+{
+ struct cmd_arp_del_result *params = parsed_result;
+ /*struct app_params *app = data;*/
+
+ struct arp_key_ipv4 key;
+/* int status;*/
+
+/* key.type = ARP_IPV4;*/
+/* key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);*/
+/* key.key.ipv4.port_id = params->port_id;*/
+ key.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr);
+ key.port_id = params->port_id;
+ key.filler1 = 0;
+ key.filler2 = 0;
+ key.filler3 = 0;
+
+ struct arp_entry_data *arp_data = retrieve_arp_entry(key);
+
+ if (arp_data) {
+ if (ARPICMP_DEBUG)
+ printf("ARP entry exists for ip 0x%x, port %d\n",
+ params->ip.addr.ipv4.s_addr, params->port_id);
+ return;
+ }
+ /* else request an arp*/
+ if (ARPICMP_DEBUG)
+ printf("ARP - requesting arp for ip 0x%x, port %d\n",
+ params->ip.addr.ipv4.s_addr, params->port_id);
+ request_arp(params->port_id, params->ip.addr.ipv4.s_addr);
+ /*give pipeline number too*/
+}
+
+static cmdline_parse_token_string_t cmd_arp_req_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arpreq");
+
+static cmdline_parse_inst_t cmd_arp_req = {
+ .f = cmd_arp_req_parsed,
+ .data = NULL,
+ .help_str = "ARP request",
+ .tokens = {
+ (void *)&cmd_arp_del_p_string,
+ (void *)&cmd_arp_del_p,
+ (void *)&cmd_arp_req_string,
+ (void *)&cmd_arp_del_port_id,
+ (void *)&cmd_arp_del_ip,
+ NULL,
+ },
+};
+
+/*
+ * arpicmp echo req
+ */
+
+/*Re-uses delete structures*/
+
+static void
+cmd_icmp_echo_req_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_arp_del_result *params = parsed_result;
+ struct rte_mbuf *pkt;
+ l2_phy_interface_t *port = (l2_phy_interface_t *) ifm_get_port((uint8_t)params->port_id);
+
+ if (ARPICMP_DEBUG)
+ printf("Echo Req Handler ip %x, port %d\n",
+ params->ip.addr.ipv4.s_addr, params->port_id);
+
+ pkt = request_echo(params->port_id, params->ip.addr.ipv4.s_addr);
+ port->transmit_single_pkt(port, pkt);
+}
+
+static cmdline_parse_token_string_t cmd_icmp_echo_req_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "icmpecho");
+
+static cmdline_parse_inst_t cmd_icmp_echo_req = {
+ .f = cmd_icmp_echo_req_parsed,
+ .data = NULL,
+ .help_str = "ICMP echo request",
+ .tokens = {
+ (void *)&cmd_arp_del_p_string,
+ (void *)&cmd_arp_del_p,
+ (void *)&cmd_icmp_echo_req_string,
+ (void *)&cmd_arp_del_port_id,
+ (void *)&cmd_arp_del_ip,
+ NULL,
+ },
+};
+
+/*
+ * arp ls
+ */
+
+struct cmd_arp_ls_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+};
+
+static void
+cmd_arp_ls_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl, __rte_unused void *data)
+{
+ printf("\nARP table ...\n");
+ printf("-------------\n");
+ print_arp_table();
+
+ printf
+ ("............................................................\n");
+
+ printf("\nND IPv6 table:\n");
+ printf("--------------\n");
+ print_nd_table();
+}
+
+static cmdline_parse_token_string_t cmd_arp_ls_p_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, p_string,
+ "p");
+
+static cmdline_parse_token_num_t cmd_arp_ls_p =
+TOKEN_NUM_INITIALIZER(struct cmd_arp_ls_result, p, UINT32);
+
+static cmdline_parse_token_string_t cmd_arp_ls_arp_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, arp_string,
+ "arpls");
+
+static cmdline_parse_inst_t cmd_arp_ls = {
+ .f = cmd_arp_ls_parsed,
+ .data = NULL,
+ .help_str = "ARP list",
+ .tokens = {
+ (void *)&cmd_arp_ls_p_string,
+ (void *)&cmd_arp_ls_p,
+ (void *)&cmd_arp_ls_arp_string,
+ NULL,
+ },
+};
+
+/*
+ * show ports info
+ */
+
+struct cmd_show_ports_info_result {
+ cmdline_fixed_string_t p_string;
+ uint32_t p;
+ cmdline_fixed_string_t arp_string;
+};
+
+static void
+cmd_show_ports_info_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ show_ports_info();
+}
+
+static cmdline_parse_token_string_t cmd_show_ports_info_string =
+TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, arp_string,
+ "showPortsInfo");
+
+static cmdline_parse_inst_t cmd_show_ports_info = {
+ .f = cmd_show_ports_info_parsed,
+ .data = NULL,
+ .help_str = "show ports info",
+ .tokens = {
+ (void *)&cmd_arp_ls_p_string,
+ (void *)&cmd_arp_ls_p,
+ (void *)&cmd_show_ports_info_string,
+ NULL,
+ },
+};
+#endif
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *) &lb_cmd_entry_dbg,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_loadb_fe_ops = {
+ .f_init = NULL,
+ .f_free = NULL,
+ .cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_loadb = {
+ .name = "LOADB",
+ .be_ops = &pipeline_loadb_be_ops,
+ .fe_ops = &pipeline_loadb_fe_ops,
+};
diff --git a/common/VIL/pipeline_loadb/pipeline_loadb.h b/common/VIL/pipeline_loadb/pipeline_loadb.h
new file mode 100644
index 00000000..866a6eab
--- /dev/null
+++ b/common/VIL/pipeline_loadb/pipeline_loadb.h
@@ -0,0 +1,29 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef __INCLUDE_PIPELINE_LOADB_H__
+#define __INCLUDE_PIPELINE_LOADB_H__
+
+#include "pipeline.h"
+#include "pipeline_loadb_be.h"
+
+/*
+ * Pipeline type
+ */
+
+extern struct pipeline_type pipeline_loadb;
+
+#endif
diff --git a/common/VIL/pipeline_loadb/pipeline_loadb_be.c b/common/VIL/pipeline_loadb/pipeline_loadb_be.c
new file mode 100644
index 00000000..c7910127
--- /dev/null
+++ b/common/VIL/pipeline_loadb/pipeline_loadb_be.c
@@ -0,0 +1,1417 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_ip.h>
+#include <rte_hash.h>
+#include <rte_byteorder.h>
+#include <rte_table_lpm.h>
+#include <rte_table_hash.h>
+#include <rte_jhash.h>
+#include <rte_thash.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_prefetch.h>
+#include <rte_table_array.h>
+#include "pipeline_loadb_be.h"
+#include "pipeline_actions_common.h"
+#include "hash_func.h"
+#include "pipeline_arpicmp_be.h"
+#include "vnf_common.h"
+#include "app.h"
+
+#define BYTES_TO_BITS 8
+#define ROTATE_15_BITS 15
+
+#define MAX_VNF_THREADS 16
+
+int pkt_burst_cnt;
+
+uint8_t LOADB_DEBUG;
+uint8_t total_vnf_threads;
+uint32_t phyport_offset;
+
+struct pipeline_loadb {
+ struct pipeline p;
+ pipeline_msg_req_handler custom_handlers[PIPELINE_LOADB_MSG_REQS];
+
+ uint8_t n_vnf_threads;
+ uint8_t n_lb_tuples;
+ uint32_t outport_offset;
+ uint64_t receivedLBPktCount;
+ uint64_t droppedLBPktCount;
+ uint8_t links_map[PIPELINE_MAX_PORT_IN];
+ uint8_t outport_id[PIPELINE_MAX_PORT_IN];
+ uint8_t n_prv_Q;
+ uint8_t n_pub_Q;
+ uint8_t pipeline_num;
+} __rte_cache_aligned;
+
+uint8_t default_rss_key[] = {
+ 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
+ 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
+ 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
+ 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
+ 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
+};
+
+static void *pipeline_loadb_msg_req_custom_handler(struct pipeline *p,
+ void *msg);
+
+static pipeline_msg_req_handler handlers[] = {
+ [PIPELINE_MSG_REQ_PING] =
+ pipeline_msg_req_ping_handler,
+ [PIPELINE_MSG_REQ_STATS_PORT_IN] =
+ pipeline_msg_req_stats_port_in_handler,
+ [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
+ pipeline_msg_req_stats_port_out_handler,
+ [PIPELINE_MSG_REQ_STATS_TABLE] =
+ pipeline_msg_req_stats_table_handler,
+ [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
+ pipeline_msg_req_port_in_enable_handler,
+ [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
+ pipeline_msg_req_port_in_disable_handler,
+ [PIPELINE_MSG_REQ_CUSTOM] =
+ pipeline_loadb_msg_req_custom_handler,
+
+};
+
+static void *pipeline_loadb_msg_req_entry_dbg_handler(struct pipeline *,
+ void *msg);
+
+static pipeline_msg_req_handler custom_handlers[] = {
+ [PIPELINE_LOADB_MSG_REQ_ENTRY_DBG] =
+ pipeline_loadb_msg_req_entry_dbg_handler,
+};
+
+/*
+ * LOADB table
+ */
+struct loadb_table_entry {
+ struct rte_pipeline_table_entry head;
+} __rte_cache_aligned;
+
+void *pipeline_loadb_msg_req_custom_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_loadb *p_lb = (struct pipeline_loadb *)p;
+ struct pipeline_custom_msg_req *req = msg;
+ pipeline_msg_req_handler f_handle;
+
+ f_handle = (req->subtype < PIPELINE_LOADB_MSG_REQS) ?
+ p_lb->custom_handlers[req->subtype] :
+ pipeline_msg_req_invalid_handler;
+
+ if (f_handle == NULL)
+ f_handle = pipeline_msg_req_invalid_handler;
+
+ return f_handle(p, req);
+}
+
+uint32_t lb_pkt_print_count;
+
+uint8_t calculate_lb_thread_prv(struct rte_mbuf *pkt, void *arg)
+{
+ uint32_t hash_key[2], hash_ipv4;
+ uint32_t temp1, temp2, temp3;
+ uint8_t thread;
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *) ap->p;
+ uint8_t nthreads = p_loadb->n_vnf_threads;
+ union rte_thash_tuple tuple;
+
+ uint32_t *src_addr;
+ uint32_t *dst_addr;
+ uint16_t *src_port;
+ uint16_t *dst_port;
+ uint8_t *protocol;
+ struct lb_pkt *lb_pkt = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6) {
+ src_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.src_addr;
+ dst_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.dst_addr;
+ src_port = &lb_pkt->ipv6_port.src_port;
+ dst_port = &lb_pkt->ipv6_port.dst_port;
+ protocol = &lb_pkt->ipv6_port.ipv6.proto;
+ } else {
+ src_addr = &lb_pkt->ipv4_port.ipv4.src_addr;
+ dst_addr = &lb_pkt->ipv4_port.ipv4.dst_addr;
+ src_port = &lb_pkt->ipv4_port.src_port;
+ dst_port = &lb_pkt->ipv4_port.dst_port;
+ protocol = &lb_pkt->ipv4_port.ipv4.next_proto_id;
+ }
+
+ switch (p_loadb->n_lb_tuples) {
+
+ case 0:
+ /* Write */
+ /* Egress */
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6)
+ temp1 = rte_bswap32(dst_addr[3]) ^ *dst_port;
+ else
+ temp1 = *dst_addr ^ *dst_port;
+
+ temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
+ (temp1 >> 8) ^ temp1;
+
+ temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
+
+ /* To select the thread */
+ thread = temp3 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+ return thread;
+
+ case 1:
+ /* Write */
+ /* Egress */
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6)
+ hash_key[0] = rte_bswap32(dst_addr[3]);
+ else
+ hash_key[0] = rte_bswap32(*dst_addr);
+
+ /* Compute */
+ hash_ipv4 = rte_jhash(&hash_key[0], 4, 0);
+
+ /* To select the thread */
+ thread = (hash_ipv4 % nthreads);
+
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3)
+ printf("thread: %u hash: %x hash_key: %x\n",
+ thread, hash_ipv4, hash_key[0]);
+ return thread;
+
+ case 2:
+ /* Write */
+ /* Egress */
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
+ ETHER_TYPE_IPv6) {
+ hash_key[0] = rte_bswap32(dst_addr[3]);
+ hash_key[1] = *dst_port << 16;
+ } else{
+ hash_key[0] = rte_bswap32(*dst_addr);
+ hash_key[1] = *dst_port << 16;
+ }
+ /* Compute */
+ hash_ipv4 = rte_jhash(&hash_key[0], 6, 0);
+
+ /* To select the thread */
+ thread = (hash_ipv4 % nthreads);
+
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("public_addr: %x public_port: %x\n",
+ hash_key[0], *dst_port);
+ printf("thread: %u hash: %x hash_key0: %x "
+ "hash_key1: %x\n", thread, hash_ipv4,
+ hash_key[0], hash_key[1]);
+ }
+ return thread;
+
+ case 3:
+ printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
+ return 0;
+
+ case 4:
+ /* Write */
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
+ ETHER_TYPE_IPv6) {
+ tuple.v4.src_addr = rte_bswap32(src_addr[3]);
+ tuple.v4.dst_addr = rte_bswap32(dst_addr[3]);
+ tuple.v4.sport = *src_port;
+ tuple.v4.dport = *dst_port;
+ } else{
+ tuple.v4.src_addr = rte_bswap32(*src_addr);
+ tuple.v4.dst_addr = rte_bswap32(*dst_addr);
+ tuple.v4.sport = *src_port;
+ tuple.v4.dport = *dst_port;
+ }
+ /* Compute */
+ hash_ipv4 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V4_L4_LEN,
+ default_rss_key);
+ /* Egress */
+
+ /* To select the thread */
+ thread = (hash_ipv4 % nthreads);
+
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("src_addr: %x dst_addr: %x src_port: %x "
+ "dst_port: %x\n", tuple.v4.src_addr, tuple.v4.dst_addr,
+ tuple.v4.sport, tuple.v4.dport);
+ printf("thread: %u hash: %x\n", thread, hash_ipv4);
+ }
+
+ return thread;
+
+ case 5:
+
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
+ ETHER_TYPE_IPv6) {
+ /* point to last 32 bits of IPv6 addresses*/
+ src_addr += 3;
+ dst_addr += 3;
+ }
+
+ /* Compute */
+ temp1 = *src_addr ^ *dst_addr ^ *src_port ^
+ *dst_port ^ *protocol;
+
+ temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^ (temp1 >> 8) ^ temp1;
+ temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
+
+ /* Egress */
+
+ /* To select the thread */
+ thread = (temp3 % nthreads);
+
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("thread: %u temp1: %x temp2: %x temp3: %x\n",
+ thread, temp1, temp2, temp3);
+ printf("src_addr: %x dst_addr: %x src_port: %x "
+ "dst_port: %x protocol: %x\n", *src_addr, *dst_addr,
+ *src_port, *dst_port, *protocol);
+ }
+ return thread;
+
+ default:
+ printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
+ return 0;
+
+ }
+}
+
+uint8_t calculate_lb_thread_pub(struct rte_mbuf *pkt, void *arg)
+{
+ uint32_t hash_key[2], hash_ipv4;
+ uint32_t temp1, temp2, temp3;
+ uint8_t thread;
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *) ap->p;
+ uint8_t nthreads = p_loadb->n_vnf_threads;
+ union rte_thash_tuple tuple;
+
+ uint32_t *src_addr;
+ uint32_t *dst_addr;
+ uint16_t *src_port;
+ uint16_t *dst_port;
+ uint8_t *protocol;
+ struct lb_pkt *lb_pkt = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ MBUF_HDR_ROOM);
+
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6) {
+ src_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.src_addr;
+ dst_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.dst_addr;
+ src_port = &lb_pkt->ipv6_port.src_port;
+ dst_port = &lb_pkt->ipv6_port.dst_port;
+ protocol = &lb_pkt->ipv6_port.ipv6.proto;
+ } else {
+ src_addr = &lb_pkt->ipv4_port.ipv4.src_addr;
+ dst_addr = &lb_pkt->ipv4_port.ipv4.dst_addr;
+ src_port = &lb_pkt->ipv4_port.src_port;
+ dst_port = &lb_pkt->ipv4_port.dst_port;
+ protocol = &lb_pkt->ipv4_port.ipv4.next_proto_id;
+ }
+
+ switch (p_loadb->n_lb_tuples) {
+
+ case 0:
+ /* Write */
+ /* Ingress */
+ temp1 = *src_addr ^ *src_port;
+ temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
+ (temp1 >> 8) ^ temp1;
+ temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
+
+ /* To select the thread */
+ thread = temp3 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ return thread;
+
+ case 1:
+ /* Write */
+ /* Ingress */
+ hash_key[0] = rte_bswap32(*src_addr);
+
+ /* Compute */
+ hash_ipv4 = rte_jhash(&hash_key[0], 4, 0);
+
+ /* To select the thread */
+ thread = hash_ipv4 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3)
+ printf("thread: %u hash: %x hash_key: %x\n",
+ thread, hash_ipv4, hash_key[0]);
+ return thread;
+
+ case 2:
+ /* Write */
+ /* Ingress */
+ hash_key[0] = rte_bswap32(*src_addr);
+ hash_key[1] = *src_port << 16;
+
+ /* Compute */
+ hash_ipv4 = rte_jhash(&hash_key[0], 6, 0);
+
+ /* To select the thread */
+ thread = hash_ipv4 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("thread: %u hash: %x hash_key0: %x "
+ "hash_key1: %x\n", thread, hash_ipv4,
+ hash_key[0], hash_key[1]);
+ printf("public_addr: %x public_port: %x\n",
+ hash_key[0], *src_port);
+ }
+ return thread;
+
+ case 3:
+ printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
+ return 0;
+
+ case 4:
+ /* Write */
+ tuple.v4.src_addr = rte_bswap32(*src_addr);
+ tuple.v4.dst_addr = rte_bswap32(*dst_addr);
+ tuple.v4.sport = *src_port;
+ tuple.v4.dport = *dst_port;
+
+ /* Compute */
+ hash_ipv4 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V4_L4_LEN, default_rss_key);
+
+ /* Ingress */
+ /* To select the thread */
+ thread = hash_ipv4 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("src_addr: %x dst_addr: %x src_port: %x "
+ "dst_port: %x\n", tuple.v4.src_addr,
+ tuple.v4.dst_addr, tuple.v4.sport, tuple.v4.dport);
+
+ printf("thread: %u hash: %x\n", thread, hash_ipv4);
+ }
+ return thread;
+
+ case 5:
+
+ if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
+ ETHER_TYPE_IPv6) {
+ /* point to last 32 bits of IPv6 addresses*/
+ src_addr += 3;
+ dst_addr += 3;
+ }
+
+ /* Compute */
+ temp1 = *src_addr ^ *dst_addr ^ *src_port ^
+ *dst_port ^ *protocol;
+ temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
+ (temp1 >> 8) ^ temp1;
+ temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
+
+ /* To select the thread */
+ thread = temp3 % nthreads;
+ /* To select the Q */
+ thread = ap->in_port_id + (p_loadb->p.n_ports_in *
+ (thread + 1) - p_loadb->p.n_ports_in);
+
+ if (LOADB_DEBUG > 3) {
+ printf("src_addr: %x dst_addr: %x src_port: %x "
+ "dst_port: %x protocol: %x\n", *src_addr, *dst_addr,
+ *src_port, *dst_port, *protocol);
+
+ printf("thread: %u temp1: %x temp2: %x temp3: %x\n",
+ thread, temp1, temp2, temp3);
+ }
+
+ return thread;
+
+ default:
+ printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
+ return 0;
+
+ }
+}
+
+static inline void
+pkt_work_loadb_key_prv(
+ struct rte_mbuf *pkt,
+ __rte_unused uint32_t pkt_num,
+ void *arg)
+{
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
+ uint32_t outport_offset = p_loadb->outport_offset;
+
+ struct lb_pkt *lb_pkt = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ MBUF_HDR_ROOM);
+ uint32_t *out_port = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ outport_offset);
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("Start pkt_work_loadb_key\n");
+ #endif
+
+ if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
+ print_pkt1(pkt);
+ lb_pkt_print_count++;
+ printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
+ "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
+ rte_be_to_cpu_16(lb_pkt->eth.ether_type),
+ lb_pkt->ipv4_port.ipv4.next_proto_id, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ /* Write */
+ *out_port = calculate_lb_thread_prv(pkt, arg);
+
+ p_loadb->receivedLBPktCount++;
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("End pkt_work_loadb_key\n");
+ #endif
+}
+
+static inline void
+pkt_work_loadb_key_pub(
+ struct rte_mbuf *pkt,
+ __rte_unused uint32_t pkt_num,
+ void *arg)
+{
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
+ uint32_t outport_offset = p_loadb->outport_offset;
+
+ struct lb_pkt *lb_pkt = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt,
+ MBUF_HDR_ROOM);
+ uint32_t *out_port = RTE_MBUF_METADATA_UINT32_PTR(pkt,
+ outport_offset);
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("Start pkt_work_loadb_key\n");
+ #endif
+
+ if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
+ print_pkt1(pkt);
+ lb_pkt_print_count++;
+ printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
+ "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
+ rte_be_to_cpu_16(lb_pkt->eth.ether_type),
+ lb_pkt->ipv4_port.ipv4.next_proto_id, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ /* Write */
+ *out_port = calculate_lb_thread_pub(pkt, arg);
+
+ p_loadb->receivedLBPktCount++;
+#ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("End pkt_work_loadb_key\n");
+#endif
+}
+
+static inline void
+pkt4_work_loadb_key_prv(
+ struct rte_mbuf **pkt,
+ __rte_unused uint32_t pkt_num,
+ void *arg)
+{
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
+ uint32_t outport_offset = p_loadb->outport_offset;
+
+ uint32_t *out_port0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
+ outport_offset);
+ uint32_t *out_port1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
+ outport_offset);
+ uint32_t *out_port2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
+ outport_offset);
+ uint32_t *out_port3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
+ outport_offset);
+
+ struct lb_pkt *lb_pkt0 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt1 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt2 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt3 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
+ MBUF_HDR_ROOM);
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("Start pkt4_work_loadb_key\n");
+ #endif
+
+ if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
+ print_pkt1(pkt[0]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt0->eth.ether_type),
+ lb_pkt0->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[1]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt1->eth.ether_type),
+ lb_pkt1->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[2]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt2->eth.ether_type),
+ lb_pkt2->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[3]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt3->eth.ether_type),
+ lb_pkt3->ipv4_port.ipv4.next_proto_id);
+ }
+ *out_port0 = calculate_lb_thread_prv(pkt[0], arg);
+ *out_port1 = calculate_lb_thread_prv(pkt[1], arg);
+ *out_port2 = calculate_lb_thread_prv(pkt[2], arg);
+ *out_port3 = calculate_lb_thread_prv(pkt[3], arg);
+
+ p_loadb->receivedLBPktCount += 4;
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("End pkt4_work_loadb_key\n");
+ #endif
+
+}
+
+static inline void
+pkt4_work_loadb_key_pub(
+ struct rte_mbuf **pkt,
+ __rte_unused uint32_t pkt_num,
+ void *arg)
+{
+ struct pipeline_loadb_in_port_h_arg *ap = arg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
+ uint32_t outport_offset = p_loadb->outport_offset;
+
+ uint32_t *out_port0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
+ outport_offset);
+ uint32_t *out_port1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
+ outport_offset);
+ uint32_t *out_port2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
+ outport_offset);
+ uint32_t *out_port3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
+ outport_offset);
+
+ struct lb_pkt *lb_pkt0 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt1 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt2 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
+ MBUF_HDR_ROOM);
+ struct lb_pkt *lb_pkt3 = (struct lb_pkt *)
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
+ MBUF_HDR_ROOM);
+
+ #ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("Start pkt4_work_loadb_key\n");
+ #endif
+
+ if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
+ print_pkt1(pkt[0]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt0->eth.ether_type),
+ lb_pkt0->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[1]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt1->eth.ether_type),
+ lb_pkt1->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[2]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt2->eth.ether_type),
+ lb_pkt2->ipv4_port.ipv4.next_proto_id);
+
+ print_pkt1(pkt[3]);
+ lb_pkt_print_count++;
+
+ printf("\nEth Typ %x, Prot %x\n",
+ rte_be_to_cpu_16(lb_pkt3->eth.ether_type),
+ lb_pkt3->ipv4_port.ipv4.next_proto_id);
+ }
+ *out_port0 = calculate_lb_thread_prv(pkt[0], arg);
+ *out_port1 = calculate_lb_thread_pub(pkt[1], arg);
+ *out_port2 = calculate_lb_thread_pub(pkt[2], arg);
+ *out_port3 = calculate_lb_thread_pub(pkt[3], arg);
+
+ p_loadb->receivedLBPktCount += 4;
+#ifdef MY_LOADB_DBG_PRINT
+ if (LOADB_DEBUG == 3)
+ printf("End pkt4_work_loadb_key\n");
+#endif
+
+}
+
+PIPELINE_LOADB_KEY_PORT_IN_AH(port_in_ah_loadb_key_prv,
+ pkt_work_loadb_key_prv,
+ pkt4_work_loadb_key_prv);
+
+PIPELINE_LOADB_KEY_PORT_IN_AH(port_in_ah_loadb_key_pub,
+ pkt_work_loadb_key_pub,
+ pkt4_work_loadb_key_pub);
+
+static int
+pipeline_loadb_parse_args(struct pipeline_loadb *p,
+ struct pipeline_params *params)
+{
+ uint32_t outport_offset_present = 0;
+ uint32_t n_vnf_threads_present = 0;
+ uint32_t pktq_in_prv_present = 0;
+ uint32_t prv_que_handler_present = 0;
+ uint32_t prv_to_pub_map_present = 0;
+ uint8_t n_prv_in_port = 0;
+ uint32_t i;
+
+ /* Default number of tuples */
+ p->n_lb_tuples = 0;
+
+ if (LOADB_DEBUG > 2)
+ printf("LOADB pipeline_loadb_parse_args params->n_args: %d\n",
+ params->n_args);
+
+ for (i = 0; i < params->n_args; i++) {
+ char *arg_name = params->args_name[i];
+ char *arg_value = params->args_value[i];
+
+ if (LOADB_DEBUG > 2)
+ printf("LOADB args[%d]: %s %d, %s\n", i, arg_name,
+ atoi(arg_value), arg_value);
+
+ /* outport_offset = 128 + 8 */
+ if (strcmp(arg_name, "outport_offset") == 0) {
+ if (outport_offset_present)
+ return -1;
+ outport_offset_present = 1;
+
+ p->outport_offset = atoi(arg_value);
+ if (p->outport_offset <= 0) {
+ printf("Outport_offset is invalid\n");
+ return -1;
+ }
+ printf("outport_offset: 0x%x\n", p->outport_offset);
+ continue;
+ }
+ /* n_vnf_threads = 4 */
+ if (strcmp(arg_name, "n_vnf_threads") == 0) {
+ if (n_vnf_threads_present)
+ return -1;
+ n_vnf_threads_present = 1;
+
+ p->n_vnf_threads = atoi(arg_value);
+
+ total_vnf_threads += p->n_vnf_threads;
+
+ if ((p->n_vnf_threads <= 0)
+ || (total_vnf_threads > MAX_VNF_THREADS)) {
+ printf("n_vnf_threads : MIN->0 MAX->16\n");
+ return -1;
+ }
+ printf("n_vnf_threads : 0x%x\n", p->n_vnf_threads);
+ printf("total_vnf_threads: 0x%x\n", total_vnf_threads);
+ continue;
+ }
+
+ /* pktq_in_prv */
+ if (strcmp(arg_name, "pktq_in_prv") == 0) {
+ if (pktq_in_prv_present) {
+ printf("Duplicate pktq_in_prv ... "
+ "parse failed..\n\n");
+ return -1;
+ }
+ pktq_in_prv_present = 1;
+
+ int rxport = 0, j = 0;
+ char phy_port_num[8];
+ char *token = strtok(arg_value, "RXQ");
+ while (token) {
+ j = 0;
+ while ((j < 7) && (token[j] != '.')) {
+ phy_port_num[j] = token[j];
+ j++;
+ }
+ phy_port_num[j] = '\0';
+ rxport = atoi(phy_port_num);
+ printf("token: %s, phy_port_str: %s, "
+ "phy_port_num %d\n",
+ token, phy_port_num, rxport);
+ prv_in_port_a[n_prv_in_port++] = rxport;
+ // set rxport egress
+ if (rxport < 0xff){
+ if(rxport < PIPELINE_MAX_PORT_IN)
+ in_port_dir_a[rxport] = 1;
+ }
+ token = strtok(NULL, "RXQ");
+ }
+
+ if (n_prv_in_port == 0) {
+ printf("VNF common parse error - "
+ "no prv RX phy port\n");
+ return -1;
+ }
+ continue;
+ }
+
+ /* pktq_in_prv_handler */
+
+ if (strcmp(arg_name, "prv_que_handler") == 0) {
+
+ if (prv_que_handler_present) {
+ printf("Duplicate pktq_in_prv ..\n\n");
+ return -1;
+ }
+ prv_que_handler_present = 1;
+ n_prv_in_port = 0;
+
+ char *token;
+ int rxport = 0;
+ /* get the first token */
+ token = strtok(arg_value, "(");
+ token = strtok(token, ")");
+ token = strtok(token, ",");
+ printf("***** prv_que_handler *****\n");
+ if (token)
+ printf("string is :%s\n", token);
+
+ if (token)
+ //printf("string is null\n");
+ printf("string is :%s\n", token);
+
+ /* walk through other tokens */
+ while (token != NULL) {
+ printf(" %s\n", token);
+ rxport = atoi(token);
+ prv_que_port_index[n_prv_in_port++] = rxport;
+ if (rxport < 0xff){
+ if(rxport < PIPELINE_MAX_PORT_IN)
+ in_port_egress_prv[rxport] = 1;
+ }
+ p->n_prv_Q++;
+ token = strtok(NULL, ",");
+ }
+
+ if (n_prv_in_port == 0) {
+ printf("VNF common parse err - no prv RX phy port\n");
+ return -1;
+ }
+
+ continue;
+ }
+ /* prv_to_pub_map */
+ if (strcmp(arg_name, "prv_to_pub_map") == 0) {
+ if (prv_to_pub_map_present) {
+ printf("Duplicated prv_to_pub_map ... "
+ "parse failed ...\n");
+ return -1;
+ }
+ prv_to_pub_map_present = 1;
+
+ int rxport = 0, txport = 0, j = 0, k = 0;
+ char rx_phy_port_num[5];
+ char tx_phy_port_num[5];
+ char *token = strtok(arg_value, "(");
+ while (token) {
+ j = 0;
+ while ((j < 4) && (token[j] != ',')) {
+ rx_phy_port_num[j] = token[j];
+ j++;
+ }
+ rx_phy_port_num[j] = '\0';
+ rxport = atoi(rx_phy_port_num);
+
+ j++;
+ k = 0;
+ while ((k < 4) && (token[j+k] != ')')) {
+ tx_phy_port_num[k] = token[j+k];
+ k++;
+ }
+ tx_phy_port_num[k] = '\0';
+ txport = atoi(tx_phy_port_num);
+
+ printf("token: %s,rx_phy_port_str: %s, phy_port_num "
+ "%d, tx_phy_port_str: %s, tx_phy_port_num %d\n",
+ token, rx_phy_port_num, rxport,
+ tx_phy_port_num, txport);
+ if(rxport < PIPELINE_MAX_PORT_IN)
+ if ((rxport >= PIPELINE_MAX_PORT_IN) ||
+ (txport >= PIPELINE_MAX_PORT_IN) ||
+ (in_port_dir_a[rxport] != 1)) {
+ printf("CG-NAPT parse error - "
+ "incorrect prv-pub translation. Rx %d, "
+ "Tx %d, Rx Dir %d\n", rxport, txport,
+ in_port_dir_a[rxport]);
+
+ return -1;
+ }
+ if (rxport < 0xff){
+ if (rxport < PIPELINE_MAX_PORT_IN)
+ prv_to_pub_map[rxport] = txport;
+ }
+ if (txport < 0xff)
+ if(txport < PIPELINE_MAX_PORT_IN)
+ pub_to_prv_map[txport] = rxport;
+ token = strtok(NULL, "(");
+ }
+
+ continue;
+ }
+ /* Set number of tuples if available in config file */
+ if (strcmp(arg_name, "n_lb_tuples") == 0) {
+ p->n_lb_tuples = atoi(arg_value);
+ printf("n_lb_tuples: 0x%x\n", p->n_lb_tuples);
+ }
+
+ /* loadb_debug */
+ if (strcmp(arg_name, "loadb_debug") == 0) {
+ LOADB_DEBUG = atoi(arg_value);
+ continue;
+ }
+
+ /* any other Unknown argument return -1 */
+ } /* for */
+
+ /* Check that mandatory arguments are present */
+ if ((n_vnf_threads_present == 0) || (outport_offset_present == 0))
+ return -1;
+
+ return 0;
+
+}
+
+int check_loadb_thread(
+ struct app_params *app,
+ struct pipeline_params *params,
+ int32_t n_vnf_threads)
+{
+ uint32_t i;
+ int pipeline_num = 0;
+ int count = 0;
+ int dont_care = sscanf(params->name, "PIPELINE%d", &pipeline_num);
+ if (dont_care != 1)
+ return -1;
+ /* changed from pipeline_num+1 to +2 */
+ for (i = pipeline_num + 2; i < app->n_pipelines; i++) {
+ struct app_pipeline_params *p = &app->pipeline_params[i];
+ if (!strncmp(p->type, "LOADB", strlen(p->type)))
+ break;
+ count++;
+ }
+ if (n_vnf_threads != count)
+ return -1;
+ return 0;
+
+}
+
+static void *pipeline_loadb_init(
+ struct pipeline_params *params,
+ __rte_unused void *arg)
+ /* arg is app parameter (struct app_params *app) */
+ /*save it for use in port in handler */
+{
+ struct pipeline *p;
+ struct pipeline_loadb *p_loadb;
+ uint32_t size, i, in_ports_arg_size;
+
+ /* Check input arguments */
+ if ((params == NULL) ||
+ (params->n_ports_in == 0) || (params->n_ports_out == 0))
+ return NULL;
+
+ /* Memory allocation */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_loadb));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ p_loadb = (struct pipeline_loadb *)p;
+ if (p == NULL)
+ return NULL;
+
+ strcpy(p->name, params->name);
+ p->log_level = params->log_level;
+
+ PLOG(p, HIGH, "LOADB");
+
+ p_loadb->n_vnf_threads = 0;
+ p_loadb->outport_offset = 0;
+ p_loadb->receivedLBPktCount = 0;
+ p_loadb->droppedLBPktCount = 0;
+ for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
+ p_loadb->links_map[i] = 0xff;
+ }
+ p_loadb->pipeline_num = 0xff;
+ p_loadb->n_prv_Q = 0;
+ p_loadb->n_pub_Q = 0;
+
+ /* Parse arguments */
+
+ if (pipeline_loadb_parse_args(p_loadb, params))
+ return NULL;
+
+ /* Pipeline */
+ {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "LOADB",
+ .socket_id = params->socket_id,
+ .offset_port_id = 0,
+ };
+
+ p->p = rte_pipeline_create(&pipeline_params);
+ if (p->p == NULL) {
+ rte_free(p);
+ return NULL;
+ }
+
+ printf("Loadb p->p %p, socket %d\n", p->p,
+ pipeline_params.socket_id);
+ }
+
+ /* Memory allocation for in_port_h_arg */
+ in_ports_arg_size =
+ RTE_CACHE_LINE_ROUNDUP((sizeof(struct pipeline_loadb_in_port_h_arg))
+ * (params->n_ports_in));
+ struct pipeline_loadb_in_port_h_arg *ap =
+ (struct pipeline_loadb_in_port_h_arg *)
+ rte_zmalloc(NULL,
+ in_ports_arg_size,
+ RTE_CACHE_LINE_SIZE);
+ if (ap == NULL)
+ return NULL;
+
+ printf("ap pointer %p\n", ap);
+
+ /* Input ports */
+ p->n_ports_in = params->n_ports_in;
+ for (i = 0; i < p->n_ports_in; i++) {
+ /* passing our loadb pipeline in call back arg */
+ (ap[i]).p = p_loadb;
+ (ap[i]).in_port_id = i;
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops =
+ pipeline_port_in_params_get_ops(&params->port_in
+ [i]),
+ .arg_create =
+ pipeline_port_in_params_convert(&params->port_in
+ [i]),
+ /* Public in-port handler */
+ .f_action = NULL,
+ .arg_ah = &(ap[i]),
+ .burst_size = params->port_in[i].burst_size,
+ };
+
+ /* Private in-port handler */
+ if (is_port_index_privte(i)) {/* Multiport changes*/
+ printf("LOADB %d port is Prv\n", i);
+ port_params.f_action = port_in_ah_loadb_key_prv;
+ } else{
+ printf("LOADB %d port is Pub\n", i);
+ port_params.f_action = port_in_ah_loadb_key_pub;
+ }
+
+ int status = rte_pipeline_port_in_create(p->p,
+ &port_params,
+ &p->port_in_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ }
+
+ p_loadb->n_pub_Q = p_loadb->p.n_ports_in - p_loadb->n_prv_Q;
+ printf("LOADB : n_prv_Q - %d n_pub_Q - %d\n",
+ p_loadb->n_prv_Q, p_loadb->n_pub_Q);
+
+ for (i = 0; i < p->n_ports_in; i++) {
+ printf("is_port_index_privte(%d): %d\n", i,
+ is_port_index_privte(i));
+ printf("is_phy_port_privte(%d): %d\n", i,
+ is_phy_port_privte(i));
+ printf("action handler of %d:%p\n", i,
+ p_loadb->p.p->ports_in[i].f_action);
+ }
+
+ /* Output ports */
+ p->n_ports_out = params->n_ports_out;
+ for (i = 0; i < p->n_ports_out; i++) {
+ struct rte_pipeline_port_out_params port_params = {
+ .ops =
+ pipeline_port_out_params_get_ops(&params->port_out
+ [i]),
+ .arg_create =
+ pipeline_port_out_params_convert(&params->port_out
+ [i]),
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ int status = rte_pipeline_port_out_create(p->p,
+ &port_params,
+ &p->port_out_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ printf("Outport p->port_out_id[%d] %p\n", i,
+ &p->port_out_id[i]);
+ }
+
+ int pipeline_num = 0;
+ int dont_care = sscanf(params->name, "PIPELINE%d", &pipeline_num);
+ if (dont_care != 1) {
+ printf("Unable to read pipeline number\n");
+ return NULL;
+ }
+ p_loadb->pipeline_num = pipeline_num;
+#if 0
+ set_outport_id(pipeline_num, p, lb_outport_id);
+ set_phy_outport_map(pipeline_num, p_loadb->links_map);
+
+ set_port_to_loadb_map(pipeline_num);
+
+ register_loadb_to_arp(pipeline_num, p, app);
+#endif
+ register_pipeline_Qs(p_loadb->pipeline_num, p);
+ set_link_map(p_loadb->pipeline_num, p, p_loadb->links_map);
+ //set_outport_id(p_loadb->pipeline_num, p, p_loadb->outport_id);
+
+ /* Tables */
+ p->n_tables = 1;
+ {
+
+ struct rte_table_array_params table_array_params = {
+ .n_entries = MAX_VNF_THREADS,
+ .offset = p_loadb->outport_offset,
+ };
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_array_ops,
+ .arg_create = &table_array_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = p_loadb,
+ .action_data_size = 0,
+ };
+
+ int status;
+
+ status = rte_pipeline_table_create(p->p,
+ &table_params,
+ &p->table_id[0]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ } /* Tables */
+
+ /* Connecting input ports to tables */
+ for (i = 0; i < p->n_ports_in; i++) {
+ int status = rte_pipeline_port_in_connect_to_table(
+ p->p,
+ p->port_in_id[i],
+ p->table_id[0]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < p->n_ports_in; i++) {
+ int status = rte_pipeline_port_in_enable(p->p,
+ p->port_in_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Initialize table entries */
+ {
+ for (i = 0; i < MAX_VNF_THREADS; i++) {
+ struct rte_table_array_key key = {
+ .pos = i,
+ };
+ struct loadb_table_entry entry;
+ entry.head.action = RTE_PIPELINE_ACTION_PORT;
+
+ if (i < p->n_ports_out) {
+ entry.head.port_id = p->port_out_id[i];
+ printf("\ni %d, p->port_out_id[%d] %d", i, i,
+ p->port_out_id[i]);
+ } else {
+ /* First CGNAPT thread */
+ entry.head.port_id = p->port_out_id[0];
+ entry.head.action = RTE_PIPELINE_ACTION_DROP;
+ }
+
+ struct rte_pipeline_table_entry *entry_ptr;
+ int key_found, status;
+ status = rte_pipeline_table_entry_add(
+ p->p,
+ p->table_id[0],
+ &key,
+ (struct rte_pipeline_table_entry *)
+ &entry,
+ &key_found,
+ &entry_ptr);
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+ }
+ /* Add default entry to tables */
+ {
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ /* LB by default forward to 1st cgnat thread */
+ .port_id = p->port_out_id[0],
+ };
+
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ int status = rte_pipeline_table_default_entry_add(
+ p->p,
+ p->table_id[0],
+ &default_entry,
+ &default_entry_ptr);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ }
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p->p) < 0) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+
+ /* Message queues */
+ p->n_msgq = params->n_msgq;
+ for (i = 0; i < p->n_msgq; i++)
+ p->msgq_in[i] = params->msgq_in[i];
+ for (i = 0; i < p->n_msgq; i++)
+ p->msgq_out[i] = params->msgq_out[i];
+
+ /* Message handlers */
+ memcpy(p->handlers, handlers, sizeof(p->handlers));
+ memcpy(p_loadb->custom_handlers,
+ custom_handlers, sizeof(p_loadb->custom_handlers));
+
+ return p;
+}
+
+static int pipeline_loadb_free(void *pipeline)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ /* Check input arguments */
+ if (p == NULL)
+ return -1;
+
+ /* Free resources */
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return 0;
+}
+
+static int
+pipeline_loadb_track(void *pipeline,
+ __rte_unused uint32_t port_in, uint32_t *port_out)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ /* Check input arguments */
+ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
+ return -1;
+
+ if (p->n_ports_in == 1) {
+ *port_out = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int pipeline_loadb_timer(void *pipeline)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ pipeline_msg_req_handle(p);
+ rte_pipeline_flush(p->p);
+
+ return 0;
+}
+
+void *pipeline_loadb_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_loadb_entry_dbg_msg_rsp *rsp = msg;
+ uint8_t *Msg = msg;
+ struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)p;
+
+ rsp->status = 0;
+
+ printf("LoadB debug handler called with args %x %x, offset %d\n",
+ Msg[LOADB_DBG_CMD_OFST], Msg[LOADB_DBG_CMD_OFST + 1],
+ LOADB_DBG_CMD_OFST);
+
+ if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_STATS_SHOW) {
+ printf("\nLoadB Packet Stats: Received %" PRIu64 "\n",
+ p_loadb->receivedLBPktCount);
+ return rsp;
+ }
+ if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_STATS_CLEAR) {
+ printf("\nLoadB Packet Stats: Received %" PRIu64 "\n",
+ p_loadb->receivedLBPktCount);
+ p_loadb->receivedLBPktCount = 0;
+ return rsp;
+ }
+
+ if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_DBG_LEVEL) {
+ LOADB_DEBUG = Msg[LOADB_DBG_CMD_OFST + 1];
+ printf("LOADB Debug level set to %d\n", LOADB_DEBUG);
+ lb_pkt_print_count = 0;
+ return rsp;
+ }
+ if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_DBG_SHOW) {
+ printf("\nLoadB DBG Level: %u\n", LOADB_DEBUG);
+ return rsp;
+ }
+ if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_IF_STATS) {
+ printf("\n");
+ uint8_t i, j;
+
+ for (i = 0; i < p->n_ports_in; i++) {
+ struct rte_eth_stats stats;
+ rte_eth_stats_get(p_loadb->links_map[i], &stats);
+ if (is_phy_port_privte(i))
+ printf("Private Port Stats %d\n", i);
+ else
+ printf("Public Port Stats %d\n", i);
+ printf("\n\tipackets : %" PRIu64 "\n\topackets : %"
+ PRIu64 "\n\tierrors : %" PRIu64
+ "\n\toerrors : %" PRIu64 "\n\trx_nombuf: %"
+ PRIu64 "\n", stats.ipackets, stats.opackets,
+ stats.ierrors, stats.oerrors, stats.rx_nombuf);
+ if (is_phy_port_privte(i))
+ printf("Private Q: ");
+ else
+ printf("Public Q: ");
+ for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS; j++)
+ printf(" %" PRIu64 ", %" PRIu64 "|",
+ stats.q_ipackets[j],
+ stats.q_opackets[j]);
+
+ printf("\n\n");
+
+ }
+ return rsp;
+ }
+
+ return rsp;
+
+}
+
+struct pipeline_be_ops pipeline_loadb_be_ops = {
+ .f_init = pipeline_loadb_init,
+ .f_free = pipeline_loadb_free,
+ .f_run = NULL,
+ .f_timer = pipeline_loadb_timer,
+ .f_track = pipeline_loadb_track,
+};
diff --git a/common/VIL/pipeline_loadb/pipeline_loadb_be.h b/common/VIL/pipeline_loadb/pipeline_loadb_be.h
new file mode 100644
index 00000000..a948f4cb
--- /dev/null
+++ b/common/VIL/pipeline_loadb/pipeline_loadb_be.h
@@ -0,0 +1,149 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef __INCLUDE_PIPELINE_LOADB_BE_H__
+#define __INCLUDE_PIPELINE_LOADB_BE_H__
+
+#include <rte_ip.h>
+#include "pipeline_common_be.h"
+#include <app.h>
+
+#define MBUF_HDR_ROOM 256
+#define ETH_HDR_SIZE 14
+#define IP_HDR_SRC_ADR_OFST 12
+#define IP_HDR_DST_ADR_OFST 16
+#define IP_HDR_PROTOCOL_OFST 9
+#define IP_HDR_SIZE 20
+#define IPV6_HDR_SRC_ADR_OFST 8
+#define IPV6_HDR_DST_ADR_OFST 24
+#define IPV6_HDR_PROTOCOL_OFST 6
+#define IPV6_HDR_SIZE 40
+#define IP_PROTOCOL_TCP 6
+#define IP_PROTOCOL_UDP 17
+#define PIPELINE_LOADB_KEY_MAX_SIZE 64
+
+#define LOADB_ING_DIR 0
+#define LOADB_EGR_DIR 1
+
+#define LOADB_DBG_CMD_OFST 8
+#define LOADB_DBG_CMD_STATS_SHOW 0
+#define LOADB_DBG_CMD_STATS_CLEAR 1
+#define LOADB_DBG_CMD_DBG_LEVEL 2
+#define LOADB_DBG_CMD_DBG_SHOW 3
+#define LOADB_DBG_CMD_IF_STATS 4
+#define LOADB_DBG_CMD_OFST1 10
+
+#define PIPELINE_LOADB_KEY_PORT_IN_AH(f_ah, f_pkt_work, f_pkt4_work) \
+static int \
+f_ah( \
+ __rte_unused struct rte_pipeline *rte_p, \
+ struct rte_mbuf **pkts, \
+ uint32_t n_pkts, \
+ void *arg) \
+{ \
+ uint32_t i, j; \
+ \
+ for (j = 0; j < n_pkts; j++) \
+ rte_prefetch0(pkts[j]); \
+ pkt_burst_cnt = 0; \
+ for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \
+ f_pkt4_work(&pkts[i], i, arg); \
+ \
+ for ( ; i < n_pkts; i++) \
+ f_pkt_work(pkts[i], i, arg); \
+ \
+ \
+ return 0; \
+}
+
+extern uint8_t LOADB_DEBUG;
+extern uint8_t in_port_egress_prv[PIPELINE_MAX_PORT_IN];
+extern uint8_t prv_que_port_index[PIPELINE_MAX_PORT_IN];
+extern uint8_t in_port_dir_a[PIPELINE_MAX_PORT_IN];
+
+extern uint8_t get_in_port_dir(uint8_t);
+extern uint8_t is_port_index_privte(uint16_t);
+extern uint8_t is_phy_port_privte(uint16_t);
+extern uint32_t get_prv_to_pub_port(uint32_t *ip_addr, uint8_t type);
+extern uint32_t get_pub_to_prv_port(uint32_t *ip_addr, uint8_t type);
+extern uint8_t prv_to_pub_map[PIPELINE_MAX_PORT_IN];
+//extern struct app_params *myApp;
+//extern struct pipeline_arpicmp *p_arp;
+
+/*
+ * LOADB Entry
+ */
+
+struct pipeline_loadb_in_port_h_arg {
+ struct pipeline_loadb *p;
+ uint8_t in_port_id;
+};
+
+/*
+ * Messages
+ */
+enum pipeline_loadb_msg_req_type {
+ /* to be used for debug purposes */
+ PIPELINE_LOADB_MSG_REQ_ENTRY_DBG,
+ PIPELINE_LOADB_MSG_REQS
+};
+
+/*
+ * MSG ENTRY DBG
+ */
+struct pipeline_loadb_entry_dbg_msg_req {
+ enum pipeline_msg_req_type type;
+ enum pipeline_loadb_msg_req_type subtype;
+
+ /* data */
+ uint8_t data[5];
+};
+
+struct pipeline_loadb_entry_dbg_msg_rsp {
+ int status;
+ void *entry_ptr;
+};
+
+extern struct pipeline_be_ops pipeline_loadb_be_ops;
+struct ipv4_hdr_port {
+ struct ipv4_hdr ipv4;
+ uint16_t src_port;
+ uint16_t dst_port;
+
+} __attribute__((__packed__));
+struct ipv6_hdr_port {
+ struct ipv6_hdr ipv6;
+ uint16_t src_port;
+ uint16_t dst_port;
+
+} __attribute__((__packed__));
+
+struct lb_pkt {
+ struct ether_hdr eth;
+ union{
+ struct ipv4_hdr_port ipv4_port;
+ struct ipv6_hdr_port ipv6_port;
+ };
+} __attribute__((__packed__));
+
+uint8_t calculate_lb_thread_prv(struct rte_mbuf *pkt, void *arg);
+uint8_t calculate_lb_thread_pub(struct rte_mbuf *pkt, void *arg);
+int check_loadb_thread(
+ struct app_params *app,
+ struct pipeline_params *params,
+ int32_t n_vnf_threads);
+
+#endif