From 51cd08d9a3f2826088d122e2a5683315c77a2786 Mon Sep 17 00:00:00 2001 From: Vishwesh M Rudramuni Date: Tue, 18 Apr 2017 19:41:40 +0530 Subject: common: Adding common library for sample vnf JIRA: SAMPLEVNF-3 This patch adds common libraries required as part of the sample vnf. This includes the following libraries 1. ACL library 2. SIP 3. FTP 4. Connection tracker 5. L2l3 stack - Interface Manager - ARP & ICMPv4 - ND & ICMPv6 and other common libraries needed for ip pipeline framework Change-Id: I117690b6b63fbcd76974cd7274518484e60980ab Signed-off-by: Vishwesh M Rudramuni [Push patch to gerrit] Signed-off-by: Deepak S --- common/VIL/pipeline_txrx/pipeline_txrx_be.c | 915 ++++++++++++++++++++++++++++ 1 file changed, 915 insertions(+) create mode 100644 common/VIL/pipeline_txrx/pipeline_txrx_be.c (limited to 'common/VIL/pipeline_txrx/pipeline_txrx_be.c') 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 + +#include +#include +#include +#include +#include +#include + +#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(¶ms-> + port_in[i]), + .arg_create = + pipeline_port_in_params_convert(¶ms-> + 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(¶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; + } + } + + 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, +}; -- cgit 1.2.3-korg