summaryrefslogtreecommitdiffstats
path: root/common/VIL/pipeline_txrx
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/pipeline_txrx')
-rw-r--r--common/VIL/pipeline_txrx/pipeline_txrx.c151
-rw-r--r--common/VIL/pipeline_txrx/pipeline_txrx.h28
-rw-r--r--common/VIL/pipeline_txrx/pipeline_txrx_be.c915
-rw-r--r--common/VIL/pipeline_txrx/pipeline_txrx_be.h76
4 files changed, 1170 insertions, 0 deletions
diff --git a/common/VIL/pipeline_txrx/pipeline_txrx.c b/common/VIL/pipeline_txrx/pipeline_txrx.c
new file mode 100644
index 00000000..c1fc075f
--- /dev/null
+++ b/common/VIL/pipeline_txrx/pipeline_txrx.c
@@ -0,0 +1,151 @@
+/*
+// 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_txrx.h"
+#include "vnf_common.h"
+//#include "lib_arp.h"
+#include "pipeline_arpicmp_be.h"
+
+static int
+app_pipeline_txrx_entry_dbg(struct app_params *app,
+ uint32_t pipeline_id, uint8_t *msg)
+{
+ struct pipeline_txrx_entry_dbg_msg_req *req;
+ struct pipeline_txrx_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_TXRX_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_txrx_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, "txrx");
+
+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 = "TXRX 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 cmdline_parse_ctx_t pipeline_cmds[] = {
+ (cmdline_parse_inst_t *) &lb_cmd_entry_dbg,
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_txrx_fe_ops = {
+ .f_init = NULL,
+ .f_free = NULL,
+ .cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_txrx = {
+ .name = "TXRX",
+ .be_ops = &pipeline_txrx_be_ops,
+ .fe_ops = &pipeline_txrx_fe_ops,
+};
diff --git a/common/VIL/pipeline_txrx/pipeline_txrx.h b/common/VIL/pipeline_txrx/pipeline_txrx.h
new file mode 100644
index 00000000..99069246
--- /dev/null
+++ b/common/VIL/pipeline_txrx/pipeline_txrx.h
@@ -0,0 +1,28 @@
+/*
+// 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_TXRX_H__
+#define __INCLUDE_PIPELINE_TXRX_H__
+
+#include "pipeline.h"
+#include "pipeline_txrx_be.h"
+
+/*
+ * Pipeline type
+ */
+extern struct pipeline_type pipeline_txrx;
+
+#endif
diff --git a/common/VIL/pipeline_txrx/pipeline_txrx_be.c b/common/VIL/pipeline_txrx/pipeline_txrx_be.c
new file mode 100644
index 00000000..9e7645dd
--- /dev/null
+++ b/common/VIL/pipeline_txrx/pipeline_txrx_be.c
@@ -0,0 +1,915 @@
+/*
+// 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 <string.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_byteorder.h>
+#include <rte_table_stub.h>
+#include <rte_table_hash.h>
+#include <rte_pipeline.h>
+
+#include "pipeline_txrx_be.h"
+#include "pipeline_actions_common.h"
+#include "parser.h"
+#include "hash_func.h"
+#include "pipeline_arpicmp_be.h"
+#include "vnf_common.h"
+#include "app.h"
+#ifndef VNF_ACL
+#include "lib_icmpv6.h"
+#endif
+
+uint8_t TXRX_DEBUG;
+int pkt_burst_cnt;
+
+struct pipeline_txrx {
+ struct pipeline p;
+ pipeline_msg_req_handler
+ custom_handlers[PIPELINE_TXRX_MSG_REQS];
+ uint64_t receivedPktCount;
+ uint64_t droppedPktCount;
+ uint8_t links_map[PIPELINE_MAX_PORT_IN];
+ uint8_t outport_id[PIPELINE_MAX_PORT_IN];
+ uint8_t pipeline_num;
+ uint8_t txrx_type;
+} __rte_cache_aligned;
+
+enum{
+TYPE_TXTX,
+TYPE_RXRX,
+};
+static void *pipeline_txrx_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_txrx_msg_req_custom_handler,
+
+};
+
+static void *pipeline_txrx_msg_req_entry_dbg_handler(struct pipeline *p,
+ void *msg);
+static void *pipeline_txrx_msg_req_entry_dbg_handler(
+ __rte_unused struct pipeline *p,
+ __rte_unused void *msg)
+{
+ /*have to handle dbg commands*/
+ return NULL;
+}
+
+static __rte_unused pipeline_msg_req_handler custom_handlers[] = {
+ [PIPELINE_TXRX_MSG_REQ_ENTRY_DBG] =
+ pipeline_txrx_msg_req_entry_dbg_handler,
+};
+
+/**
+ * Function for pipeline custom handlers
+ *
+ * @param pipeline
+ * A void pointer to pipeline
+ * @param msg
+ * void pointer for incoming data
+ *
+ * @return
+ * void pointer of response
+ */
+void *pipeline_txrx_msg_req_custom_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)p;
+ struct pipeline_custom_msg_req *req = msg;
+ pipeline_msg_req_handler f_handle;
+
+ f_handle = (req->subtype < PIPELINE_TXRX_MSG_REQS) ?
+ p_txrx->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);
+}
+
+/* Not needed as no arguments are needed for TxRX
+ * ARP arguments are handled in ARP module
+ */
+int
+pipeline_txrx_parse_args(struct pipeline_txrx *p,
+ struct pipeline_params *params);
+int
+pipeline_txrx_parse_args(struct pipeline_txrx *p,
+ struct pipeline_params *params)
+{
+ uint32_t i;
+ uint8_t txrx_type_present = 0;
+
+ if (TXRX_DEBUG > 2)
+ printf("TXRX pipeline_txrx_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 (TXRX_DEBUG > 2)
+ printf("TXRX args[%d]: %s %d, %s\n", i, arg_name,
+ atoi(arg_value), arg_value);
+
+ /* txrx_type = val */
+ if (strcmp(arg_name, "pipeline_txrx_type") == 0) {
+ if (txrx_type_present)
+ return -1;
+ txrx_type_present = 1;
+
+
+ if (strcmp(arg_value, "TXTX") == 0) {
+ p->txrx_type = TYPE_TXTX;
+ printf("pipeline_txrx_type is TXTX\n");
+ }
+ if (strcmp(arg_value, "RXRX") == 0) {
+ p->txrx_type = TYPE_RXRX;
+ printf("pipeline_txrx_type is RXRX\n");
+ }
+ continue;
+ }
+ }
+
+ if (!txrx_type_present) {
+ printf("TXRX type not specified\n");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+uint32_t txrx_pkt_print_count;
+static inline void
+pkt_work_txrx(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
+{
+
+ struct pipeline_txrx_in_port_h_arg *ap = arg;
+ struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)ap->p;
+ uint8_t solicited_node_multicast_addr[16] =
+ {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
+
+ p_txrx->receivedPktCount++;
+
+ if (p_txrx->txrx_type == TYPE_TXTX)
+ return;
+
+ uint8_t in_port_id = pkt->port;
+ uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
+
+ uint32_t pkt_mask = 1 << pkt_num;
+ /* ARP outport number */
+ uint32_t out_port = p_txrx->p.n_ports_out - 1;
+
+ uint16_t *eth_proto =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
+
+ uint8_t *protocol;
+ uint32_t prot_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
+
+ #ifdef IPV6
+ struct ipv6_hdr *ipv6_h;
+ ipv6_h = rte_pktmbuf_mtod_offset (pkt, struct ipv6_hdr *, sizeof(struct ether_hdr));
+ uint32_t prot_offset_ipv6 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
+
+ if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6)
+ protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset_ipv6);
+ else
+ protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
+ #else
+ protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
+ #endif
+
+
+ if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
+ print_pkt1(pkt);
+ txrx_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(*eth_proto), *protocol, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+ /* Classifier for ICMP pass-through*/
+ struct app_link_params *link;
+
+ link = &myApp->link_params[in_port_id];
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
+
+ if (TXRX_DEBUG > 2)
+ if (rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
+ printf ("%s: linkIp: %x, dst_addr: %x\n", __FUNCTION__, link->ip, *dst_addr);
+
+ #if 1
+ switch (rte_be_to_cpu_16(*eth_proto)) {
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
+ break;
+
+ case ETH_TYPE_IPV4:
+ if ((*protocol == IP_PROTOCOL_ICMP) &&
+ (link->ip == rte_be_to_cpu_32(*dst_addr))) {
+ if (is_phy_port_privte(pkt->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_txrx->p.p,
+ out_port, pkt);
+ rte_pipeline_ah_packet_drop(
+ p_txrx->p.p,
+ pkt_mask);
+ }
+ }
+
+ break;
+
+ #ifdef IPV6
+ case ETH_TYPE_IPV6:
+ if (*protocol == ICMPV6_PROTOCOL_ID) {
+ #ifndef VNF_ACL
+ if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
+ || !memcmp(ipv6_h->dst_addr, solicited_node_multicast_addr, 13)) {
+ #endif
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
+ #ifndef VNF_ACL
+ } else {
+ printf("Dropping the IPv6 pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
+ }
+ #endif
+ }
+ break;
+ #endif
+
+ default: /* Not valid pkt */
+ printf("Dropping the pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
+
+ }
+ #endif
+
+}
+
+static inline void
+pkt4_work_txrx(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
+{
+ struct pipeline_txrx_in_port_h_arg *ap = arg;
+ struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)ap->p;
+ uint8_t solicited_node_multicast_addr[16] =
+ {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
+
+ if (p_txrx->txrx_type == TYPE_TXTX)
+ return;
+
+ uint16_t in_port_id = (*pkt)->port;
+ uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
+
+
+ uint32_t pkt_mask0 = 1 << pkt_num;
+ uint32_t pkt_mask1 = 1 << (pkt_num + 1);
+ uint32_t pkt_mask2 = 1 << (pkt_num + 2);
+ uint32_t pkt_mask3 = 1 << (pkt_num + 3);
+
+ /* ARP outport number */
+ uint32_t out_port = p_txrx->p.n_ports_out - 1;
+
+ uint16_t *eth_proto0 =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
+ uint16_t *eth_proto1 =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
+ uint16_t *eth_proto2 =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
+ uint16_t *eth_proto3 =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
+
+ uint8_t *protocol0, *protocol1, *protocol2, *protocol3;
+ uint32_t prot_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
+
+ #ifdef IPV6
+ struct ipv6_hdr *ipv6_h0, *ipv6_h1, *ipv6_h2, *ipv6_h3;
+ ipv6_h0 = rte_pktmbuf_mtod_offset (pkt[0], struct ipv6_hdr *, sizeof(struct ether_hdr));
+ uint32_t prot_offset_ipv6 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
+
+/* --0-- */
+ if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
+ protocol0 =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
+ else
+ protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
+
+/* --1-- */
+ ipv6_h1 = rte_pktmbuf_mtod_offset (pkt[1], struct ipv6_hdr *, sizeof(struct ether_hdr));
+ if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
+ protocol1 =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
+ else
+ protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
+
+/* --2-- */
+ ipv6_h2 = rte_pktmbuf_mtod_offset (pkt[2], struct ipv6_hdr *, sizeof(struct ether_hdr));
+ if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
+ protocol2 =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
+ else
+ protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
+
+/* --3-- */
+ ipv6_h3 = rte_pktmbuf_mtod_offset (pkt[3], struct ipv6_hdr *, sizeof(struct ether_hdr));
+ if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
+ protocol3 =
+ RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
+ else
+ protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
+ #else
+ protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
+ protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
+ protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
+ protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
+ #endif
+
+ if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
+ print_pkt1(pkt[0]);
+ txrx_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(*eth_proto0), *protocol0, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ struct app_link_params *link;
+
+ link = &myApp->link_params[in_port_id];
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ uint32_t dst_addr_offset0 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr0 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset0);
+
+ if (TXRX_DEBUG > 2)
+ if (rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
+ printf ("%s: linkIp: %x, dst_addr0: %x\n", __FUNCTION__, link->ip, *dst_addr0);
+
+ #if 1
+ switch (rte_be_to_cpu_16(*eth_proto0)) {
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[0]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
+ break;
+
+ case ETH_TYPE_IPV4:
+ if ((*protocol0 == IP_PROTOCOL_ICMP) &&
+ (link->ip == rte_be_to_cpu_32(*dst_addr0))) {
+ if (is_phy_port_privte(pkt[0]->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_txrx->p.p, out_port, pkt[0]);
+ rte_pipeline_ah_packet_drop(
+ p_txrx->p.p, pkt_mask0);
+ }
+ }
+
+ break;
+
+ #ifdef IPV6
+ case ETH_TYPE_IPV6:
+ if (*protocol0 == ICMPV6_PROTOCOL_ID) {
+ #ifndef VNF_ACL
+ if (!memcmp(ipv6_h0->dst_addr, link->ipv6, 16)
+ || !memcmp(ipv6_h0->dst_addr, solicited_node_multicast_addr, 13)) {
+ #endif
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[0]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
+
+ #ifndef VNF_ACL
+ } else {
+ printf("Dropping the IPv6 pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
+ }
+ #endif
+ }
+ break;
+ #endif
+
+ default: /* Not valid pkt */
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
+
+ }
+ #endif
+
+ if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
+ print_pkt1(pkt[1]);
+ txrx_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(*eth_proto1), *protocol1, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ uint32_t dst_addr_offset1 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr1 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset1);
+
+ if (TXRX_DEBUG > 2)
+ if (rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
+ printf ("%s: linkIp: %x, dst_addr1: %x\n", __FUNCTION__, link->ip, *dst_addr1);
+
+ switch (rte_be_to_cpu_16(*eth_proto1)) {
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[1]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
+ break;
+
+ case ETH_TYPE_IPV4:
+ if ((*protocol1 == IP_PROTOCOL_ICMP) &&
+ (link->ip == rte_be_to_cpu_32(*dst_addr1))) {
+ if (is_phy_port_privte(pkt[1]->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_txrx->p.p,
+ out_port, pkt[1]);
+ rte_pipeline_ah_packet_drop(
+ p_txrx->p.p,
+ pkt_mask1);
+ }
+ }
+
+ break;
+
+ #ifdef IPV6
+ case ETH_TYPE_IPV6:
+ if (*protocol1 == ICMPV6_PROTOCOL_ID) {
+ #ifndef VNF_ACL
+ if (!memcmp(ipv6_h1->dst_addr, link->ipv6, 16)
+ || !memcmp(ipv6_h1->dst_addr, solicited_node_multicast_addr, 13)) {
+ #endif
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[1]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
+ #ifndef VNF_ACL
+ } else {
+ printf("Dropping the IPv6 pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
+ }
+ #endif
+ }
+ break;
+ #endif
+
+ default: /* Not valid pkt */
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
+
+ }
+
+ if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
+ print_pkt1(pkt[2]);
+ txrx_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(*eth_proto2), *protocol2, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ uint32_t dst_addr_offset2 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr2 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset2);
+
+ if (TXRX_DEBUG > 2)
+ if (rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
+ printf ("%s: linkIp: %x, dst_addr2: %x\n", __FUNCTION__, link->ip, *dst_addr2);
+
+ switch (rte_be_to_cpu_16(*eth_proto2)) {
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[2]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
+ break;
+
+ case ETH_TYPE_IPV4:
+ if ((*protocol2 == IP_PROTOCOL_ICMP) &&
+ (link->ip == rte_be_to_cpu_32(*dst_addr2))) {
+ if (is_phy_port_privte(pkt[2]->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_txrx->p.p,
+ out_port, pkt[2]);
+ rte_pipeline_ah_packet_drop(
+ p_txrx->p.p,
+ pkt_mask2);
+ }
+ }
+
+ break;
+
+ #ifdef IPV6
+ case ETH_TYPE_IPV6:
+ if (*protocol2 == ICMPV6_PROTOCOL_ID) {
+ #ifndef VNF_ACL
+ if (!memcmp(ipv6_h2->dst_addr, link->ipv6, 16)
+ || !memcmp(ipv6_h2->dst_addr, solicited_node_multicast_addr, 13)) {
+ #endif
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[2]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
+ #ifndef VNF_ACL
+ } else {
+ printf("Dropping the IPv6 pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
+ }
+ #endif
+ }
+ break;
+ #endif
+
+ default: /* Not valid pkt */
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
+
+ }
+
+ if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
+ print_pkt1(pkt[3]);
+ txrx_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(*eth_proto3), *protocol3, ETH_TYPE_ARP,
+ ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
+ }
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ uint32_t dst_addr_offset3 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ uint32_t *dst_addr3 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset3);
+
+ if (TXRX_DEBUG > 2)
+ if (rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
+ printf ("%s: linkIp: %x, dst_addr3: %x\n", __FUNCTION__, link->ip, *dst_addr3);
+
+ switch (rte_be_to_cpu_16(*eth_proto3)) {
+ case ETH_TYPE_ARP:
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[3]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
+ break;
+
+ case ETH_TYPE_IPV4:
+ if ((*protocol3 == IP_PROTOCOL_ICMP) &&
+ (link->ip == rte_be_to_cpu_32(*dst_addr3))) {
+ if (is_phy_port_privte(pkt[3]->port)) {
+ rte_pipeline_port_out_packet_insert(
+ p_txrx->p.p,
+ out_port, pkt[3]);
+ rte_pipeline_ah_packet_drop(
+ p_txrx->p.p,
+ pkt_mask3);
+ }
+ }
+
+ break;
+
+ #ifdef IPV6
+ case ETH_TYPE_IPV6:
+ if (*protocol3 == ICMPV6_PROTOCOL_ID) {
+ #ifndef VNF_ACL
+ if (!memcmp(ipv6_h3->dst_addr, link->ipv6, 16)
+ || !memcmp(ipv6_h3->dst_addr, solicited_node_multicast_addr, 13)) {
+ #endif
+ rte_pipeline_port_out_packet_insert(p_txrx->p.p,
+ out_port, pkt[3]);
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
+ #ifndef VNF_ACL
+ } else {
+ printf("Dropping the IPv6 pkt\n");
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
+ }
+ #endif
+ }
+ break;
+ #endif
+
+ default: /* Not valid pkt */
+ rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
+
+ }
+
+ p_txrx->receivedPktCount += 4;
+
+}
+
+PIPELINE_TXRX_KEY_PORT_IN_AH(port_in_ah_txrx, pkt_work_txrx, pkt4_work_txrx);
+
+static void *pipeline_txrx_init(struct pipeline_params *params,
+ __rte_unused void *arg)
+{
+ struct pipeline *p;
+ struct pipeline_txrx *p_pt;
+ uint32_t size, i, in_ports_arg_size;
+
+ printf("Start pipeline_txrx_init\n");
+
+ /* 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_txrx));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ p_pt = (struct pipeline_txrx *)p;
+ if (p == NULL)
+ return NULL;
+
+ PLOG(p, HIGH, "TXRX");
+ strcpy(p->name, params->name);
+ p->log_level = params->log_level;
+
+ p_pt->receivedPktCount = 0;
+ p_pt->droppedPktCount = 0;
+ for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
+ p_pt->links_map[i] = 0xff;
+
+ p_pt->pipeline_num = 0;
+ printf("txrx initialization of variables done\n");
+
+ /* Parse arguments */
+ if (pipeline_txrx_parse_args(p_pt, params))
+ return NULL;
+
+ /* Pipeline */
+ {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "TXRX",
+ .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;
+ }
+ }
+
+ p->n_ports_in = params->n_ports_in;
+ p->n_ports_out = params->n_ports_out;
+ p->n_tables = p->n_ports_in;
+
+ /* Memory allocation for in_port_h_arg */
+ in_ports_arg_size =
+ RTE_CACHE_LINE_ROUNDUP((sizeof
+ (struct pipeline_txrx_in_port_h_arg)) *
+ (params->n_ports_in));
+ struct pipeline_txrx_in_port_h_arg *ap =
+ (struct pipeline_txrx_in_port_h_arg *)rte_zmalloc(NULL,
+ in_ports_arg_size,
+ RTE_CACHE_LINE_SIZE);
+ if (ap == NULL)
+ return NULL;
+ /*Input ports */
+ for (i = 0; i < p->n_ports_in; i++) {
+ /* passing our txrx pipeline in call back arg */
+ (ap[i]).p = p_pt;
+ (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]),
+ .f_action = NULL,
+ .arg_ah = &(ap[i]),
+ .burst_size = params->port_in[i].burst_size,
+ };
+
+ port_params.f_action = port_in_ah_txrx;
+
+ 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;
+ }
+ }
+
+ /* Output ports */
+ 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;
+ }
+ }
+
+ int pipeline_num = 0;
+ int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
+ if (status < 0) {
+ printf("Unable to read pipeline number\n");
+ return NULL;
+ }
+ p_pt->pipeline_num = (uint8_t) pipeline_num;
+
+ register_pipeline_Qs(p_pt->pipeline_num, p);
+ set_link_map(p_pt->pipeline_num, p, p_pt->links_map);
+ set_outport_id(p_pt->pipeline_num, p, p_pt->outport_id);
+
+ /* Tables */
+ for (i = 0; i < p->n_ports_in; i++) {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_stub_ops,
+ .arg_create = NULL,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ int status = rte_pipeline_table_create(p->p,
+ &table_params,
+ &p->table_id[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* 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[i]);
+
+ if (status) {
+ rte_pipeline_free(p->p);
+ rte_free(p);
+ return NULL;
+ }
+ }
+
+ /* Add entries to tables */
+ for (i = 0; i < p->n_ports_in; i++) {
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ .port_id = p->port_out_id[i],
+ };
+
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ int status = rte_pipeline_table_default_entry_add(
+ p->p,
+ p->
+ table_id[i],
+ &default_entry,
+ &default_entry_ptr);
+
+ 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;
+ }
+ }
+
+ /* 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));
+
+ return p;
+}
+
+static int pipeline_txrx_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_txrx_timer(void *pipeline)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ pipeline_msg_req_handle(p);
+ rte_pipeline_flush(p->p);
+
+ return 0;
+}
+
+static int
+pipeline_txrx_track(void *pipeline, 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;
+
+ *port_out = port_in / p->n_ports_in;
+ return 0;
+}
+
+struct pipeline_be_ops pipeline_txrx_be_ops = {
+ .f_init = pipeline_txrx_init,
+ .f_free = pipeline_txrx_free,
+ .f_run = NULL,
+ .f_timer = pipeline_txrx_timer,
+ .f_track = pipeline_txrx_track,
+};
diff --git a/common/VIL/pipeline_txrx/pipeline_txrx_be.h b/common/VIL/pipeline_txrx/pipeline_txrx_be.h
new file mode 100644
index 00000000..f794729e
--- /dev/null
+++ b/common/VIL/pipeline_txrx/pipeline_txrx_be.h
@@ -0,0 +1,76 @@
+/*
+// 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_TXRX_BE_H__
+#define __INCLUDE_PIPELINE_TXRX_BE_H__
+
+#include "pipeline_common_be.h"
+#define PIPELINE_TXRX_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 struct pipeline_be_ops pipeline_txrx_be_ops;
+/*
+ * Messages
+ */
+enum pipeline_txrx_msg_req_type {
+ PIPELINE_TXRX_MSG_REQ_ENTRY_DBG,
+ PIPELINE_TXRX_MSG_REQS
+};
+/*
+ * MSG ENTRY DBG
+ */
+struct pipeline_txrx_entry_dbg_msg_req {
+ enum pipeline_msg_req_type type;
+ enum pipeline_txrx_msg_req_type subtype;
+
+ /* data */
+ uint8_t data[5];
+};
+/*
+ * TXRX Entry
+ */
+
+struct pipeline_txrx_in_port_h_arg {
+ struct pipeline_txrx *p;
+ uint8_t in_port_id;
+};
+
+struct pipeline_txrx_entry_dbg_msg_rsp {
+ int status;
+};
+
+#endif