diff options
Diffstat (limited to 'common/VIL/pipeline_loadb')
-rw-r--r-- | common/VIL/pipeline_loadb/pipeline_loadb.c | 493 | ||||
-rw-r--r-- | common/VIL/pipeline_loadb/pipeline_loadb.h | 29 | ||||
-rw-r--r-- | common/VIL/pipeline_loadb/pipeline_loadb_be.c | 1417 | ||||
-rw-r--r-- | common/VIL/pipeline_loadb/pipeline_loadb_be.h | 149 |
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(¶ms->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(¶ms->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(¶ms->port_in + [i]), + .arg_create = + pipeline_port_in_params_convert(¶ms->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(¶ms->port_out + [i]), + .arg_create = + pipeline_port_out_params_convert(¶ms->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 |