summaryrefslogtreecommitdiffstats
path: root/common/VIL/pipeline_arpicmp
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/pipeline_arpicmp')
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp.c2118
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp.h122
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c3484
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.h343
4 files changed, 6067 insertions, 0 deletions
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c
new file mode 100644
index 00000000..1ea9e749
--- /dev/null
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c
@@ -0,0 +1,2118 @@
+/*
+// 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_arpicmp_be.h"
+#include "pipeline_arpicmp.h"
+#include "vnf_common.h"
+
+#include "app.h"
+#include "vnf_common.h"
+#ifndef VNF_ACL
+#include "lib_arp.h"
+#endif
+
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_string_fns.h>
+
+uint16_t verbose_level = 1; /**< should be Silent by default. */
+uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */
+
+/*
+ * Work-around of a compilation error with ICC on invocations of the
+ * rte_be_to_cpu_16() function.
+ */
+#ifdef __GCC__
+#define RTE_BE_TO_CPU_16(be_16_v) rte_be_to_cpu_16((be_16_v))
+#define RTE_CPU_TO_BE_16(cpu_16_v) rte_cpu_to_be_16((cpu_16_v))
+#else
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+#define RTE_BE_TO_CPU_16(be_16_v) (be_16_v)
+#define RTE_CPU_TO_BE_16(cpu_16_v) (cpu_16_v)
+#else
+#define RTE_BE_TO_CPU_16(be_16_v) \
+ ((uint16_t) ((((be_16_v) & 0xFF) << 8) | ((be_16_v) >> 8)))
+#define RTE_CPU_TO_BE_16(cpu_16_v) \
+ ((uint16_t) ((((cpu_16_v) & 0xFF) << 8) | ((cpu_16_v) >> 8)))
+#endif
+#endif
+
+/*
+ * 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];
+
+ #if 0
+ 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);
+ #endif
+ if (params->ip.family == AF_INET) {
+ populate_arp_entry(&params->macaddr,
+ rte_cpu_to_be_32(params->ip.addr.
+ ipv4.s_addr),
+ params->port_id
+ #ifndef VNF_ACL
+ , STATIC_ARP
+ #endif
+ );
+ } else {
+ memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16);
+ populate_nd_entry(&params->macaddr, ipv6, params->port_id
+ #ifndef VNF_ACL
+ , STATIC_ND
+ #endif
+ );
+ }
+}
+
+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];
+
+ #if 0
+ 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);
+ #endif
+ if (params->ip.family == AF_INET) {
+ remove_arp_entry(rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr),
+ params->port_id
+ #ifndef VNF_ACL
+ , NULL
+ #endif
+ );
+ } 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);
+
+ #ifdef VNF_ACL
+ request_arp_wrap(params->port_id, params->ip.addr.ipv4.s_addr);
+ #else
+ request_arp(params->port_id, params->ip.addr.ipv4.s_addr);
+ #endif
+ /*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;
+
+ if (ARPICMP_DEBUG)
+ printf("Echo Req Handler ip %x, port %d\n",
+ params->ip.addr.ipv4.s_addr, params->port_id);
+
+ request_echo(params->port_id, params->ip.addr.ipv4.s_addr);
+}
+
+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,
+ },
+};
+
+#ifndef VNF_ACL
+struct cmd_arp_dbg_result {
+ cmdline_fixed_string_t arpdbg_str;
+ uint32_t flag;
+};
+
+cmdline_parse_token_string_t cmd_arp_dbg_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_dbg_result, arpdbg_str,
+ "arpdbg");
+cmdline_parse_token_num_t cmd_arp_dbg_flag =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_dbg_result, flag, UINT32);
+
+static void
+cmd_arp_dbg_parse(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_arp_dbg_result *params = parsed_result;
+ if(params)
+ {
+ set_arpdebug(params->flag);
+ }
+ else
+ {
+ printf("%s: Params is NULL",__FUNCTION__);
+ }
+}
+
+cmdline_parse_inst_t cmd_arp_dbg = {
+ .f = cmd_arp_dbg_parse,
+ .data = NULL,
+ .help_str = "Turn on/off(1/0) arp debug",
+ .tokens = {
+ (void *)&cmd_arp_dbg_string,
+ (void *)&cmd_arp_dbg_flag,
+ NULL,
+ },
+};
+
+struct cmd_arp_timer_result {
+ cmdline_fixed_string_t arptimer_str;
+ uint32_t arptimer_val;
+};
+
+cmdline_parse_token_string_t cmd_arp_timer_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_arp_timer_result, arptimer_str,
+ "arptimerexpiry");
+cmdline_parse_token_num_t cmd_arp_timer_val =
+ TOKEN_NUM_INITIALIZER(struct cmd_arp_timer_result, arptimer_val, UINT32);
+
+static void
+cmd_arp_timer_parse(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_arp_timer_result *params = parsed_result;
+ if(params)
+ {
+ set_arptimeout(params->arptimer_val);
+ }
+ else
+ {
+ printf("%s: Params is NULL",__FUNCTION__);
+ }
+}
+
+cmdline_parse_inst_t cmd_arp_timer = {
+ .f = cmd_arp_timer_parse,
+ .data = NULL,
+ .help_str = "Timer expiry val by def 10 sec",
+ .tokens = {
+ (void *)&cmd_arp_timer_string,
+ (void *)&cmd_arp_timer_val,
+ NULL,
+ },
+};
+#endif
+
+/*
+ * Forwarding of packets in I/O mode.
+ * Forward packets "as-is".
+ * This is the fastest possible forwarding operation, as it does not access
+ * to packets data.
+ */
+ static void
+pkt_burst_io_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+ #endif
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+ #endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+ #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+ #endif
+
+ fs->rx_packets += nb_rx;
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ fs->tx_packets += nb_tx;
+
+ #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+ #endif
+
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+ #endif
+}
+
+
+struct fwd_engine io_fwd_engine = {
+ .fwd_mode_name = "io",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_io_forward,
+};
+
+static inline void print_ether_addr(
+ const char *what,
+ struct ether_addr *eth_addr)
+{
+ char buf[ETHER_ADDR_FMT_SIZE];
+ ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", what, buf);
+}
+
+/*
+ * Received a burst of packets.
+ */
+ static void
+pkt_burst_receive(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *mb;
+ struct ether_hdr *eth_hdr;
+ uint16_t eth_type;
+ uint64_t ol_flags;
+ uint16_t nb_rx;
+ uint16_t i, packet_type;
+ uint16_t is_encapsulation;
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+ #endif
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+ #endif
+
+ /*
+ * Receive a burst of packets.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+ #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+ #endif
+
+ fs->rx_packets += nb_rx;
+
+ /*
+ * Dump each received packet if verbose_level > 0.
+ */
+ if (verbose_level > 0)
+ printf("port %u/queue %u: received %u packets\n",
+ (unsigned int) fs->rx_port,
+ (unsigned int) fs->rx_queue,
+ (unsigned int) nb_rx);
+ for (i = 0; i < nb_rx; i++) {
+ mb = pkts_burst[i];
+ if (verbose_level == 0) {
+ rte_pktmbuf_free(mb);
+ continue;
+ }
+ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
+ eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type);
+ ol_flags = mb->ol_flags;
+ packet_type = mb->packet_type;
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+
+ print_ether_addr(" src=", &eth_hdr->s_addr);
+ print_ether_addr(" - dst=", &eth_hdr->d_addr);
+ printf(" - type=0x%04x - length=%u - nb_segs=%d",
+ eth_type, (unsigned int) mb->pkt_len,
+ (int)mb->nb_segs);
+ if (ol_flags & PKT_RX_RSS_HASH) {
+ printf(" - RSS hash=0x%x", (unsigned int)
+ mb->hash.rss);
+ printf(" - RSS queue=0x%x", (unsigned int)
+ fs->rx_queue);
+ } else if (ol_flags & PKT_RX_FDIR) {
+ printf(" - FDIR matched ");
+ if (ol_flags & PKT_RX_FDIR_ID)
+ printf("ID=0x%x",
+ mb->hash.fdir.hi);
+ else if (ol_flags & PKT_RX_FDIR_FLX)
+ printf("flex bytes=0x%08x %08x",
+ mb->hash.fdir.hi, mb->hash.fdir.lo);
+ else
+ printf("hash=0x%x ID=0x%x ",
+ mb->hash.fdir.hash, mb->hash.fdir.id);
+ }
+ if (ol_flags & PKT_RX_VLAN_PKT)
+ printf(" - VLAN tci=0x%x", mb->vlan_tci);
+ if (ol_flags & PKT_RX_QINQ_PKT)
+ printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
+ mb->vlan_tci, mb->vlan_tci_outer);
+ if (mb->packet_type) {
+ uint32_t ptype;
+
+ /* (outer) L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L2_ETHER:
+ printf(" - (outer) L2 type: ETHER");
+ break;
+ case RTE_PTYPE_L2_ETHER_TIMESYNC:
+ printf(" - (outer) L2 type: ETHER_Timesync");
+ break;
+ case RTE_PTYPE_L2_ETHER_ARP:
+ printf(" - (outer) L2 type: ETHER_ARP");
+ break;
+ case RTE_PTYPE_L2_ETHER_LLDP:
+ printf(" - (outer) L2 type: ETHER_LLDP");
+ break;
+ default:
+ printf(" - (outer) L2 type: Unknown");
+ break;
+ }
+
+ /* (outer) L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L3_IPV4:
+ printf(" - (outer) L3 type: IPV4");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT:
+ printf(" - (outer) L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6:
+ printf(" - (outer) L3 type: IPV6");
+ break;
+ case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT:
+ printf(" - (outer) L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN:
+ printf(" - (outer) L3 type: IPV6_EXT_UNKNOWN");
+ break;
+ default:
+ printf(" - (outer) L3 type: Unknown");
+ break;
+ }
+
+ /* (outer) L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_L4_TCP:
+ printf(" - (outer) L4 type: TCP");
+ break;
+ case RTE_PTYPE_L4_UDP:
+ printf(" - (outer) L4 type: UDP");
+ break;
+ case RTE_PTYPE_L4_FRAG:
+ printf(" - (outer) L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_L4_SCTP:
+ printf(" - (outer) L4 type: SCTP");
+ break;
+ case RTE_PTYPE_L4_ICMP:
+ printf(" - (outer) L4 type: ICMP");
+ break;
+ case RTE_PTYPE_L4_NONFRAG:
+ printf(" - (outer) L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - (outer) L4 type: Unknown");
+ break;
+ }
+
+ /* packet tunnel type */
+ ptype = mb->packet_type & RTE_PTYPE_TUNNEL_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_TUNNEL_IP:
+ printf(" - Tunnel type: IP");
+ break;
+ case RTE_PTYPE_TUNNEL_GRE:
+ printf(" - Tunnel type: GRE");
+ break;
+ case RTE_PTYPE_TUNNEL_VXLAN:
+ printf(" - Tunnel type: VXLAN");
+ break;
+ case RTE_PTYPE_TUNNEL_NVGRE:
+ printf(" - Tunnel type: NVGRE");
+ break;
+ case RTE_PTYPE_TUNNEL_GENEVE:
+ printf(" - Tunnel type: GENEVE");
+ break;
+ case RTE_PTYPE_TUNNEL_GRENAT:
+ printf(" - Tunnel type: GRENAT");
+ break;
+ default:
+ printf(" - Tunnel type: Unknown");
+ break;
+ }
+
+ /* inner L2 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L2_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L2_ETHER:
+ printf(" - Inner L2 type: ETHER");
+ break;
+ case RTE_PTYPE_INNER_L2_ETHER_VLAN:
+ printf(" - Inner L2 type: ETHER_VLAN");
+ break;
+ default:
+ printf(" - Inner L2 type: Unknown");
+ break;
+ }
+ /* inner L3 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L3_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L3_IPV4:
+ printf(" - Inner L3 type: IPV4");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT:
+ printf(" - Inner L3 type: IPV4_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6:
+ printf(" - Inner L3 type: IPV6");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN:
+ printf(" - Inner L3 type: "
+ "IPV4_EXT_UNKNOWN");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT:
+ printf(" - Inner L3 type: IPV6_EXT");
+ break;
+ case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN:
+ printf(" - Inner L3 type: "
+ "IPV6_EXT_UNKNOWN");
+ break;
+ default:
+ printf(" - Inner L3 type: Unknown");
+ break;
+ }
+
+ /* inner L4 packet type */
+ ptype = mb->packet_type & RTE_PTYPE_INNER_L4_MASK;
+ switch (ptype) {
+ case RTE_PTYPE_INNER_L4_TCP:
+ printf(" - Inner L4 type: TCP");
+ break;
+ case RTE_PTYPE_INNER_L4_UDP:
+ printf(" - Inner L4 type: UDP");
+ break;
+ case RTE_PTYPE_INNER_L4_FRAG:
+ printf(" - Inner L4 type: L4_FRAG");
+ break;
+ case RTE_PTYPE_INNER_L4_SCTP:
+ printf(" - Inner L4 type: SCTP");
+ break;
+ case RTE_PTYPE_INNER_L4_ICMP:
+ printf(" - Inner L4 type: ICMP");
+ break;
+ case RTE_PTYPE_INNER_L4_NONFRAG:
+ printf(" - Inner L4 type: L4_NONFRAG");
+ break;
+ default:
+ printf(" - Inner L4 type: Unknown");
+ break;
+ }
+ printf("\n");
+ } else
+ printf("Unknown packet type\n");
+ if (is_encapsulation) {
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ struct udp_hdr *udp_hdr;
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+ uint8_t l4_proto;
+ struct vxlan_hdr *vxlan_hdr;
+
+ l2_len = sizeof(struct ether_hdr);
+
+ /* Do not support ipv4 option field */
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+ l3_len = sizeof(struct ipv4_hdr);
+ ipv4_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct ipv4_hdr *,
+ l2_len);
+ l4_proto = ipv4_hdr->next_proto_id;
+ } else {
+ l3_len = sizeof(struct ipv6_hdr);
+ ipv6_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct ipv6_hdr *,
+ l2_len);
+ l4_proto = ipv6_hdr->proto;
+ }
+ if (l4_proto == IPPROTO_UDP) {
+ udp_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct udp_hdr *,
+ l2_len + l3_len);
+ l4_len = sizeof(struct udp_hdr);
+ vxlan_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct vxlan_hdr *,
+ l2_len + l3_len + l4_len);
+
+ printf(" - VXLAN packet: packet type =%d, "
+ "Destination UDP port =%d, VNI = %d",
+ packet_type,
+ RTE_BE_TO_CPU_16(udp_hdr->dst_port),
+ rte_be_to_cpu_32(
+ vxlan_hdr->vx_vni) >> 8);
+ }
+ }
+ printf(" - Receive queue=0x%x", (unsigned int) fs->rx_queue);
+ printf("\n");
+ if (ol_flags != 0) {
+ unsigned int rxf;
+ const char *name;
+
+ for (rxf = 0; rxf < sizeof(mb->ol_flags) * 8; rxf++) {
+ if ((ol_flags & (1ULL << rxf)) == 0)
+ continue;
+ name = rte_get_rx_ol_flag_name(1ULL << rxf);
+ if (name == NULL)
+ continue;
+ printf(" %s\n", name);
+ }
+ }
+ rte_pktmbuf_free(mb);
+ }
+
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+ #endif
+}
+
+struct fwd_engine rx_only_engine = {
+ .fwd_mode_name = "rxonly",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_receive,
+};
+
+/* *** SET FORWARDING MODE *** */
+struct cmd_set_fwd_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t mode;
+};
+
+/*
+ * Forwarding engines.
+ */
+struct fwd_engine *fwd_engines[] = {
+ &io_fwd_engine,
+ #if 0
+ &mac_fwd_engine,
+ &mac_retry_fwd_engine,
+ &mac_swap_engine,
+ &flow_gen_engine,
+ #endif
+ &rx_only_engine,
+ #if 0
+ &tx_only_engine,
+ &csum_fwd_engine,
+ &icmp_echo_engine,
+ #ifdef RTE_LIBRTE_IEEE1588
+ &ieee1588_fwd_engine,
+ #endif
+ #endif
+ NULL,
+};
+
+struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */
+
+void set_pkt_forwarding_mode(const char *fwd_mode_name)
+{
+ struct fwd_engine *fwd_eng;
+ unsigned int i;
+
+ i = 0;
+ while ((fwd_eng = fwd_engines[i]) != NULL) {
+ if (!strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) {
+ printf("Set %s packet forwarding mode\n",
+ fwd_mode_name);
+ cur_fwd_eng = fwd_eng;
+ return;
+ }
+ i++;
+ }
+ printf("Invalid %s packet forwarding mode\n", fwd_mode_name);
+}
+
+static void cmd_set_fwd_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_fwd_mode_result *res = parsed_result;
+
+ set_pkt_forwarding_mode(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_setfwd_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setfwd_fwd =
+TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, fwd, "fwd");
+cmdline_parse_token_string_t cmd_setfwd_mode =
+TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, mode,
+ "rxonly" /* defined at init */);
+
+cmdline_parse_inst_t cmd_set_fwd_mode = {
+ .f = cmd_set_fwd_mode_parsed,
+ .data = NULL,
+ .help_str = NULL, /* defined at init */
+ .tokens = {
+ (void *)&cmd_setfwd_set,
+ (void *)&cmd_setfwd_fwd,
+ (void *)&cmd_setfwd_mode,
+ NULL,
+ },
+};
+
+#if 1
+
+static uint16_t
+str2flowtype(char *string)
+{
+ uint8_t i = 0;
+ static const struct {
+ char str[32];
+ uint16_t type;
+ } flowtype_str[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str); i++) {
+ if (!strcmp(flowtype_str[i].str, string))
+ return flowtype_str[i].type;
+ }
+ return RTE_ETH_FLOW_UNKNOWN;
+}
+
+static inline int
+parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned int size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT8_MAX)
+ return -1;
+ flexbytes[i] = (uint8_t)int_fld;
+ }
+ return ret;
+}
+
+/* *** deal with flow director filter *** */
+struct cmd_flow_director_result {
+ cmdline_fixed_string_t flow_director_filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t ether;
+ uint16_t ether_type;
+ cmdline_fixed_string_t src;
+ cmdline_ipaddr_t ip_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t verify_tag;
+ uint32_t verify_tag_value;
+ cmdline_ipaddr_t tos;
+ uint8_t tos_value;
+ cmdline_ipaddr_t proto;
+ uint8_t proto_value;
+ cmdline_ipaddr_t ttl;
+ uint8_t ttl_value;
+ cmdline_fixed_string_t vlan;
+ uint16_t vlan_value;
+ cmdline_fixed_string_t flexbytes;
+ cmdline_fixed_string_t flexbytes_value;
+ cmdline_fixed_string_t pf_vf;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+ cmdline_fixed_string_t fd_id;
+ uint32_t fd_id_value;
+ cmdline_fixed_string_t mac;
+ struct ether_addr mac_addr;
+ cmdline_fixed_string_t tunnel;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t tunnel_id;
+ uint32_t tunnel_id_value;
+};
+
+static void
+cmd_flow_director_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_result *res = parsed_result;
+ struct rte_eth_fdir_filter entry;
+ uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
+ char *end;
+ unsigned long vf_id;
+ int ret = 0;
+
+ if (enable_hwlb) {
+ printf("Hash Filter is already Defined !\n");
+ printf("Please undefine HWLD flag and define "
+ "FDIR_FILTER flag\n");
+ return;
+ }
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+ memset(flexbytes, 0, sizeof(flexbytes));
+ memset(&entry, 0, sizeof(struct rte_eth_fdir_filter));
+#if 0
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(res->mode_value, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return;
+ }
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(res->mode_value, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return;
+ }
+ } else {
+ if (strcmp(res->mode_value, "IP")) {
+ printf("Please set mode to IP.\n");
+ return;
+ }
+#endif
+ {
+ entry.input.flow_type = str2flowtype(res->flow_type);
+ }
+
+ ret = parse_flexbytes(res->flexbytes_value,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flexbytes input.\n");
+ return;
+ }
+
+ switch (entry.input.flow_type) {
+ case RTE_ETH_FLOW_FRAG_IPV4:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+ entry.input.flow.ip4_flow.proto = res->proto_value;
+ case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.ip4_flow.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.ip4_flow.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+
+ case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.sctp4_flow.ip.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.sctp4_flow.ip.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp4_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+
+ case RTE_ETH_FLOW_FRAG_IPV6:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+ entry.input.flow.ipv6_flow.proto = res->proto_value;
+ case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.ipv6_flow.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.ipv6_flow.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+
+ case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.sctp6_flow.ip.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.sctp6_flow.ip.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp6_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+ case RTE_ETH_FLOW_L2_PAYLOAD:
+ entry.input.flow.l2_flow.ether_type =
+ rte_cpu_to_be_16(res->ether_type);
+ break;
+ default:
+ break;
+ }
+#if 0
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ (void)rte_memcpy(&entry.input.flow.mac_vlan_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct ether_addr));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ (void)rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct ether_addr));
+ entry.input.flow.tunnel_flow.tunnel_type =
+ str2fdir_tunneltype(res->tunnel_type);
+ entry.input.flow.tunnel_flow.tunnel_id =
+ rte_cpu_to_be_32(res->tunnel_id_value);
+ }
+#endif
+
+ (void)rte_memcpy(entry.input.flow_ext.flexbytes,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+
+ entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(res->vlan_value);
+
+ entry.action.flex_off = 0; /*use 0 by default */
+ if (!strcmp(res->drop, "drop"))
+ entry.action.behavior = RTE_ETH_FDIR_REJECT;
+ else
+ entry.action.behavior = RTE_ETH_FDIR_ACCEPT;
+
+ if (!strcmp(res->pf_vf, "pf"))
+ entry.input.flow_ext.is_vf = 0;
+ else if (!strncmp(res->pf_vf, "vf", 2)) {
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ errno = 0;
+ vf_id = strtoul(res->pf_vf + 2, &end, 10);
+ if (errno != 0 || *end != '\0' || vf_id >= dev_info.max_vfs) {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ entry.input.flow_ext.is_vf = 1;
+ entry.input.flow_ext.dst_id = (uint16_t)vf_id;
+ } else {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ /* set to report FD ID by default */
+ entry.action.report_status = RTE_ETH_FDIR_REPORT_ID;
+ entry.action.rx_queue = res->queue_id;
+ entry.soft_id = res->fd_id_value;
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_ADD, &entry);
+ else if (!strcmp(res->ops, "del"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_DELETE, &entry);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_UPDATE, &entry);
+ if (ret < 0)
+ printf("flow director programming error: (%s)\n",
+ strerror(-ret));
+// fdir_filter_enabled = 1;
+}
+
+
+
+cmdline_parse_token_string_t cmd_flow_director_filter =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_director_filter, "flow_director_filter");
+
+cmdline_parse_token_num_t cmd_flow_director_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_id, UINT8);
+
+
+cmdline_parse_token_string_t cmd_flow_director_mode =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode, "mode");
+
+cmdline_parse_token_string_t cmd_flow_director_mode_ip =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "IP");
+
+cmdline_parse_token_string_t cmd_flow_director_ops =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ops, "add#del#update");
+
+cmdline_parse_token_string_t cmd_flow_director_flow =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow, "flow");
+
+cmdline_parse_token_string_t cmd_flow_director_flow_type =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_type, "ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload");
+
+cmdline_parse_token_string_t cmd_flow_director_src =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ src, "src");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src =
+TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_src);
+cmdline_parse_token_num_t cmd_flow_director_port_src =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_dst =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ dst, "dst");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst =
+TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_dst);
+cmdline_parse_token_num_t cmd_flow_director_port_dst =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_dst, UINT16);
+
+cmdline_parse_token_string_t cmd_flow_director_tos =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tos, "tos");
+cmdline_parse_token_num_t cmd_flow_director_tos_value =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ tos_value, UINT8);
+
+cmdline_parse_token_string_t cmd_flow_director_ttl =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ttl, "ttl");
+cmdline_parse_token_num_t cmd_flow_director_ttl_value =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ttl_value, UINT8);
+
+cmdline_parse_token_string_t cmd_flow_director_vlan =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ vlan, "vlan");
+cmdline_parse_token_num_t cmd_flow_director_vlan_value =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ vlan_value, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_flexbytes =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes, "flexbytes");
+cmdline_parse_token_string_t cmd_flow_director_flexbytes_value =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes_value, NULL);
+cmdline_parse_token_string_t cmd_flow_director_drop =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_flow_director_pf_vf =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ pf_vf, NULL);
+cmdline_parse_token_string_t cmd_flow_director_queue =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_flow_director_queue_id =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_fd_id =
+TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ fd_id, "fd_id");
+cmdline_parse_token_num_t cmd_flow_director_fd_id_value =
+TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ fd_id_value, UINT32);
+
+
+cmdline_parse_inst_t cmd_add_del_udp_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "add or delete an udp/tcp flow director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_port_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+/* L2 payload*/
+cmdline_parse_token_string_t cmd_flow_director_ether =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ether, "ether");
+cmdline_parse_token_num_t cmd_flow_director_ether_type =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ether_type, UINT16);
+
+cmdline_parse_inst_t cmd_add_del_l2_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "add or delete a L2 flow director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_ether,
+ (void *)&cmd_flow_director_ether_type,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+#if 1
+/* Set hash input set */
+struct cmd_set_hash_input_set_result {
+ cmdline_fixed_string_t set_hash_input_set;
+ uint8_t port_id;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t inset_field0;
+ cmdline_fixed_string_t inset_field1;
+ cmdline_fixed_string_t inset_field2;
+ cmdline_fixed_string_t inset_field3;
+ cmdline_fixed_string_t inset_field4;
+ cmdline_fixed_string_t select;
+};
+
+static enum rte_eth_input_set_field
+str2inset(char *string)
+{
+ uint16_t i;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_input_set_field inset;
+ } inset_table[] = {
+ {"ethertype", RTE_ETH_INPUT_SET_L2_ETHERTYPE},
+ {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN},
+ {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN},
+ {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4},
+ {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4},
+ {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS},
+ {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO},
+ {"ipv4-ttl", RTE_ETH_INPUT_SET_L3_IP4_TTL},
+ {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6},
+ {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6},
+ {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC},
+ {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER},
+ {"ipv6-hop-limits", RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS},
+ {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},
+ {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT},
+ {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},
+ {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT},
+ {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},
+ {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},
+ {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG},
+ {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY},
+ {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY},
+ {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD},
+ {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD},
+ {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD},
+ {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD},
+ {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD},
+ {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD},
+ {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD},
+ {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD},
+ {"none", RTE_ETH_INPUT_SET_NONE},
+ };
+ for (i = 0; i < RTE_DIM(inset_table); i++) {
+ if (!strcmp(string, inset_table[i].str))
+ return inset_table[i].inset;
+ }
+
+ return RTE_ETH_INPUT_SET_UNKNOWN;
+}
+
+static void
+cmd_set_hash_input_set_1_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ if (enable_flow_dir) {
+ printf("FDIR Filter is Defined!\n");
+ printf("Please undefine FDIR_FILTER flag and define "
+ "HWLD flag\n");
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field0);
+ info.info.input_set_conf.inset_size = 1;
+
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+
+ //hash_filter_enabled = 1;
+}
+
+static void
+cmd_set_hash_input_set_2_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ if (enable_flow_dir) {
+ printf("FDIR Filter is Defined!\n");
+ printf("Please undefine FDIR_FILTER flag and define "
+ "HWLD flag\n");
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field0);
+ info.info.input_set_conf.field[1] = str2inset(res->inset_field1);
+
+ info.info.input_set_conf.inset_size = 2;
+
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+
+ //hash_filter_enabled = 1;
+}
+
+#if 0
+static void
+cmd_set_hash_input_set_3_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field0);
+ info.info.input_set_conf.field[1] = str2inset(res->inset_field1);
+ info.info.input_set_conf.field[2] = str2inset(res->inset_field2);
+ info.info.input_set_conf.inset_size = 3;
+
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+}
+#endif
+static void
+cmd_set_hash_input_set_4_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ if (enable_flow_dir) {
+ printf("FDIR Filter is Defined!\n");
+ printf("Please undefine FDIR_FILTER flag and define "
+ "HWLD flag\n");
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field0);
+ info.info.input_set_conf.field[1] = str2inset(res->inset_field1);
+ info.info.input_set_conf.field[2] = str2inset(res->inset_field2);
+ info.info.input_set_conf.field[3] = str2inset(res->inset_field3);
+
+ info.info.input_set_conf.inset_size = 4;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ //hash_filter_enabled = 1;
+}
+
+#if 0
+static void
+cmd_set_hash_input_set_5_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field0);
+ info.info.input_set_conf.field[1] = str2inset(res->inset_field1);
+ info.info.input_set_conf.field[2] = str2inset(res->inset_field2);
+ info.info.input_set_conf.field[3] = str2inset(res->inset_field3);
+ info.info.input_set_conf.field[4] = str2inset(res->inset_field4);
+
+ info.info.input_set_conf.inset_size = 5;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+}
+#endif
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ set_hash_input_set, "set_hash_input_set");
+cmdline_parse_token_num_t cmd_set_hash_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ flow_type,
+ "ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_field0 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field0,
+ "src-ipv4#src-ipv6#dst-ipv4#dst-ipv6#"
+ "udp-src-port#udp-dst-port#tcp-src-port#tcp-dst-port#none");
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_field1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field1,
+ "dst-ipv4#dst-ipv6#"
+ "udp-src-port#tcp-src-port#udp-dst-port#tcp-dst-port#none");
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_field2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field2,
+ "udp-src-port#tcp-src-port#none");
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_field3 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field3,
+ "udp-dst-port#tcp-dst-port#none");
+#if 0
+cmdline_parse_token_string_t cmd_set_hash_input_set_field4 =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field4, "ipv4-proto#ipv6-next-header#none");
+#endif
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_select =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ select, "select#add");
+
+cmdline_parse_inst_t cmd_set_hash_input_set_1 = {
+ .f = cmd_set_hash_input_set_1_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set_1 <port_id> "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "src-ipv4|src-ipv6|dst-ipv4|dst-ipv6|"
+ "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|none "
+ "select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field0,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_hash_input_set_2 = {
+ .f = cmd_set_hash_input_set_2_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set_2 <port_id> "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other| "
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "src-ipv4|src-ipv6|dst-ipv4|dst-ipv6| "
+ "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|none "
+ "udp-src-port|tcp-src-port|udp-dst-port|tcp-dst-port|none "
+ "select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field0,
+ (void *)&cmd_set_hash_input_set_field1,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+
+#if 0
+cmdline_parse_inst_t cmd_set_hash_input_set_3 = {
+ .f = cmd_set_hash_input_set_3_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set_3 <port_id> "
+ "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|"
+ "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|"
+ "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|"
+ "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|"
+ "fld-7th|fld-8th|none "
+ "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|none "
+ "select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field0,
+ (void *)&cmd_set_hash_input_set_field1,
+ (void *)&cmd_set_hash_input_set_field2,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+#endif
+
+cmdline_parse_inst_t cmd_set_hash_input_set_4 = {
+ .f = cmd_set_hash_input_set_4_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set_4 <port_id> "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "src-ipv4|src-ipv6|dst-ipv4|dst-ipv6|"
+ "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|none "
+ "udp-src-port|tcp-src-port|udp-dst-port|tcp-dst-port|none "
+ "udp-src-port|tcp-src-port|dst-ipv4|none "
+ "udp-dst-port|tcp-dst-port|none "
+ "select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field0,
+ (void *)&cmd_set_hash_input_set_field1,
+ (void *)&cmd_set_hash_input_set_field2,
+ (void *)&cmd_set_hash_input_set_field3,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+#if 0
+cmdline_parse_inst_t cmd_set_hash_input_set_5 = {
+ .f = cmd_set_hash_input_set_5_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set_5 <port_id> "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "src-ipv4|src-ipv6|none "
+ "dst-ipv4|dst-ipv6|none "
+ "udp-src-port|tcp-src-port|none "
+ "udp-dst-port|tcp-dst-port|none "
+ "ipv4-proto|ipv6-next-header|none "
+ "select|add",
+
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field0,
+ (void *)&cmd_set_hash_input_set_field1,
+ (void *)&cmd_set_hash_input_set_field2,
+ (void *)&cmd_set_hash_input_set_field3,
+ (void *)&cmd_set_hash_input_set_field4,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+#endif
+#endif
+/* set hash global config */
+struct cmd_set_hash_global_config_result {
+ cmdline_fixed_string_t set_hash_global_config;
+ uint8_t port_id;
+ cmdline_fixed_string_t hash_func;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t enable;
+};
+
+static void
+cmd_set_hash_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_global_config_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ uint32_t ftype, idx, offset;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ res->port_id);
+ return;
+ }
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ if (!strcmp(res->hash_func, "toeplitz"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+ else if (!strcmp(res->hash_func, "simple_xor"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+ else if (!strcmp(res->hash_func, "default"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_DEFAULT;
+
+ ftype = str2flowtype(res->flow_type);
+ idx = ftype / (CHAR_BIT * sizeof(uint32_t));
+ offset = ftype % (CHAR_BIT * sizeof(uint32_t));
+ info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset);
+ if (!strcmp(res->enable, "enable"))
+ if(idx < RTE_SYM_HASH_MASK_ARRAY_SIZE)
+ info.info.global_conf.sym_hash_enable_mask[idx] |=
+ (1UL << offset);
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0)
+ printf("Cannot set global hash configurations by port %d\n",
+ res->port_id);
+ else
+ printf("Global hash configurations have been set "
+ "succcessfully by port %d\n", res->port_id);
+}
+cmdline_parse_token_string_t cmd_set_hash_global_config_all =
+TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ set_hash_global_config, "set_hash_global_config");
+cmdline_parse_token_num_t cmd_set_hash_global_config_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_set_hash_global_config_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_hash_global_config_hash_func =
+TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ hash_func, "toeplitz#simple_xor#default");
+cmdline_parse_token_string_t cmd_set_hash_global_config_flow_type =
+TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ flow_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_hash_global_config_enable =
+TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_hash_global_config = {
+ .f = cmd_set_hash_global_config_parsed,
+ .data = NULL,
+ .help_str = "set_hash_global_config port_id "
+ "toeplitz|simple_xor|default "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "enable|disable",
+ .tokens = {
+ (void *)&cmd_set_hash_global_config_all,
+ (void *)&cmd_set_hash_global_config_port_id,
+ (void *)&cmd_set_hash_global_config_hash_func,
+ (void *)&cmd_set_hash_global_config_flow_type,
+ (void *)&cmd_set_hash_global_config_enable,
+ NULL,
+ },
+};
+
+/* *** Set symmetric hash enable per port *** */
+struct cmd_set_sym_hash_ena_per_port_result {
+ cmdline_fixed_string_t set_sym_hash_ena_per_port;
+ cmdline_fixed_string_t enable;
+ uint8_t port_id;
+};
+
+static void
+cmd_set_sym_hash_per_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_sym_hash_ena_per_port_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+
+ if (!strcmp(res->enable, "enable"))
+ info.info.enable = 1;
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0) {
+ printf("Cannot set symmetric hash enable per port on "
+ "port %u\n", res->port_id);
+ return;
+ }
+ printf("Symmetric hash has been set to %s on port %u\n",
+ res->enable, res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ set_sym_hash_ena_per_port, "set_sym_hash_ena_per_port");
+cmdline_parse_token_num_t cmd_set_sym_hash_ena_per_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_sym_hash_ena_per_port = {
+ .f = cmd_set_sym_hash_per_port_parsed,
+ .data = NULL,
+ .help_str = "set_sym_hash_ena_per_port port_id enable|disable",
+ .tokens = {
+ (void *)&cmd_set_sym_hash_ena_per_port_all,
+ (void *)&cmd_set_sym_hash_ena_per_port_port_id,
+ (void *)&cmd_set_sym_hash_ena_per_port_enable,
+ NULL,
+ },
+};
+#endif
+
+static int
+app_pipeline_arpicmp_entry_dbg(struct app_params *app,
+ uint32_t pipeline_id, uint8_t *msg)
+{
+ struct pipeline_arpicmp_entry_dbg_msg_req *req;
+ struct pipeline_arpicmp_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_ARPICMP_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_arpicmp_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 = "ARPICMP 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,
+ (cmdline_parse_inst_t *) &cmd_arp_add,
+ (cmdline_parse_inst_t *) &cmd_arp_del,
+ (cmdline_parse_inst_t *) &cmd_arp_req,
+ (cmdline_parse_inst_t *) &cmd_icmp_echo_req,
+ (cmdline_parse_inst_t *) &cmd_arp_ls,
+ (cmdline_parse_inst_t *) &cmd_show_ports_info,
+ /*HWLB cmds*/
+ (cmdline_parse_inst_t *) &cmd_set_fwd_mode,
+ (cmdline_parse_inst_t *) &cmd_add_del_udp_flow_director,
+ (cmdline_parse_inst_t *) &cmd_add_del_l2_flow_director,
+ (cmdline_parse_inst_t *) &cmd_set_hash_input_set_1,
+ (cmdline_parse_inst_t *) &cmd_set_hash_input_set_2,
+/* (cmdline_parse_inst_t *) & cmd_set_hash_input_set_3,*/
+ (cmdline_parse_inst_t *) &cmd_set_hash_input_set_4,
+/* (cmdline_parse_inst_t *) & cmd_set_hash_input_set_5,*/
+ (cmdline_parse_inst_t *) &cmd_set_hash_global_config,
+ (cmdline_parse_inst_t *) &cmd_set_sym_hash_ena_per_port,
+ #ifndef VNF_ACL
+ (cmdline_parse_inst_t *) &cmd_arp_dbg,
+ (cmdline_parse_inst_t *) &cmd_arp_timer,
+ #endif
+ NULL,
+};
+
+static struct pipeline_fe_ops pipeline_arpicmp_fe_ops = {
+ .f_init = NULL,
+ .f_free = NULL,
+ .cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_arpicmp = {
+ .name = "ARPICMP",
+ .be_ops = &pipeline_arpicmp_be_ops,
+ .fe_ops = &pipeline_arpicmp_fe_ops,
+};
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.h b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.h
new file mode 100644
index 00000000..1efb14e2
--- /dev/null
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.h
@@ -0,0 +1,122 @@
+/*
+// 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_ARPICMP_H__
+#define __INCLUDE_PIPELINE_ARPICMP_H__
+
+#include "pipeline.h"
+#include "pipeline_arpicmp_be.h"
+
+/*
+ * Pipeline type
+ */
+extern struct pipeline_type pipeline_arpicmp;
+//uint16_t verbose_level = 1; /**< should be Silent by default. */
+#define MAX_PKT_BURST 512
+#define DEF_PKT_BURST 32
+/**< Number of packets per burst. */
+//uint16_t nb_pkt_per_burst = DEF_PKT_BURST;
+typedef uint8_t portid_t;
+typedef uint16_t queueid_t;
+typedef uint16_t streamid_t;
+/**
+ * The data structure associated with a forwarding stream between a receive
+ * port/queue and a transmit port/queue.
+ */
+struct fwd_stream {
+ /* "read-only" data */
+ /**< port to poll for received packets */
+ portid_t rx_port;
+ /**< RX queue to poll on "rx_port" */
+ queueid_t rx_queue;
+ /**< forwarding port of received packets */
+ portid_t tx_port;
+ /**< TX queue to send forwarded packets */
+ queueid_t tx_queue;
+ /**< index of peer ethernet address of packets */
+ streamid_t peer_addr;
+
+ /* "read-write" results */
+ /**< received packets */
+ unsigned int rx_packets;
+ /**< received packets transmitted */
+ unsigned int tx_packets;
+ /**< received packets not forwarded */
+ unsigned int fwd_dropped;
+ /**< received packets has bad ip checksum */
+ unsigned int rx_bad_ip_csum;
+ /**< received packets has bad l4 checksum */
+ unsigned int rx_bad_l4_csum;
+ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t core_cycles; /**< used for RX and TX processing */
+ #endif
+ #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ struct pkt_burst_stats rx_burst_stats;
+ struct pkt_burst_stats tx_burst_stats;
+ #endif
+};
+/*
+ * Forwarding mode operations:
+ * - IO forwarding mode (default mode)
+ * Forwards packets unchanged.
+ *
+ * - MAC forwarding mode
+ * Set the source and the destination Ethernet addresses of packets
+ * before forwarding them.
+ *
+ * - IEEE1588 forwarding mode
+ * Check that received IEEE1588 Precise Time Protocol (PTP) packets are
+ * filtered and timestamped by the hardware.
+ * Forwards packets unchanged on the same port.
+ * Check that sent IEEE1588 PTP packets are timestamped by the hardware.
+ */
+typedef void (*port_fwd_begin_t)(portid_t pi);
+typedef void (*port_fwd_end_t)(portid_t pi);
+typedef void (*packet_fwd_t)(struct fwd_stream *fs);
+struct fwd_engine {
+ /**< Forwarding mode name. */
+ const char *fwd_mode_name;
+ /**< NULL if nothing special to do. */
+ port_fwd_begin_t port_fwd_begin;
+ /**< NULL if nothing special to do. */
+ port_fwd_end_t port_fwd_end;
+ /**< Mandatory. */
+ packet_fwd_t packet_fwd;
+};
+#define IPV4_ADDR_TO_UINT(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET) \
+ (ip) = (ip_addr).addr.ipv4.s_addr; \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+#define IPV6_ADDR_TO_ARRAY(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET6) \
+ (void)rte_memcpy(&(ip), \
+ &((ip_addr).addr.ipv6), \
+ sizeof(struct in6_addr)); \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+void set_pkt_forwarding_mode(const char *fwd_mode_name);
+#endif
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c
new file mode 100644
index 00000000..7238bd1d
--- /dev/null
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c
@@ -0,0 +1,3484 @@
+/*
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <app.h>
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+#include <rte_table_stub.h>
+#include <rte_table_hash.h>
+#include <rte_pipeline.h>
+#include <rte_arp.h>
+#include <rte_icmp.h>
+#include <rte_hash.h>
+#include <rte_jhash.h>
+#include <rte_cycles.h>
+#include <rte_hexdump.h>
+#include "pipeline_actions_common.h"
+#include "hash_func.h"
+#include "vnf_common.h"
+#include "pipeline_common_be.h"
+#include "pipeline_arpicmp_be.h"
+#include "parser.h"
+#include "hash_func.h"
+#include "vnf_common.h"
+#include "app.h"
+
+#include"pipeline_common_fe.h"
+#ifndef VNF_ACL
+#include "lib_arp.h"
+#include "lib_icmpv6.h"
+#include "interface.h"
+#endif
+
+#ifdef VNF_ACL
+
+#define NB_ARPICMP_MBUF 64
+#define NB_NDICMP_MBUF 64
+#define IP_VERSION_4 0x40
+/* default IP header length == five 32-bits words. */
+#define IP_HDRLEN 0x05
+#define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
+
+#define is_multicast_ipv4_addr(ipv4_addr) \
+ (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
+
+
+/*ND IPV6 */
+#define INADDRSZ 4
+#define IN6ADDRSZ 16
+static int my_inet_pton_ipv6(int af, const char *src, void *dst);
+static int inet_pton_ipv6(const char *src, unsigned char *dst);
+static int inet_pton_ipv4(const char *src, unsigned char *dst);
+
+uint8_t vnf_common_arp_lib_init;
+uint8_t vnf_common_nd_lib_init;
+uint8_t loadb_pipeline_count;
+
+uint32_t ARPICMP_DEBUG;
+uint32_t NDIPV6_DEBUG;
+
+uint32_t arp_route_tbl_index;
+uint32_t nd_route_tbl_index;
+uint32_t link_hw_addr_array_idx;
+
+uint32_t lib_arp_get_mac_req;
+uint32_t lib_arp_nh_found;
+uint32_t lib_arp_no_nh_found;
+uint32_t lib_arp_arp_entry_found;
+uint32_t lib_arp_no_arp_entry_found;
+uint32_t lib_arp_populate_called;
+uint32_t lib_arp_delete_called;
+uint32_t lib_arp_duplicate_found;
+
+uint32_t lib_nd_get_mac_req;
+uint32_t lib_nd_nh_found;
+uint32_t lib_nd_no_nh_found;
+uint32_t lib_nd_nd_entry_found;
+uint32_t lib_nd_no_arp_entry_found;
+uint32_t lib_nd_populate_called;
+uint32_t lib_nd_delete_called;
+uint32_t lib_nd_duplicate_found;
+
+struct rte_mempool *lib_arp_pktmbuf_tx_pool;
+struct rte_mempool *lib_nd_pktmbuf_tx_pool;
+
+struct rte_mbuf *lib_arp_pkt;
+struct rte_mbuf *lib_nd_pkt;
+
+static struct rte_hash_parameters arp_hash_params = {
+ .name = "ARP",
+ .entries = 64,
+ .reserved = 0,
+ .key_len = sizeof(struct arp_key_ipv4),
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+};
+
+static struct rte_hash_parameters nd_hash_params = {
+ .name = "ND",
+ .entries = 64,
+ .reserved = 0,
+ .key_len = sizeof(struct nd_key_ipv6),
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+};
+
+struct rte_hash *arp_hash_handle;
+struct rte_hash *nd_hash_handle;
+
+#endif
+/* Shared among all VNFs including LB */
+struct app_params *myApp;
+struct rte_pipeline *myP;
+struct pipeline_arpicmp *gp_arp;
+uint8_t num_vnf_threads;
+
+#ifdef VNF_ACL
+
+struct arp_port_address {
+ uint32_t ip;
+ uint64_t mac_addr;
+};
+
+struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
+
+uint16_t arp_meta_offset;
+#endif
+
+struct pipeline_arpicmp {
+ struct pipeline p;
+ pipeline_msg_req_handler
+ custom_handlers[PIPELINE_ARPICMP_MSG_REQS];
+ uint64_t receivedPktCount;
+ uint64_t droppedPktCount;
+ uint64_t sentPktCount;
+ uint8_t links_map[PIPELINE_MAX_PORT_IN];
+ uint8_t outport_id[PIPELINE_MAX_PORT_IN];
+ uint8_t pipeline_num;
+} __rte_cache_aligned;
+
+#ifdef VNF_ACL
+
+#define MAX_NUM_ARP_ENTRIES 64
+#define MAX_NUM_ND_ENTRIES 64
+
+
+struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
+};
+
+struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
+// {0xac102814, 1, 0xac102814},
+// {0xac106414, 0, 0xac106414},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+#endif
+
+void pipelines_port_info(void)
+{
+ struct app_params *app = myApp;
+ uint8_t i, pipeline;
+ for (pipeline = 0; pipeline < app->n_pipelines; pipeline++) {
+ printf("*** PIPELINE %d ***\n\n", pipeline);
+
+ printf("*** OUTPORTs ***\n");
+ for (i = 1; i < app->pipeline_params[pipeline].n_pktq_out;
+ i++) {
+ switch (app->pipeline_params[pipeline].pktq_out[i].
+ type) {
+ case APP_PKTQ_OUT_SWQ:
+ printf("pktq_out[%d]:%s\n", i,
+ app->swq_params[app->pipeline_params
+ [pipeline].
+ pktq_out[i].id].name);
+ break;
+ case APP_PKTQ_OUT_HWQ:
+ printf("pktq_out[%d]:%s\n", i,
+ app->hwq_out_params[app->pipeline_params
+ [pipeline].pktq_out
+ [i].id].name);
+ break;
+ default:
+ printf("Not OUT SWQ or HWQ\n");
+ }
+ }
+ printf("*** INPORTs ***\n");
+ for (i = 0; i < app->pipeline_params[pipeline].n_pktq_in; i++) {
+ switch (app->pipeline_params[pipeline].pktq_in[i]
+ .type) {
+ case APP_PKTQ_IN_SWQ:
+ printf("pktq_in[%d]:%s\n", i,
+ app->swq_params[app->pipeline_params
+ [pipeline].
+ pktq_in[i].id].name);
+ break;
+ case APP_PKTQ_IN_HWQ:
+ printf("pktq_in[%d]:%s\n", i,
+ app->hwq_in_params[app->pipeline_params
+ [pipeline].
+ pktq_in[i].id].name);
+ break;
+ default:
+ printf("Not IN SWQ or HWQ\n");
+ }
+ }
+ } //for
+}
+
+void pipelines_map_info(void)
+{
+ int i = 0;
+
+ printf("PIPELINE_MAX_PORT_IN %d\n", PIPELINE_MAX_PORT_IN);
+ printf("lb_outport_id[%d", lb_outport_id[0]);
+ for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
+ printf(",%d", lb_outport_id[i]);
+ printf("]\n");
+
+ printf("vnf_to_loadb_map[%d", vnf_to_loadb_map[0]);
+ for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
+ printf(",%d", vnf_to_loadb_map[i]);
+ printf("]\n");
+
+ printf("port_to_loadb_map[%d", port_to_loadb_map[0]);
+ for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
+ printf(",%d", port_to_loadb_map[i]);
+ printf("]\n");
+
+ printf("loadb_pipeline_nums[%d", loadb_pipeline_nums[0]);
+ for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
+ printf(",%d", loadb_pipeline_nums[i]);
+ printf("]\n");
+
+ printf("loadb_pipeline[%p", loadb_pipeline[0]);
+ for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
+ printf(",%p", loadb_pipeline[i]);
+ printf("]\n");
+}
+
+void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
+{
+ struct rte_port_ethdev_reader *hwq;
+ struct rte_port_ring_writer *out_swq;
+ struct rte_port_ring_reader *in_swq;
+ struct rte_pipeline *rte = p->p;
+ uint8_t port_count = 0;
+ int queue_out = 0xff, queue_in = 0xff;
+
+ printf("Calling register_pipeline_Qs in PIPELINE%d\n", pipeline_num);
+ for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_out[port_count].type){
+
+ case APP_PKTQ_OUT_SWQ:
+
+ if (port_count >= rte->num_ports_in) {
+
+ /* Dont register ARP output Q */
+ if (rte->num_ports_out % rte->num_ports_in)
+ if (port_count == rte->num_ports_out - 1)
+ return;
+ int temp;
+ temp = ((port_count) % rte->num_ports_in);
+
+ in_swq = rte->ports_in[temp].h_port;
+ out_swq = rte->ports_out[port_count].h_port;
+ printf("in_swq : %s\n",
+ in_swq->ring->name);
+ int status =
+ sscanf(in_swq->ring->name, "SWQ%d",
+ &queue_in);
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+ printf("out_swq: %s\n",
+ out_swq->ring->name);
+ status =
+ sscanf(out_swq->ring->name, "SWQ%d",
+ &queue_out);
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+ if (queue_in < 128 && queue_out < 128) {
+ SWQ_to_Port_map[queue_out] =
+ SWQ_to_Port_map[queue_in];
+ printf("SWQ_to_Port_map[%d]%d\n", queue_out,
+ SWQ_to_Port_map[queue_out]);
+ }
+ continue;
+ }
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_in[port_count].type){
+
+ case APP_PKTQ_OUT_HWQ:
+ hwq = rte->ports_in[port_count].h_port;
+ out_swq = rte->ports_out[port_count].h_port;
+ printf("out_swq: %s\n",
+ out_swq->ring->name);
+ int status =
+ sscanf(out_swq->ring->name, "SWQ%d",
+ &queue_out);
+
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+ if (queue_out < 128) {
+ SWQ_to_Port_map[queue_out] = hwq->port_id;
+ printf("SWQ_to_Port_map[%d]%d\n", queue_out,
+ SWQ_to_Port_map[queue_out]);
+ }
+ break;
+
+ case APP_PKTQ_OUT_SWQ:
+ in_swq = rte->ports_in[port_count].h_port;
+ out_swq = rte->ports_out[port_count].h_port;
+ printf("in_swq : %s\n",
+ in_swq->ring->name);
+ status =
+ sscanf(in_swq->ring->name, "SWQ%d",
+ &queue_in);
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+ printf("out_swq: %s\n",
+ out_swq->ring->name);
+ status =
+ sscanf(out_swq->ring->name, "SWQ%d",
+ &queue_out);
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+ if (queue_in < 128 && queue_out < 128){
+ SWQ_to_Port_map[queue_out] =
+ SWQ_to_Port_map[queue_in];
+ printf("SWQ_to_Port_map[%d]%d\n", queue_out,
+ SWQ_to_Port_map[queue_out]);
+ }
+ break;
+
+ default:
+ printf("This never hits\n");
+ }
+
+ break;
+
+ case APP_PKTQ_OUT_HWQ:
+ printf("This is HWQ\n");
+ break;
+
+ default:
+ printf("set_phy_outport_map: This never hits\n");
+ }
+ }
+}
+
+void set_link_map(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
+{
+ struct rte_port_ethdev_writer *hwq;
+ struct rte_port_ring_writer *out_swq;
+ struct rte_pipeline *rte = p->p;
+
+ uint8_t port_count = 0;
+ int index = 0, queue_out = 0xff;
+
+ printf("Calling set_link_map in PIPELINE%d\n", pipeline_num);
+ for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_out[port_count].type){
+
+ case APP_PKTQ_OUT_HWQ:
+ hwq = rte->ports_out[port_count].h_port;
+ map[index++] = hwq->port_id;
+ printf("links_map[%d]:%d\n", index - 1, map[index - 1]);
+ break;
+
+ case APP_PKTQ_OUT_SWQ:
+ out_swq = rte->ports_out[port_count].h_port;
+ printf("set_link_map out_swq: %s\n",
+ out_swq->ring->name);
+ int status = sscanf(out_swq->ring->name, "SWQ%d",
+ &queue_out);
+ if (status < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+
+ if (queue_out < 128) {
+ map[index++] = SWQ_to_Port_map[queue_out];
+ printf("links_map[%s]:%d\n", out_swq->ring->name,
+ map[index - 1]);
+ }
+ break;
+
+ default:
+ printf("set_phy_outport_map: This never hits\n");
+ }
+ }
+}
+
+void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
+{
+ uint8_t port_count = 0;
+ int queue_out = 0xff, index = 0;
+
+ struct rte_port_ethdev_writer *hwq;
+ struct rte_port_ring_writer *out_swq;
+ struct rte_pipeline *rte = p->p;
+
+ printf("\n**** set_outport_id() with pipeline_num:%d ****\n\n",
+ pipeline_num);
+ for (port_count = 0;
+ port_count < rte->num_ports_out;
+ port_count++) {
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_out[port_count].type) {
+
+ case APP_PKTQ_OUT_HWQ:
+ hwq = rte->ports_out[port_count].h_port;
+ //if (index >= 0)
+ {
+ map[hwq->port_id] = index;
+ printf("hwq port_id:%d index:%d\n",
+ hwq->port_id, index);
+ map[hwq->port_id] = index++;
+ printf("hwq port_id:%d index:%d\n",
+ hwq->port_id, index-1);
+ printf("outport_id[%d]:%d\n", index - 1,
+ map[index - 1]);
+ }
+ break;
+
+ case APP_PKTQ_OUT_SWQ:
+
+ /* Dont register ARP output Q */
+ if (port_count >= rte->num_ports_in)
+ if (rte->num_ports_out % rte->num_ports_in)
+ if (port_count == rte->num_ports_out - 1)
+ return;
+ out_swq = rte->ports_out[port_count].h_port;
+ printf("set_outport_id out_swq: %s\n",
+ out_swq->ring->name);
+ int temp = sscanf(out_swq->ring->name, "SWQ%d",
+ &queue_out);
+ if (temp < 0) {
+ printf("Unable to read SWQ number\n");
+ return;
+ }
+
+ if (queue_out < 128 && index >= 0) {
+ map[SWQ_to_Port_map[queue_out]] = index++;
+ printf("outport_id[%s]:%d\n", out_swq->ring->name,
+ map[SWQ_to_Port_map[queue_out]]);
+ }
+ break;
+
+ default:
+ printf(" ");
+
+ }
+ }
+}
+
+void set_phy_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
+{
+ uint8_t port_count = 0;
+ int index = 0;
+
+ struct rte_port_ethdev_writer *hwq;
+ struct rte_pipeline *rte = p->p;
+
+ printf("\n**** set_phy_outport_id() with pipeline_num:%d ****\n\n",
+ pipeline_num);
+ for (port_count = 0;
+ port_count < myApp->pipeline_params[pipeline_num].n_pktq_out;
+ port_count++) {
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_out[port_count].type) {
+
+ case APP_PKTQ_OUT_HWQ:
+ hwq = rte->ports_out[port_count].h_port;
+ map[hwq->port_id] = index++;
+ printf("outport_id[%d]:%d\n", index - 1,
+ map[index - 1]);
+ break;
+
+ default:
+ printf(" ");
+
+ }
+ }
+}
+
+void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
+{
+ uint8_t port_count = 0;
+ int index = 0;
+
+ struct rte_port_ethdev_reader *hwq;
+ struct rte_pipeline *rte = p->p;
+
+ printf("\n**** set_phy_inport_id() with pipeline_num:%d ****\n\n",
+ pipeline_num);
+ for (port_count = 0;
+ port_count < myApp->pipeline_params[pipeline_num].n_pktq_in;
+ port_count++) {
+
+ switch (myApp->pipeline_params[pipeline_num].
+ pktq_in[port_count].type) {
+
+ case APP_PKTQ_OUT_HWQ:
+ hwq = rte->ports_in[port_count].h_port;
+ map[hwq->port_id] = index++;
+ printf("outport_id[%d]:%d\n", index - 1,
+ map[index - 1]);
+ break;
+
+ default:
+ printf(" ");
+
+ }
+ }
+}
+
+#ifdef VNF_ACL
+
+uint32_t get_nh(uint32_t ip, uint32_t *port)
+{
+ int i = 0;
+ for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
+ if (((lib_arp_route_table[i].
+ ip & lib_arp_route_table[i].mask) ==
+ (ip & lib_arp_route_table[i].mask))) {
+
+ *port = lib_arp_route_table[i].port;
+ lib_arp_nh_found++;
+ return lib_arp_route_table[i].nh;
+ }
+ if (ARPICMP_DEBUG > 1)
+ printf("No nh match ip 0x%x, port %u, t_ip "
+ "0x%x, t_port %u, mask 0x%x, r1 %x, r2 %x\n",
+ ip, *port, lib_arp_route_table[i].ip,
+ lib_arp_route_table[i].port,
+ lib_arp_route_table[i].mask,
+ (lib_arp_route_table[i].ip &
+ lib_arp_route_table[i].mask),
+ (ip & lib_arp_route_table[i].mask));
+ }
+ if (ARPICMP_DEBUG && ip)
+ printf("No NH - ip 0x%x, port %u\n", ip, *port);
+ lib_arp_no_nh_found++;
+ return 0;
+}
+
+/*ND IPv6 */
+void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
+{
+ int i = 0;
+ uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
+ uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
+ memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
+ memset(netip_nd, 0, sizeof(netip_nd));
+ memset(netip_in, 0, sizeof(netip_in));
+ if (!ipv6)
+ return;
+ for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
+
+ convert_prefixlen_to_netmask_ipv6(
+ lib_nd_route_table[i].depth,
+ netmask_ipv6);
+
+ for (k = 0; k < 16; k++) {
+ if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
+ depthflags++;
+ netip_nd[k] = lib_nd_route_table[i].ipv6[k];
+ }
+ }
+
+ for (l = 0; l < 16; l++) {
+ if (ipv6[l] & netmask_ipv6[l]) {
+ depthflags1++;
+ netip_in[l] = ipv6[l];
+ }
+ }
+ int j = 0;
+ if ((depthflags == depthflags1)
+ && (memcmp(netip_nd, netip_in,
+ sizeof(netip_nd)) == 0)) {
+ //&& (lib_nd_route_table[i].port == port))
+ *port = lib_nd_route_table[i].port;
+ lib_nd_nh_found++;
+
+ for (j = 0; j < 16; j++)
+ nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
+
+ return;
+ }
+
+ if (NDIPV6_DEBUG > 1)
+ printf("No nh match\n");
+ depthflags = 0;
+ depthflags1 = 0;
+ }
+ if (NDIPV6_DEBUG && ipv6)
+ printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
+ lib_nd_no_nh_found++;
+}
+
+/* Added for Multiport changes*/
+int get_dest_mac_addr_port(const uint32_t ipaddr,
+ uint32_t *phy_port, struct ether_addr *hw_addr)
+{
+ lib_arp_get_mac_req++;
+ uint32_t nhip = 0;
+
+ nhip = get_nh(ipaddr, phy_port);
+ if (nhip == 0) {
+ if (ARPICMP_DEBUG && ipaddr)
+ printf("ARPICMP no nh found for ip %x, port %d\n",
+ ipaddr, *phy_port);
+ //return 0;
+ return NH_NOT_FOUND;
+ }
+
+ struct arp_entry_data *ret_arp_data = NULL;
+ struct arp_key_ipv4 tmp_arp_key;
+ tmp_arp_key.port_id = *phy_port;/* Changed for Multi Port*/
+ tmp_arp_key.ip = nhip;
+
+ ret_arp_data = retrieve_arp_entry(tmp_arp_key);
+ if (ret_arp_data == NULL) {
+ if (ARPICMP_DEBUG && ipaddr) {
+ printf
+ ("ARPICMP no arp entry found for ip %x, port %d\n",
+ ipaddr, *phy_port);
+ print_arp_table();
+ }
+ lib_arp_no_arp_entry_found++;
+ return ARP_NOT_FOUND;
+ }
+ ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
+ lib_arp_arp_entry_found++;
+ return ARP_FOUND;
+}
+
+/*ND IPv6 */
+int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t phy_port,
+ struct ether_addr *hw_addr, uint8_t nhipv6[])
+{
+ int i = 0, j = 0, flag = 0;
+ lib_nd_get_mac_req++;
+
+ if (ipv6addr)
+ get_nh_ipv6(ipv6addr, &phy_port, nhipv6);
+ for (j = 0; j < 16; j++) {
+ if (nhipv6[j])
+ flag++;
+ }
+ if (flag == 0) {
+ if (ipv6addr) {
+ if (NDIPV6_DEBUG && ipv6addr)
+ printf("NDIPV6 no nh found for ipv6 "
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x, port %d\n",
+ ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
+ ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
+ ipv6addr[8], ipv6addr[9], ipv6addr[10],
+ ipv6addr[11], ipv6addr[12], ipv6addr[13],
+ ipv6addr[14], ipv6addr[15], phy_port);
+ return 0;
+ }
+ }
+
+ struct nd_entry_data *ret_nd_data = NULL;
+ struct nd_key_ipv6 tmp_nd_key;
+ tmp_nd_key.port_id = phy_port;
+
+ for (i = 0; i < 16; i++)
+ tmp_nd_key.ipv6[i] = nhipv6[i];
+
+ ret_nd_data = retrieve_nd_entry(tmp_nd_key);
+ if (ret_nd_data == NULL) {
+ if (NDIPV6_DEBUG && ipv6addr) {
+ printf("NDIPV6 no nd entry found for ip %x, port %d\n",
+ ipv6addr[0], phy_port);
+ }
+ lib_nd_no_arp_entry_found++;
+ return 0;
+ }
+ ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
+ lib_nd_nd_entry_found++;
+ return 1;
+
+}
+
+/*ND IPv6 */
+int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
+ struct ether_addr *hw_addr, uint8_t nhipv6[])
+{
+ int i = 0, j = 0, flag = 0;
+ lib_nd_get_mac_req++;
+
+ get_nh_ipv6(ipv6addr, phy_port, nhipv6);
+ for (j = 0; j < 16; j++) {
+ if (nhipv6[j])
+ flag++;
+ }
+ if (flag == 0) {
+ if (NDIPV6_DEBUG && ipv6addr)
+ printf("NDIPV6 no nh found for ipv6 "
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x, port %d\n",
+ ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
+ ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
+ ipv6addr[8], ipv6addr[9], ipv6addr[10],
+ ipv6addr[11], ipv6addr[12], ipv6addr[13],
+ ipv6addr[14], ipv6addr[15], *phy_port);
+ return 0;
+ }
+
+ struct nd_entry_data *ret_nd_data = NULL;
+ struct nd_key_ipv6 tmp_nd_key;
+ tmp_nd_key.port_id = *phy_port;
+
+ for (i = 0; i < 16; i++)
+ tmp_nd_key.ipv6[i] = nhipv6[i];
+
+ ret_nd_data = retrieve_nd_entry(tmp_nd_key);
+ if (ret_nd_data == NULL) {
+ if (NDIPV6_DEBUG && ipv6addr) {
+ printf("NDIPV6 no nd entry found for ip %x, port %d\n",
+ ipv6addr[0], *phy_port);
+ }
+ lib_nd_no_arp_entry_found++;
+ return 0;
+ }
+ ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
+ lib_nd_nd_entry_found++;
+ return 1;
+
+}
+
+/*
+ * ARP table
+ */
+struct lib_arp_arp_table_entry {
+ struct rte_pipeline_table_entry head;
+ uint64_t macaddr;
+};
+
+static const char *arp_op_name(uint16_t arp_op)
+{
+ switch (CHECK_ENDIAN_16(arp_op)) {
+ case (ARP_OP_REQUEST):
+ return "ARP Request";
+ case (ARP_OP_REPLY):
+ return "ARP Reply";
+ case (ARP_OP_REVREQUEST):
+ return "Reverse ARP Request";
+ case (ARP_OP_REVREPLY):
+ return "Reverse ARP Reply";
+ case (ARP_OP_INVREQUEST):
+ return "Peer Identify Request";
+ case (ARP_OP_INVREPLY):
+ return "Peer Identify Reply";
+ default:
+ break;
+ }
+ return "Unkwown ARP op";
+}
+
+static void print_icmp_packet(struct icmp_hdr *icmp_h)
+{
+ printf(" ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
+ icmp_h->icmp_type,
+ (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
+ (icmp_h->icmp_type ==
+ IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")), icmp_h->icmp_code,
+ CHECK_ENDIAN_16(icmp_h->icmp_ident),
+ CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
+}
+
+static void print_ipv4_h(struct ipv4_hdr *ip_h)
+{
+ struct icmp_hdr *icmp_h =
+ (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
+ printf(" IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
+ (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
+ ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
+ if (ip_h->next_proto_id == IPPROTO_ICMP)
+ print_icmp_packet(icmp_h);
+}
+
+static void print_arp_packet(struct arp_hdr *arp_h)
+{
+ printf(" ARP: hrd=%d proto=0x%04x hln=%d "
+ "pln=%d op=%u (%s)\n",
+ CHECK_ENDIAN_16(arp_h->arp_hrd),
+ CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
+ arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
+ arp_op_name(arp_h->arp_op));
+
+ if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
+ printf("incorrect arp_hrd format for IPv4 ARP (%d)\n",
+ (arp_h->arp_hrd));
+ } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
+ printf("incorrect arp_pro format for IPv4 ARP (%d)\n",
+ (arp_h->arp_pro));
+ } else if (arp_h->arp_hln != 6) {
+ printf("incorrect arp_hln format for IPv4 ARP (%d)\n",
+ arp_h->arp_hln);
+ } else if (arp_h->arp_pln != 4) {
+ printf("incorrect arp_pln format for IPv4 ARP (%d)\n",
+ arp_h->arp_pln);
+ } else {
+ // print remainder of ARP request
+ printf(" sha=%02X:%02X:%02X:%02X:%02X:%02X",
+ arp_h->arp_data.arp_sha.addr_bytes[0],
+ arp_h->arp_data.arp_sha.addr_bytes[1],
+ arp_h->arp_data.arp_sha.addr_bytes[2],
+ arp_h->arp_data.arp_sha.addr_bytes[3],
+ arp_h->arp_data.arp_sha.addr_bytes[4],
+ arp_h->arp_data.arp_sha.addr_bytes[5]);
+ printf(" sip=%d.%d.%d.%d\n",
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
+ CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
+ printf(" tha=%02X:%02X:%02X:%02X:%02X:%02X",
+ arp_h->arp_data.arp_tha.addr_bytes[0],
+ arp_h->arp_data.arp_tha.addr_bytes[1],
+ arp_h->arp_data.arp_tha.addr_bytes[2],
+ arp_h->arp_data.arp_tha.addr_bytes[3],
+ arp_h->arp_data.arp_tha.addr_bytes[4],
+ arp_h->arp_data.arp_tha.addr_bytes[5]);
+ printf(" tip=%d.%d.%d.%d\n",
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
+ (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
+ CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
+ }
+}
+
+static void print_eth(struct ether_hdr *eth_h)
+{
+ printf(" ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
+ eth_h->s_addr.addr_bytes[0],
+ eth_h->s_addr.addr_bytes[1],
+ eth_h->s_addr.addr_bytes[2],
+ eth_h->s_addr.addr_bytes[3],
+ eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
+ printf(" dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eth_h->d_addr.addr_bytes[0],
+ eth_h->d_addr.addr_bytes[1],
+ eth_h->d_addr.addr_bytes[2],
+ eth_h->d_addr.addr_bytes[3],
+ eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
+
+}
+
+static void
+print_mbuf(const char *rx_tx, unsigned int portid, struct rte_mbuf *mbuf,
+ unsigned int line)
+{
+ struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
+ struct arp_hdr *arp_h =
+ (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+ struct ipv4_hdr *ipv4_h =
+ (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+
+ printf("%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
+ rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
+ print_eth(eth_h);
+ switch (rte_cpu_to_be_16(eth_h->ether_type)) {
+ case ETHER_TYPE_IPv4:
+ print_ipv4_h(ipv4_h);
+ break;
+ case ETHER_TYPE_ARP:
+ print_arp_packet(arp_h);
+ break;
+ default:
+ printf(" unknown packet type\n");
+ break;
+ }
+ fflush(stdout);
+}
+
+struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key)
+{
+ struct arp_entry_data *ret_arp_data = NULL;
+ arp_key.filler1 = 0;
+ arp_key.filler2 = 0;
+ arp_key.filler3 = 0;
+
+ int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
+ (void **)&ret_arp_data);
+ if (ret < 0) {
+ if (ARPICMP_DEBUG)
+ printf("arp-hash lookup failed ret %d, "
+ "EINVAL %d, ENOENT %d\n",
+ ret, EINVAL, ENOENT);
+ } else {
+ return ret_arp_data;
+ }
+
+ return NULL;
+}
+
+/*
+* ND IPv6
+* Validate if key-value pair already exists in the hash table
+* for given key - ND IPv6
+*
+*/
+struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
+{
+ struct nd_entry_data *ret_nd_data = NULL;
+ nd_key.filler1 = 0;
+ nd_key.filler2 = 0;
+ nd_key.filler3 = 0;
+
+ /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
+ int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
+ (void **)&ret_nd_data);
+ if (ret < 0) {
+ if (NDIPV6_DEBUG)
+ printf("nd-hash: no lookup Entry Found - "
+ "ret %d, EINVAL %d, ENOENT %d\n",
+ ret, EINVAL, ENOENT);
+ } else {
+ return ret_nd_data;
+ }
+
+ return NULL;
+}
+
+void print_arp_table(void)
+{
+ const void *next_key;
+ void *next_data;
+ uint32_t iter = 0;
+
+ printf("\tport hw addr status ip addr\n");
+
+ while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
+ >= 0) {
+
+ struct arp_entry_data *tmp_arp_data =
+ (struct arp_entry_data *)next_data;
+ struct arp_key_ipv4 tmp_arp_key;
+ memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
+ printf
+ ("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
+ tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
+ tmp_arp_data->eth_addr.addr_bytes[1],
+ tmp_arp_data->eth_addr.addr_bytes[2],
+ tmp_arp_data->eth_addr.addr_bytes[3],
+ tmp_arp_data->eth_addr.addr_bytes[4],
+ tmp_arp_data->eth_addr.addr_bytes[5],
+ tmp_arp_data->status ==
+ COMPLETE ? "COMPLETE" : "INCOMPLETE",
+ (tmp_arp_data->ip >> 24),
+ ((tmp_arp_data->ip & 0x00ff0000) >> 16),
+ ((tmp_arp_data->ip & 0x0000ff00) >> 8),
+ ((tmp_arp_data->ip & 0x000000ff)));
+ }
+
+ uint32_t i = 0;
+ printf("\nARP routing table has %d entries\n", arp_route_tbl_index);
+ printf("\nIP_Address Mask Port NH_IP_Address\n");
+ for (i = 0; i < arp_route_tbl_index; i++) {
+ printf("0x%x 0x%x %d 0x%x\n",
+ lib_arp_route_table[i].ip,
+ lib_arp_route_table[i].mask,
+ lib_arp_route_table[i].port, lib_arp_route_table[i].nh);
+ }
+
+ printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, "
+ "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
+ lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
+ lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
+ lib_arp_populate_called, lib_arp_delete_called,
+ lib_arp_duplicate_found);
+
+ printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
+}
+
+/* ND IPv6 */
+void print_nd_table(void)
+{
+ const void *next_key;
+ void *next_data;
+ uint32_t iter = 0;
+ uint8_t ii = 0, j = 0, k = 0;
+
+ printf("\tport hw addr status ip addr\n");
+
+ while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
+ 0) {
+
+ struct nd_entry_data *tmp_nd_data =
+ (struct nd_entry_data *)next_data;
+ struct nd_key_ipv6 tmp_nd_key;
+ memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
+ printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n",
+ tmp_nd_data->port,
+ tmp_nd_data->eth_addr.addr_bytes[0],
+ tmp_nd_data->eth_addr.addr_bytes[1],
+ tmp_nd_data->eth_addr.addr_bytes[2],
+ tmp_nd_data->eth_addr.addr_bytes[3],
+ tmp_nd_data->eth_addr.addr_bytes[4],
+ tmp_nd_data->eth_addr.addr_bytes[5],
+ tmp_nd_data->status ==
+ COMPLETE ? "COMPLETE" : "INCOMPLETE");
+ printf("\t\t\t\t\t\t");
+ for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
+ printf("%02X%02X ", tmp_nd_data->ipv6[ii],
+ tmp_nd_data->ipv6[ii + 1]);
+ }
+ printf("\n");
+ }
+
+ uint32_t i = 0;
+ printf("\n\nND IPV6 routing table has %d entries\n",
+ nd_route_tbl_index);
+ printf("\nIP_Address Depth Port NH_IP_Address\n");
+ for (i = 0; i < nd_route_tbl_index; i++) {
+ printf("\n");
+
+ for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
+ printf("%02X%02X ", lib_nd_route_table[i].ipv6[j],
+ lib_nd_route_table[i].ipv6[j + 1]);
+ }
+
+ printf
+ ("\n\t\t\t %d %d\n",
+ lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
+ printf("\t\t\t\t\t\t\t\t\t");
+ for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
+ printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
+ lib_nd_route_table[i].ipv6[k + 1]);
+ }
+ }
+ printf("\nND IPV6 Stats:\nTotal Queries %u, ok_NH %u, no_NH %u,"
+ "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
+ lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
+ lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
+ lib_nd_populate_called, lib_nd_delete_called,
+ lib_nd_duplicate_found);
+ printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
+}
+
+void remove_arp_entry(uint32_t ipaddr, uint8_t portid)
+{
+
+ /* need to lock here if multi-threaded... */
+ /* rte_hash_del_key is not thread safe */
+ struct arp_key_ipv4 arp_key;
+ arp_key.port_id = portid;
+ arp_key.ip = ipaddr;
+ arp_key.filler1 = 0;
+ arp_key.filler2 = 0;
+ arp_key.filler3 = 0;
+
+ lib_arp_delete_called++;
+
+ if (ARPICMP_DEBUG)
+ printf("remove_arp_entry ip %x, port %d\n", arp_key.ip,
+ arp_key.port_id);
+ rte_hash_del_key(arp_hash_handle, &arp_key);
+}
+
+/* ND IPv6 */
+void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
+{
+ /* need to lock here if multi-threaded */
+ /* rte_hash_del_key is not thread safe */
+ int i = 0;
+ struct nd_key_ipv6 nd_key;
+ nd_key.port_id = portid;
+ /* arp_key.ip = rte_bswap32(ipaddr); */
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ nd_key.ipv6[i] = ipv6addr[i];
+
+ nd_key.filler1 = 0;
+ nd_key.filler2 = 0;
+ nd_key.filler3 = 0;
+
+ lib_nd_delete_called++;
+
+ if (NDIPV6_DEBUG) {
+ printf("Deletes rte hash table nd entry for port %d ipv6=",
+ nd_key.port_id);
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2)
+ printf("%02X%02X ", nd_key.ipv6[i], nd_key.ipv6[i + 1]);
+ }
+ rte_hash_del_key(nd_hash_handle, &nd_key);
+}
+
+void
+populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
+ uint8_t portid)
+{
+ /* need to lock here if multi-threaded */
+ /* rte_hash_add_key_data is not thread safe */
+ struct arp_key_ipv4 arp_key;
+ arp_key.port_id = portid;
+ arp_key.ip = ipaddr;
+ arp_key.filler1 = 0;
+ arp_key.filler2 = 0;
+ arp_key.filler3 = 0;
+
+ lib_arp_populate_called++;
+
+ if (ARPICMP_DEBUG)
+ printf("populate_arp_entry ip %x, port %d\n", arp_key.ip,
+ arp_key.port_id);
+ struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key);
+ if (new_arp_data
+ && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
+ if (ARPICMP_DEBUG)
+ printf("arp_entry exists ip%x, port %d\n", arp_key.ip,
+ arp_key.port_id);
+ lib_arp_duplicate_found++;
+ return;
+ }
+ new_arp_data = (struct arp_entry_data *)
+ malloc(sizeof(struct arp_entry_data));
+ if (new_arp_data == NULL) {
+ printf("populate_arp_entry:new_arp_data is NULL\n");
+ return;
+ }
+ new_arp_data->eth_addr = *hw_addr;
+ new_arp_data->status = INCOMPLETE;
+ new_arp_data->port = portid;
+ new_arp_data->ip = ipaddr;
+ rte_hash_add_key_data(arp_hash_handle, &arp_key, new_arp_data);
+
+ if (ARPICMP_DEBUG) {
+ // print entire hash table
+ printf("\tARP: table update - hwaddr= "
+ "%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d "
+ "on port=%d\n",
+ new_arp_data->eth_addr.addr_bytes[0],
+ new_arp_data->eth_addr.addr_bytes[1],
+ new_arp_data->eth_addr.addr_bytes[2],
+ new_arp_data->eth_addr.addr_bytes[3],
+ new_arp_data->eth_addr.addr_bytes[4],
+ new_arp_data->eth_addr.addr_bytes[5],
+ (arp_key.ip >> 24),
+ ((arp_key.ip & 0x00ff0000) >> 16),
+ ((arp_key.ip & 0x0000ff00) >> 8),
+ ((arp_key.ip & 0x000000ff)), portid);
+ /* print_arp_table(); */
+ puts("");
+ }
+}
+
+/*
+* ND IPv6
+*
+* Install key - data pair in Hash table - From Pipeline Configuration
+*
+*/
+int
+populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
+ uint8_t portid)
+{
+
+ /* need to lock here if multi-threaded */
+ /* rte_hash_add_key_data is not thread safe */
+ uint8_t i;
+ struct nd_key_ipv6 nd_key;
+ nd_key.port_id = portid;
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
+ nd_key.ipv6[i] = ipv6[i];
+
+ printf("\n");
+ nd_key.filler1 = 0;
+ nd_key.filler2 = 0;
+ nd_key.filler3 = 0;
+
+ lib_nd_populate_called++;
+
+ /*Validate if key-value pair already
+ * exists in the hash table for ND IPv6
+ */
+ struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
+
+ if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr,
+ hw_addr)) {
+
+ if (NDIPV6_DEBUG) {
+ printf("nd_entry exists port %d ipv6 = ",
+ nd_key.port_id);
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
+
+ printf("%02X%02X ", nd_key.ipv6[i],
+ nd_key.ipv6[i + 1]);
+ }
+ }
+
+ lib_nd_duplicate_found++;
+ if (NDIPV6_DEBUG)
+ printf("nd_entry exists\n");
+ return 0;
+ }
+
+ new_nd_data = (struct nd_entry_data *)
+ malloc(sizeof(struct nd_entry_data));
+ if (new_nd_data == NULL) {
+ printf("populate_nd_entry: new_nd_data is NULL\n");
+ return 0;
+ }
+ new_nd_data->eth_addr = *hw_addr;
+ new_nd_data->status = COMPLETE;
+ new_nd_data->port = portid;
+
+ if (NDIPV6_DEBUG)
+ printf("populate_nd_entry ipv6=");
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
+ new_nd_data->ipv6[i] = ipv6[i];
+
+ if (NDIPV6_DEBUG) {
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
+
+ printf("%02X%02X ", new_nd_data->ipv6[i],
+ new_nd_data->ipv6[i + 1]);
+ }
+ }
+
+ /*Add a key-data pair at hash table for ND IPv6 static routing */
+ rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
+
+ if (NDIPV6_DEBUG)
+ printf("\n....Added a key-data pair at rte hash table "
+ "for ND IPv6 static routing\n");
+
+ if (NDIPV6_DEBUG) {
+ /* print entire hash table */
+ printf("\tND: table update - hwaddr= "
+ "%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
+ new_nd_data->eth_addr.addr_bytes[0],
+ new_nd_data->eth_addr.addr_bytes[1],
+ new_nd_data->eth_addr.addr_bytes[2],
+ new_nd_data->eth_addr.addr_bytes[3],
+ new_nd_data->eth_addr.addr_bytes[4],
+ new_nd_data->eth_addr.addr_bytes[5], portid);
+ printf("\tipv6=");
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
+ new_nd_data->ipv6[i] = ipv6[i];
+ printf("%02X%02X ", new_nd_data->ipv6[i],
+ new_nd_data->ipv6[i + 1]);
+ }
+
+ printf("\n");
+
+ puts("");
+ }
+ return 1;
+}
+
+void print_pkt1(struct rte_mbuf *pkt)
+{
+ uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
+ int i = 0, j = 0;
+ printf("\nPacket Contents...\n");
+ for (i = 0; i < 20; i++) {
+ for (j = 0; j < 20; j++)
+ printf("%02x ", rd[(20 * i) + j]);
+ printf("\n");
+ }
+}
+
+struct ether_addr broadcast_ether_addr = {
+ .addr_bytes[0] = 0xFF,
+ .addr_bytes[1] = 0xFF,
+ .addr_bytes[2] = 0xFF,
+ .addr_bytes[3] = 0xFF,
+ .addr_bytes[4] = 0xFF,
+ .addr_bytes[5] = 0xFF,
+};
+
+static const struct ether_addr null_ether_addr = {
+ .addr_bytes[0] = 0x00,
+ .addr_bytes[1] = 0x00,
+ .addr_bytes[2] = 0x00,
+ .addr_bytes[3] = 0x00,
+ .addr_bytes[4] = 0x00,
+ .addr_bytes[5] = 0x00,
+};
+
+#define MAX_NUM_MAC_ADDRESS 16
+struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
+{.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
+{.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
+{.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
+{.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
+{.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
+{.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
+{.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
+{.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
+{.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
+{.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
+{.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
+{.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
+{.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
+{.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
+{.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
+{.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
+};
+
+struct ether_addr *get_link_hw_addr(uint8_t out_port)
+{
+ return &link_hw_addr[out_port];
+}
+
+static void
+request_icmp_echo(unsigned int port_id, uint32_t ip, struct ether_addr *gw_addr)
+{
+ struct ether_hdr *eth_h;
+ struct ipv4_hdr *ip_h;
+ struct icmp_hdr *icmp_h;
+
+ struct app_link_params *link;
+ link = &myApp->link_params[port_id];
+ arp_port_addresses[port_id].ip = link->ip;
+ arp_port_addresses[port_id].mac_addr = link->mac_addr;
+
+ struct rte_mbuf *icmp_pkt = lib_arp_pkt;
+ if (icmp_pkt == NULL) {
+ if (ARPICMP_DEBUG)
+ printf("Error allocating icmp_pkt rte_mbuf\n");
+ return;
+ }
+
+ eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
+ ether_addr_copy(gw_addr, &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)
+ &arp_port_addresses[port_id].mac_addr, &eth_h->s_addr);
+ eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
+
+ ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+ icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
+
+ ip_h->version_ihl = IP_VHL_DEF;
+ ip_h->type_of_service = 0;
+ ip_h->total_length =
+ rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
+ ip_h->packet_id = 0xaabb;
+ ip_h->fragment_offset = 0x0000;
+ ip_h->time_to_live = 64;
+ ip_h->next_proto_id = IPPROTO_ICMP;
+ ip_h->src_addr = rte_bswap32(arp_port_addresses[port_id].ip);
+ ip_h->dst_addr = ip;
+
+ ip_h->hdr_checksum = 0;
+ ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
+
+ icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
+ icmp_h->icmp_code = 0;
+ icmp_h->icmp_ident = 0xdead;
+ icmp_h->icmp_seq_nb = 0xbeef;
+
+ icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
+
+ icmp_pkt->pkt_len =
+ sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
+ sizeof(struct icmp_hdr);
+ icmp_pkt->data_len = icmp_pkt->pkt_len;
+
+ if (ARPICMP_DEBUG) {
+ printf("Sending echo request\n");
+ print_mbuf("TX", port_id, icmp_pkt, __LINE__);
+ }
+
+ rte_pipeline_port_out_packet_insert(gp_arp->p.p,
+ gp_arp->outport_id[port_id], icmp_pkt);
+ gp_arp->sentPktCount++;
+}
+
+void request_echo(unsigned int port_id, uint32_t ip)
+{
+ (void)port_id;
+ (void)ip;
+
+ struct ether_addr gw_addr;
+ uint32_t dest_ip = rte_bswap32(ip);
+ uint32_t phy_port;
+
+ if (get_dest_mac_addr_port(dest_ip, &phy_port, &gw_addr) == ARP_FOUND) {
+ request_icmp_echo(phy_port, ip, &gw_addr);
+ return;
+ }
+
+ if (ARPICMP_DEBUG)
+ printf("Sending echo request ... get mac failed.\n");
+}
+
+void request_arp(uint8_t port_id, uint32_t ip, struct rte_pipeline *rte_p)
+{
+ (void)port_id;
+ (void)ip;
+
+ struct ether_hdr *eth_h;
+ struct arp_hdr *arp_h;
+
+ struct app_link_params *link;
+ link = &myApp->link_params[port_id];
+ arp_port_addresses[port_id].ip = link->ip;
+ arp_port_addresses[port_id].mac_addr = link->mac_addr;
+
+ struct rte_mbuf *arp_pkt = lib_arp_pkt;
+
+ if (arp_pkt == NULL) {
+ if (ARPICMP_DEBUG)
+ printf("Error allocating arp_pkt rte_mbuf\n");
+ return;
+ }
+
+ eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
+
+ ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)
+ &arp_port_addresses[port_id].mac_addr, &eth_h->s_addr);
+ eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
+
+ arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+ arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
+ arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
+ arp_h->arp_hln = ETHER_ADDR_LEN;
+ arp_h->arp_pln = sizeof(uint32_t);
+ arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
+
+ ether_addr_copy((struct ether_addr *)
+ &arp_port_addresses[port_id].mac_addr,
+ &arp_h->arp_data.arp_sha);
+ arp_h->arp_data.arp_sip =
+ rte_cpu_to_be_32(arp_port_addresses[port_id].ip);
+ ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
+ arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
+ printf("arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
+ arp_h->arp_data.arp_sip);
+ /* mmcd changed length from 60 to 42 -
+ * real length of arp request, no padding on ethernet needed -
+ * looks now like linux arp
+ */
+
+ arp_pkt->pkt_len = 42;
+ arp_pkt->data_len = 42;
+
+ if (ARPICMP_DEBUG) {
+ printf("Sending arp request\n");
+ print_mbuf("TX", port_id, arp_pkt, __LINE__);
+ }
+
+ rte_pipeline_port_out_packet_insert(rte_p, port_id, arp_pkt);
+ gp_arp->sentPktCount++;
+
+}
+
+void request_arp_wrap(uint8_t port_id, uint32_t ip)
+{
+ request_arp(port_id, ip, gp_arp->p.p);
+}
+
+void process_arpicmp_pkt(
+ struct rte_mbuf *pkt,
+ uint32_t out_port,
+ uint32_t pkt_mask)
+{
+ uint8_t in_port_id = pkt->port;
+ struct app_link_params *link;
+ struct ether_hdr *eth_h;
+ struct arp_hdr *arp_h;
+ struct ipv4_hdr *ip_h;
+ struct icmp_hdr *icmp_h;
+ uint32_t cksum;
+ uint32_t ip_addr;
+ uint32_t req_tip;
+
+
+ eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+
+ if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
+ arp_h =
+ (struct arp_hdr *)((char *)eth_h +
+ sizeof(struct ether_hdr));
+ if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
+ printf
+ ("Invalid hardware format of hardware address - "
+ "not processing ARP req\n");
+ else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
+ printf
+ ("Invalid protocol address format - "
+ "not processing ARP req\n");
+ else if (arp_h->arp_hln != 6)
+ printf
+ ("Invalid hardware address length - "
+ "not processing ARP req\n");
+ else if (arp_h->arp_pln != 4)
+ printf
+ ("Invalid protocol address length - "
+ "not processing ARP req\n");
+ else {
+ link = &myApp->link_params[in_port_id];
+ arp_port_addresses[in_port_id].ip = link->ip;
+ arp_port_addresses[in_port_id].mac_addr =
+ link->mac_addr;
+
+ if (arp_h->arp_data.arp_tip !=
+ rte_bswap32(arp_port_addresses[in_port_id].ip)) {
+ printf
+ ("ARP requested IP address mismatches "
+ "interface IP - discarding\n");
+ printf("arp_tip = %x\n",
+ arp_h->arp_data.arp_tip);
+ printf("arp_port_addresses = %x\n",
+ arp_port_addresses[in_port_id].ip);
+ printf("in_port_id = %x\n", in_port_id);
+ printf("arp_port_addresses[0] = %x\n",
+ arp_port_addresses[0].ip);
+
+ rte_pipeline_ah_packet_drop(gp_arp->p.p,
+ pkt_mask);
+ gp_arp->droppedPktCount++;
+
+ }
+ /* revise conditionals to allow processing of
+ * requests with target ip = this ip and
+ * processing of replies to destination ip = this ip
+ */
+ else if (arp_h->arp_op ==
+ rte_cpu_to_be_16(ARP_OP_REQUEST)) {
+
+ if (ARPICMP_DEBUG) {
+ printf("arp_op %d, ARP_OP_REQUEST %d\n",
+ arp_h->arp_op,
+ rte_cpu_to_be_16(ARP_OP_REQUEST));
+ print_mbuf("RX", in_port_id, pkt, __LINE__);
+ }
+
+ populate_arp_entry((struct ether_addr *)
+ &arp_h->arp_data.arp_sha,
+ rte_cpu_to_be_32
+ (arp_h->arp_data.arp_sip),
+ in_port_id);
+
+ /* build reply */
+ req_tip = arp_h->arp_data.arp_tip;
+ ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
+
+ // set sender mac address -
+ ether_addr_copy((struct ether_addr *)&
+ arp_port_addresses[in_port_id].mac_addr,
+ &eth_h->s_addr);
+
+ arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
+ ether_addr_copy(&eth_h->s_addr,
+ &arp_h->arp_data.arp_sha);
+ arp_h->arp_data.arp_tip =
+ arp_h->arp_data.arp_sip;
+ arp_h->arp_data.arp_sip = req_tip;
+ ether_addr_copy(&eth_h->d_addr,
+ &arp_h->arp_data.arp_tha);
+
+ rte_pipeline_port_out_packet_insert(gp_arp->p.p,
+ out_port, pkt);
+ gp_arp->sentPktCount++;
+
+ } else if (arp_h->arp_op ==
+ rte_cpu_to_be_16(ARP_OP_REPLY)) {
+ // TODO: be sure that ARP request
+ //was actually sent!!!
+ if (ARPICMP_DEBUG) {
+ printf("ARP_OP_REPLY received");
+ print_mbuf("RX", in_port_id, pkt,
+ __LINE__);
+ }
+ populate_arp_entry((struct ether_addr *)
+ &arp_h->arp_data.arp_sha,
+ rte_bswap32(arp_h->
+ arp_data.arp_sip),
+ in_port_id);
+
+ /* To drop the packet from LB */
+ rte_pipeline_ah_packet_drop(gp_arp->p.p,
+ pkt_mask);
+ gp_arp->droppedPktCount++;
+
+ } else {
+ if (ARPICMP_DEBUG)
+ printf("Invalid ARP opcode - not "
+ "processing ARP req %x\n",
+ arp_h->arp_op);
+ }
+ }
+ } else {
+ ip_h =
+ (struct ipv4_hdr *)((char *)eth_h +
+ sizeof(struct ether_hdr));
+ icmp_h =
+ (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
+
+ if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
+
+ link = &myApp->link_params[in_port_id];
+ arp_port_addresses[in_port_id].ip = link->ip;
+ arp_port_addresses[in_port_id].mac_addr =
+ link->mac_addr;
+
+ if (!is_same_ether_addr((struct ether_addr *)
+ &arp_port_addresses[in_port_id].
+ mac_addr, &eth_h->d_addr)) {
+
+ if (ARPICMP_DEBUG)
+ printf("Ethernet frame not destined "
+ "for MAC address of received network "
+ "interface - discarding\n");
+
+ } else if (ip_h->next_proto_id != IPPROTO_ICMP) {
+ if (ARPICMP_DEBUG)
+ printf("IP protocol ID is not set to "
+ "ICMP - discarding\n");
+
+ } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
+ if (ARPICMP_DEBUG)
+ printf("IP version other than 4 - "
+ "discarding\n");
+
+ } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
+ if (ARPICMP_DEBUG)
+ printf("Unknown IHL - discarding\n");
+
+ } else {
+ if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
+ && icmp_h->icmp_code == 0) {
+ if (ARPICMP_DEBUG)
+ print_mbuf("RX", in_port_id,
+ pkt, __LINE__);
+
+ ip_addr = ip_h->src_addr;
+ ether_addr_copy(&eth_h->s_addr,
+ &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)
+ &arp_port_addresses
+ [in_port_id].mac_addr,
+ &eth_h->s_addr);
+
+ if (ip_h->dst_addr !=
+ rte_bswap32(arp_port_addresses
+ [in_port_id].ip)) {
+ if (ARPICMP_DEBUG) {
+ printf("IPv4 packet not destined for "
+ "configured IP on RX port - "
+ "discarding\n");
+ printf("ip_h->dst_addr = %u, "
+ "in_port_id = %u, "
+ "arp_port_addresses.ip = %u\n",
+ ip_h->dst_addr, in_port_id,
+ arp_port_addresses[in_port_id].ip);
+ }
+ } else {
+
+ if (is_multicast_ipv4_addr
+ (ip_h->dst_addr)) {
+ uint32_t ip_src;
+
+ ip_src = rte_be_to_cpu_32
+ (ip_addr);
+ if ((ip_src & 0x00000003) == 1)
+ ip_src = (ip_src &
+ 0xFFFFFFFC)
+ | 0x00000002;
+ else
+ ip_src = (ip_src &
+ 0xFFFFFFFC)
+ | 0x00000001;
+
+ ip_h->src_addr =
+ rte_cpu_to_be_32(ip_src);
+ ip_h->dst_addr = ip_addr;
+
+ ip_h->hdr_checksum = 0;
+ ip_h->hdr_checksum = ~rte_raw_cksum(
+ ip_h, sizeof(struct
+ ipv4_hdr));
+ } else {
+ ip_h->src_addr = ip_h->dst_addr;
+ ip_h->dst_addr = ip_addr;
+ }
+
+ icmp_h->icmp_type =
+ IP_ICMP_ECHO_REPLY;
+ cksum = ~icmp_h->icmp_cksum & 0xffff;
+ cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
+ cksum += htons(IP_ICMP_ECHO_REPLY << 8);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ icmp_h->icmp_cksum = ~cksum;
+
+ if (ARPICMP_DEBUG)
+ print_mbuf("TX", in_port_id, pkt, __LINE__);
+
+ rte_pipeline_port_out_packet_insert(gp_arp->p.p,
+ out_port, pkt);
+ gp_arp->sentPktCount++;
+
+ }
+ }
+ else if (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY
+ && icmp_h->icmp_code == 0) {
+ if (ARPICMP_DEBUG)
+ print_mbuf("RX", in_port_id,
+ pkt, __LINE__);
+
+ struct arp_key_ipv4 arp_key;
+ arp_key.port_id = in_port_id;
+ arp_key.ip =
+ rte_bswap32(ip_h->src_addr);
+ arp_key.filler1 = 0;
+ arp_key.filler2 = 0;
+ arp_key.filler3 = 0;
+
+ struct arp_entry_data *arp_entry =
+ retrieve_arp_entry(arp_key);
+ if (arp_entry == NULL) {
+ printf("Received unsolicited "
+ "ICMP echo reply from ip%x, "
+ "port %d\n",
+ arp_key.ip,
+ arp_key.port_id);
+ return;
+ }
+
+ arp_entry->status = COMPLETE;
+ /* To drop the packet from LB */
+ rte_pipeline_ah_packet_drop(gp_arp->p.p,
+ pkt_mask);
+ gp_arp->droppedPktCount++;
+ }
+ }
+ }
+ }
+}
+
+
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int my_inet_pton_ipv6(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return inet_pton_ipv4(src, dst);
+ case AF_INET6:
+ return inet_pton_ipv6(src, dst);
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton_ipv4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int inet_pton_ipv4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return 0;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return 0;
+ saw_digit = 1;
+ }
+ *tp = (unsigned char)new;
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return 0;
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return 0;
+ }
+ if (octets < 4)
+ return 0;
+
+ memcpy(dst, tmp, INADDRSZ);
+ return 1;
+}
+
+/* int
+ * inet_pton_ipv6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int inet_pton_ipv6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
+ const char *xdigits = 0, *curtok = 0;
+ int ch = 0, saw_xdigit = 0, count_xdigit = 0;
+ unsigned int val = 0;
+ unsigned int dbloct_count = 0;
+
+ memset((tp = tmp), '\0', IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return 0;
+ curtok = src;
+ saw_xdigit = count_xdigit = 0;
+ val = 0;
+
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr((xdigits = xdigits_l), ch);
+ if (pch == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ if (count_xdigit >= 4)
+ return 0;
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return 0;
+ saw_xdigit = 1;
+ count_xdigit++;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return 0;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return 0;
+ }
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char)((val >> 8) & 0xff);
+ *tp++ = (unsigned char)(val & 0xff);
+ saw_xdigit = 0;
+ count_xdigit = 0;
+ val = 0;
+ dbloct_count++;
+ continue;
+ }
+ if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton_ipv4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ dbloct_count += 2;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return 0;
+ }
+ if (saw_xdigit) {
+ if (tp + sizeof(int16_t) > endp)
+ return 0;
+ *tp++ = (unsigned char)((val >> 8) & 0xff);
+ *tp++ = (unsigned char)(val & 0xff);
+ dbloct_count++;
+ }
+ if (colonp != NULL) {
+ /* if we already have 8 double octets,
+ * having a colon means error
+ */
+ if (dbloct_count == 8)
+ return 0;
+
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[-i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return 0;
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return 1;
+}
+
+/**
+ * Function to classify ICMPv6 Packets based on NextHeader field in IPv6 Header.
+ * Updates ND Cache table with link layer addresses as received from Neighbor.
+ * Processes ICMPv6 Echo destined to local port and replys.
+ *
+ * @param pkt
+ * A pointer to the packet received from Loadbalancer pipeline
+ * @param out_port
+ * A pointer to the output port action
+ * @param pkt_num
+ * A packet number
+ *
+ * @return
+ * NULL
+ */
+
+void
+process_icmpv6_pkt(
+ struct rte_mbuf *pkt,
+ uint32_t out_port,
+ __rte_unused uint32_t pkt_num)
+{
+
+ uint8_t in_port_id = pkt->port;
+ struct app_link_params *link;
+ struct ether_hdr *eth_h;
+ struct ipv6_hdr *ipv6_h;
+ struct icmpv6_hdr *icmpv6_h;
+ struct icmpv6_nd_hdr *icmpv6_nd_h;
+ uint8_t ipv6_addr[16];
+ uint8_t i = 0, flag = 1;
+ uint8_t req_tipv6[16];
+
+ eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+ ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+ icmpv6_h =
+ (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
+ struct rte_mbuf *icmpv6_pkt = pkt;
+
+ link = &myApp->link_params[in_port_id];
+ icmpv6_port_addresses[in_port_id].mac_addr = link->mac_addr;
+
+ if (!is_same_ether_addr
+ ((struct ether_addr *)&icmpv6_port_addresses[in_port_id].mac_addr,
+ &eth_h->d_addr)) {
+ if (ARPICMP_DEBUG) {
+ printf("Ethernet frame not destined for MAC address "
+ "of received network interface - discarding\n");
+ }
+ } else {
+ if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REQUEST)
+ && (icmpv6_h->icmpv6_code == 0)) {
+ for (i = 0; i < 16; i++)
+ ipv6_addr[i] = ipv6_h->src_addr[i];
+
+ for (i = 0; i < 16; i++) {
+ if (ipv6_h->dst_addr[i] !=
+ icmpv6_port_addresses[in_port_id].ipv6[i]) {
+ flag++;
+ }
+ }
+ if (!flag) {
+ printf("IPv6 packet not destined for "
+ "configured IP on RX port - discarding\n");
+ } else {
+ {
+
+ ether_addr_copy(&eth_h->s_addr,
+ &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)
+ &icmpv6_port_addresses
+ [in_port_id].mac_addr,
+ &eth_h->s_addr);
+
+ for (i = 0; i < 16; i++)
+ ipv6_h->src_addr[i] =
+ ipv6_h->dst_addr[i];
+ for (i = 0; i < 16; i++)
+ ipv6_h->dst_addr[i] =
+ ipv6_addr[i];
+
+ icmpv6_h->icmpv6_type =
+ ICMPV6_ECHO_REPLY;
+
+ rte_pipeline_port_out_packet_insert
+ (gp_arp->p.p, out_port, icmpv6_pkt);
+ gp_arp->sentPktCount++;
+ }
+ }
+
+ } else if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REPLY)
+ && (icmpv6_h->icmpv6_code == 0)) {
+ struct nd_key_ipv6 nd_key;
+ nd_key.port_id = in_port_id;
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ nd_key.ipv6[i] = ipv6_h->src_addr[i];
+
+ nd_key.filler1 = 0;
+ nd_key.filler2 = 0;
+ nd_key.filler3 = 0;
+
+ /* Validate if key-value pair already
+ * exists in the hash table for ND IPv6
+ */
+ struct nd_entry_data *new_nd_data =
+ retrieve_nd_entry(nd_key);
+
+ if (new_nd_data == NULL) {
+ printf("Received unsolicited ICMPv6 echo "
+ "reply on port %d\n",
+ nd_key.port_id);
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
+ printf("%02X%02X ", nd_key.ipv6[i],
+ nd_key.ipv6[i + 1]);
+ }
+ return;
+ }
+
+ new_nd_data->status = COMPLETE;
+
+ } else
+ if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_SOLICITATION)
+ && (icmpv6_h->icmpv6_code == 0)) {
+
+ icmpv6_nd_h =
+ (struct icmpv6_nd_hdr *)((char *)icmpv6_h +
+ sizeof(struct icmpv6_hdr));
+ struct ether_addr *src_hw_addr = &eth_h->s_addr;
+ uint8_t src_ipv6[16], dst_ipv6[16];
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ src_ipv6[i] = ipv6_h->src_addr[i];
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ dst_ipv6[i] = ipv6_h->dst_addr[i];
+
+ // Check for Multicast Address
+ if ((IPV6_MULTICAST
+ && ((dst_ipv6[0] << 8) | dst_ipv6[1]))) {
+ if (populate_nd_entry
+ (src_hw_addr, src_ipv6, in_port_id)) {
+
+ //build a Neighbor Advertisement message
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ req_tipv6[i] =
+ icmpv6_nd_h->target_ipv6[i];
+
+ ether_addr_copy(&eth_h->s_addr,
+ &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)
+ &icmpv6_port_addresses
+ [in_port_id].mac_addr,
+ &eth_h->s_addr);
+
+ // set sender mac address
+ ether_addr_copy(&eth_h->s_addr,
+ &icmpv6_nd_h->
+ link_layer_address);
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ ipv6_h->dst_addr[i] =
+ ipv6_h->src_addr[i];
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ ipv6_h->src_addr[i] =
+ req_tipv6[i];
+ icmpv6_h->icmpv6_type =
+ ICMPV6_NEIGHBOR_ADVERTISEMENT;
+ icmpv6_nd_h->type =
+ e_Target_Link_Layer_Address;
+ icmpv6_nd_h->icmpv6_reserved |=
+ rte_cpu_to_be_32
+ (NEIGHBOR_SOLICITATION_SET);
+
+ rte_pipeline_port_out_packet_insert
+ (gp_arp->p.p, out_port, icmpv6_pkt);
+ gp_arp->sentPktCount++;
+ }
+ } else {
+ if (ARPICMP_DEBUG) {
+ printf("Non-Multicasted Neighbor "
+ "Solicitation Message Received, "
+ "can't do Address Resolution\n");
+ printf("............Some one else "
+ "is the target host here !!!\n");
+ }
+ }
+
+ } else
+ if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_ADVERTISEMENT)
+ && (icmpv6_h->icmpv6_code == 0)) {
+ struct ether_addr *src_hw_addr = &eth_h->s_addr;
+ uint8_t ipv6[16];
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ ipv6[i] = ipv6_h->src_addr[i];
+
+ if (populate_nd_entry(src_hw_addr, ipv6, in_port_id))
+ if (ARPICMP_DEBUG)
+ printf("Now on, unicast IPv6 traffic "
+ "is possible\n");
+ // Now on, unicast IPv6 traffic is possible
+ } else {
+ if (ARPICMP_DEBUG) {
+ printf("ICMPv6 Type %d Not Supported yet !!!\n",
+ icmpv6_h->icmpv6_type);
+ }
+ }
+
+ }
+
+}
+
+void request_icmpv6_echo(uint32_t port_id, uint8_t ipv6[])
+{
+ (void)port_id;
+ (void)ipv6;
+ int i;
+
+ struct ether_addr gw_addr;
+ uint8_t nhipv6[16];
+ uint8_t dest_ipv6[16];
+ uint32_t phy_port;
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ dest_ipv6[i] = ipv6[i];
+
+ if (get_dest_mac_address_ipv6_port(dest_ipv6, &phy_port,
+ &gw_addr, nhipv6)) {
+ request_icmpv6_echo_message(phy_port, ipv6, &gw_addr);
+ return;
+ }
+
+ if (ARPICMP_DEBUG)
+ printf("Sending icmpv6 echo request ... get mac failed.\n");
+}
+
+void
+request_icmpv6_echo_message(uint16_t port_id, uint8_t ipv6[],
+ struct ether_addr *gw_addr)
+{
+ struct ether_hdr *eth_h;
+ struct ipv6_hdr *ipv6_h;
+ struct icmpv6_hdr *icmpv6_h;
+ struct icmpv6_info_hdr *icmpv6_info_h;
+ int i;
+ struct app_link_params *link;
+ link = &mylink[port_id];
+
+ for (i = 0; i < 16; i++)
+ icmpv6_port_addresses[port_id].ipv6[i] = link->ipv6[i];
+
+ icmpv6_port_addresses[port_id].mac_addr = link->mac_addr;
+
+ struct rte_mbuf *icmpv6_pkt = lib_icmpv6_pkt;
+ if (icmpv6_pkt == NULL) {
+ if (ARPICMP_DEBUG)
+ printf("Error allocating icmpv6_pkt rte_mbuf\n");
+ return;
+ }
+
+ eth_h = rte_pktmbuf_mtod(icmpv6_pkt, struct ether_hdr *);
+ ether_addr_copy(gw_addr, &eth_h->d_addr);
+ ether_addr_copy((struct ether_addr *)&icmpv6_port_addresses[port_id].
+ mac_addr, &eth_h->s_addr);
+ eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv6);
+
+ ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
+ icmpv6_h =
+ (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
+ icmpv6_info_h =
+ (struct icmpv6_info_hdr *)((char *)icmpv6_h +
+ sizeof(struct icmpv6_hdr));
+
+ ipv6_h->vtc_flow = 0x60000000;
+ ipv6_h->payload_len = 64;
+ ipv6_h->proto = 58;
+ ipv6_h->hop_limits = 64;
+
+ for (i = 0; i < 16; i++) {
+ ipv6_h->src_addr[i] = icmpv6_port_addresses[port_id].ipv6[i];
+ ipv6_h->dst_addr[i] = ipv6[i];
+ }
+
+ icmpv6_h->icmpv6_type = ICMPV6_ECHO_REQUEST;
+ icmpv6_h->icmpv6_code = 0;
+ icmpv6_info_h->icmpv6_ident = 0x5151;
+ icmpv6_info_h->icmpv6_seq_nb = 0x1;
+
+ icmpv6_h->icmpv6_cksum =
+ ~rte_raw_cksum(icmpv6_h, sizeof(struct icmpv6_hdr));
+
+ icmpv6_pkt->pkt_len =
+ sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr) +
+ sizeof(struct icmpv6_hdr);
+ icmpv6_pkt->data_len = icmpv6_pkt->pkt_len;
+
+ if (ARPICMP_DEBUG)
+ printf("Sending icmpv6 echo request\n");
+
+ rte_pipeline_port_out_packet_insert(gp_arp->p.p,
+ gp_arp->outport_id[port_id],
+ icmpv6_pkt);
+
+ gp_arp->sentPktCount++;
+}
+
+
+#endif
+
+static void *pipeline_arpicmp_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_arpicmp_msg_req_custom_handler,
+
+};
+
+static void *pipeline_arpicmp_msg_req_entry_dbg_handler(struct pipeline *p,
+ void *msg);
+static void *pipeline_arpicmp_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_ARPICMP_MSG_REQ_ENTRY_DBG] =
+ pipeline_arpicmp_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_arpicmp_msg_req_custom_handler(struct pipeline *p, void *msg)
+{
+ struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)p;
+ struct pipeline_custom_msg_req *req = msg;
+ pipeline_msg_req_handler f_handle;
+
+ f_handle = (req->subtype < PIPELINE_ARPICMP_MSG_REQS) ?
+ p_arp->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);
+}
+
+#ifdef VNF_ACL
+
+/* Not needed as no arguments are needed for TxRX
+ * ARP arguments are handled in ARP module
+ */
+int
+pipeline_arpicmp_parse_args(struct pipeline_arpicmp *p,
+ struct pipeline_params *params);
+int
+pipeline_arpicmp_parse_args(
+ __rte_unused struct pipeline_arpicmp *p,
+ struct pipeline_params *params)
+{
+
+ uint32_t i;
+ uint32_t arp_meta_offset_present = 0;
+
+ uint32_t arp_route_tbl_present = 0;
+ uint32_t nd_route_tbl_present = 0;
+ uint32_t ports_mac_list_present = 0;
+ uint32_t pktq_in_prv_present = 0;
+ uint32_t prv_to_pub_map_present = 0;
+
+ uint8_t n_prv_in_port = 0;
+ for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
+ in_port_dir_a[i] = 0; //make all RX ports ingress initially
+ prv_to_pub_map[i] = 0xff;
+ pub_to_prv_map[i] = 0xff;
+ }
+
+ for (i = 0; i < params->n_args; i++) {
+ char *arg_name = params->args_name[i];
+ char *arg_value = params->args_value[i];
+
+ if (ARPICMP_DEBUG > 2) {
+ printf("ARP args[%d]: %s %d, %s\n", i, arg_name,
+ atoi(arg_value), arg_value);
+ }
+ if (strcmp(arg_name, "arp_meta_offset") == 0) {
+ if (arp_meta_offset_present) {
+ printf("arp_meta_offset "
+ "initialized already\n");
+ return -1;
+ }
+ arp_meta_offset_present = 1;
+ arp_meta_offset = atoi(arg_value);
+ 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[5];
+ char *token = strtok(arg_value, "RXQ");
+ while (token) {
+ j = 0;
+ while ((j < 4) && (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 < 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;
+ }
+
+ /* 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);
+ if (rxport < PIPELINE_MAX_PORT_IN && txport < PIPELINE_MAX_PORT_IN){
+ 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);
+ }
+ else
+ return -1;
+ 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;
+ }
+
+ prv_to_pub_map[rxport] = txport;
+ pub_to_prv_map[txport] = rxport;
+ token = strtok(NULL, "(");
+ }
+
+ continue;
+ }
+
+ /* lib_arp_debug */
+ if (strcmp(arg_name, "lib_arp_debug") == 0) {
+ ARPICMP_DEBUG = atoi(arg_value);
+
+ continue;
+ }
+
+ /* ports_mac_list */
+ if (strcmp(arg_name, "ports_mac_list") == 0) {
+ ports_mac_list_present = 1;
+
+ uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
+
+ char byteStr[MAC_NUM_BYTES][3];
+ uint32_t byte[MAC_NUM_BYTES];
+
+ char *token = strtok(arg_value, " ");
+ while (token) {
+ k = 0;
+ for (i = 0; i < MAC_NUM_BYTES; i++) {
+ for (j = 0; j < 2; j++)
+ byteStr[i][j] = token[k++];
+ byteStr[i][j] = '\0';
+ k++;
+ }
+
+ for (i = 0; i < MAC_NUM_BYTES; i++)
+ byte[i] = strtoul(byteStr[i], NULL, 16);
+
+ if (ARPICMP_DEBUG) {
+ printf("token: %s", token);
+ for (i = 0; i < MAC_NUM_BYTES; i++)
+ printf(", byte[%u] %u", i,
+ byte[i]);
+ printf("\n");
+ }
+ //Populate the static arp_route_table
+ for (i = 0; i < MAC_NUM_BYTES; i++)
+ link_hw_addr
+ [link_hw_addr_array_idx].addr_bytes
+ [i] = byte[i];
+
+ link_hw_addr_array_idx++;
+ token = strtok(NULL, " ");
+ }
+
+ continue;
+ }
+
+ /* arp_route_tbl */
+ if (strcmp(arg_name, "arp_route_tbl") == 0) {
+ arp_route_tbl_present = 1;
+
+ uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
+ 0, i = 0, j = 0, k = 0, l = 0;
+ uint32_t arp_route_tbl_str_max_len = 10;
+ char dest_ip_str[arp_route_tbl_str_max_len];
+ char mask_str[arp_route_tbl_str_max_len];
+ char tx_port_str[arp_route_tbl_str_max_len];
+ char nh_ip_str[arp_route_tbl_str_max_len];
+ char *token = strtok(arg_value, "(");
+ while (token) {
+ i = 0;
+ while ((i < (arp_route_tbl_str_max_len - 1))
+ && (token[i] != ',')) {
+ dest_ip_str[i] = token[i];
+ i++;
+ }
+ dest_ip_str[i] = '\0';
+ dest_ip = strtoul(dest_ip_str, NULL, 16);
+
+ i++;
+ j = 0;
+ while ((j < (arp_route_tbl_str_max_len - 1))
+ && (token[i + j] != ',')) {
+ mask_str[j] = token[i + j];
+ j++;
+ }
+ mask_str[j] = '\0';
+ mask = strtoul(mask_str, NULL, 16);
+
+ j++;
+ k = 0;
+ while ((k < (arp_route_tbl_str_max_len - 1))
+ && (token[i + j + k] != ',')) {
+ tx_port_str[k] = token[i + j + k];
+ k++;
+ }
+ tx_port_str[k] = '\0';
+ //atoi(tx_port_str);
+ tx_port = strtoul(tx_port_str, NULL, 16);
+
+ k++;
+ l = 0;
+ while ((l < (arp_route_tbl_str_max_len - 1))
+ && (token[i + j + k + l] != ')')) {
+ nh_ip_str[l] = token[i + j + k + l];
+ l++;
+ }
+ nh_ip_str[l] = '\0';
+ //atoi(nh_ip_str);
+ nh_ip = strtoul(nh_ip_str, NULL, 16);
+
+ if (ARPICMP_DEBUG) {
+ printf("token: %s, "
+ "dest_ip_str: %s, dest_ip %u, "
+ "mask_str: %s, mask %u, "
+ "tx_port_str: %s, tx_port %u, "
+ "nh_ip_str: %s, nh_ip %u\n",
+ token, dest_ip_str, dest_ip,
+ mask_str, mask, tx_port_str,
+ tx_port, nh_ip_str, nh_ip);
+ }
+ #if 0
+ if (tx_port >= params->n_ports_out) {
+ printf("ARP-ICMP parse error - "
+ "incorrect tx_port %d, max %d\n",
+ tx_port, params->n_ports_out);
+ return -1;
+ }
+ #endif
+
+ //Populate the static arp_route_table
+ lib_arp_route_table[arp_route_tbl_index].ip =
+ dest_ip;
+ lib_arp_route_table[arp_route_tbl_index].mask =
+ mask;
+ lib_arp_route_table[arp_route_tbl_index].port =
+ tx_port;
+ lib_arp_route_table[arp_route_tbl_index].nh =
+ nh_ip;
+ arp_route_tbl_index++;
+ token = strtok(NULL, "(");
+ }
+
+ continue;
+ }
+ /*ND IPv6 */
+ /* nd_route_tbl */
+ if (strcmp(arg_name, "nd_route_tbl") == 0) {
+ nd_route_tbl_present = 1;
+
+ uint8_t dest_ipv6[16], depth = 0, tx_port =
+ 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
+ uint8_t nd_route_tbl_str_max_len = 128; //64;
+ char dest_ipv6_str[nd_route_tbl_str_max_len];
+ char depth_str[nd_route_tbl_str_max_len];
+ char tx_port_str[nd_route_tbl_str_max_len];
+ char nh_ipv6_str[nd_route_tbl_str_max_len];
+ char *token = strtok(arg_value, "(");
+ while (token) {
+ i = 0;
+ while ((i < (nd_route_tbl_str_max_len - 1))
+ && (token[i] != ',')) {
+ dest_ipv6_str[i] = token[i];
+ i++;
+ }
+ dest_ipv6_str[i] = '\0';
+ my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
+ &dest_ipv6);
+
+ i++;
+ j = 0;
+ while ((j < (nd_route_tbl_str_max_len - 1))
+ && (token[i + j] != ',')) {
+ depth_str[j] = token[i + j];
+ j++;
+ }
+ depth_str[j] = '\0';
+ //converting string char to integer
+ int s;
+ for (s = 0; depth_str[s] != '\0'; ++s)
+ depth = depth * 10 + depth_str[s] - '0';
+
+ j++;
+ k = 0;
+ while ((k < (nd_route_tbl_str_max_len - 1))
+ && (token[i + j + k] != ',')) {
+ tx_port_str[k] = token[i + j + k];
+ k++;
+ }
+ tx_port_str[k] = '\0';
+ //atoi(tx_port_str);
+ tx_port = strtoul(tx_port_str, NULL, 16);
+
+ k++;
+ l = 0;
+ while ((l < (nd_route_tbl_str_max_len - 1))
+ && (token[i + j + k + l] != ')')) {
+ nh_ipv6_str[l] = token[i + j + k + l];
+ l++;
+ }
+ nh_ipv6_str[l] = '\0';
+ my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
+ &nh_ipv6);
+
+ //Populate the static arp_route_table
+ for (i = 0; i < 16; i++) {
+ lib_nd_route_table
+ [nd_route_tbl_index].ipv6[i] =
+ dest_ipv6[i];
+ lib_nd_route_table
+ [nd_route_tbl_index].nhipv6[i] =
+ nh_ipv6[i];
+ }
+ lib_nd_route_table[nd_route_tbl_index].depth =
+ depth;
+ lib_nd_route_table[nd_route_tbl_index].port =
+ tx_port;
+
+ nd_route_tbl_index++;
+ token = strtok(NULL, "(");
+ } //while
+
+ continue;
+ }
+ /* any other */
+
+ }
+
+ #if 0
+ if (!arp_meta_offset_present) {
+ printf("ARPICMP: arp_meta_offset not initialized\n");
+ return -1;
+ }
+ #endif
+
+ if (!arp_route_tbl_present && !nd_route_tbl_present) {
+ printf("Neither arp_route_tbl_present nor "
+ "nd_route_tbl_present declared\n");
+ return -1;
+ }
+
+ if (!pktq_in_prv_present) {
+ printf("pktq_in_prv not declared\n");
+ return -1;
+ }
+
+ if (!ports_mac_list_present) {
+ printf("ports_mac_list not declared\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
+uint32_t arpicmp_pkt_print_count;
+static inline void
+pkt_key_arpicmp(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
+{
+
+ struct pipeline_arpicmp_in_port_h_arg *ap = arg;
+ struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
+
+ p_arp->receivedPktCount++;
+
+ uint8_t in_port_id = pkt->port;
+ #ifdef VNF_ACL
+ struct app_link_params *link;
+ #endif
+ uint8_t *protocol;
+ uint32_t pkt_mask = 1 << pkt_num;
+ uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
+
+ uint32_t prot_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
+
+ #ifdef VNF_ACL
+ uint32_t out_port;
+ #endif
+
+ uint16_t *eth_proto =
+ RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ #ifdef VNF_ACL
+ 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);
+ #endif
+
+ #ifdef IPV6
+ 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 ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
+ print_pkt1(pkt);
+ arpicmp_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);
+ }
+
+ #ifdef VNF_ACL
+ link = &myApp->link_params[in_port_id];
+ #endif
+
+ /* Classifier for ICMP pass-through*/
+ if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_ARP) ||
+ ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
+ && (*protocol == IP_PROTOCOL_ICMP)
+ #ifdef VNF_ACL
+ && (link->ip == rte_be_to_cpu_32(*dst_addr))
+ #endif
+ )) {
+
+ #ifdef VNF_ACL
+ out_port = p_arp->outport_id[in_port_id];
+ process_arpicmp_pkt(pkt, out_port, pkt_mask);
+ #else
+ process_arpicmp_pkt(pkt, ifm_get_port(in_port_id));
+ #endif
+ return;
+ }
+ #ifdef IPV6
+ else if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV6)
+ && (*protocol == ICMPV6_PROTOCOL_ID)) {
+ #ifdef VNF_ACL
+ out_port = p_arp->outport_id[in_port_id];
+ process_icmpv6_pkt(pkt, out_port, pkt_mask);
+ #else
+ process_icmpv6_pkt(pkt, ifm_get_port(in_port_id));
+ #endif
+
+ return;
+ }
+ #endif
+
+ /* Drop the pkt if not ARP/ICMP */
+ rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask);
+ p_arp->droppedPktCount++;
+
+}
+
+static inline void
+pkt4_key_arpicmp(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
+{
+
+ struct pipeline_arpicmp_in_port_h_arg *ap = arg;
+ struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
+
+ p_arp->receivedPktCount += 4;
+
+ uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
+ uint8_t in_port_id = pkt[0]->port;
+
+ uint32_t prot_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
+
+ /* header room + eth hdr size + src_aadr offset in ip header */
+ #ifdef VNF_ACL
+ uint32_t dst_addr_offset =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
+ #endif
+
+ 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);
+
+ #ifdef VNF_ACL
+ uint32_t out_port0;
+ uint32_t out_port1;
+ uint32_t out_port2;
+ uint32_t out_port3;
+ #endif
+
+ 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;
+ uint8_t *protocol1;
+ uint8_t *protocol2;
+ uint8_t *protocol3;
+
+ #ifdef VNF_ACL
+ uint32_t *dst_addr0 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset);
+ uint32_t *dst_addr1 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset);
+ uint32_t *dst_addr2 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset);
+ uint32_t *dst_addr3 =
+ RTE_MBUF_METADATA_UINT32_PTR(pkt[3], dst_addr_offset);
+
+ struct app_link_params *link0;
+ struct app_link_params *link1;
+ struct app_link_params *link2;
+ struct app_link_params *link3;
+
+ link0 = &myApp->link_params[pkt[0]->port];
+ link1 = &myApp->link_params[pkt[1]->port];
+ link2 = &myApp->link_params[pkt[2]->port];
+ link3 = &myApp->link_params[pkt[3]->port];
+ #endif
+
+ #ifdef IPV6
+ uint32_t prot_offset_ipv6 =
+ MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
+
+ #endif
+
+ #ifdef IPV6
+/* --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-- */
+ 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-- */
+ 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-- */
+ 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 ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
+ print_pkt1(pkt[0]);
+ arpicmp_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);
+ }
+
+
+ if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_ARP) ||
+ ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
+ && (*protocol0 == IP_PROTOCOL_ICMP)
+ #ifdef VNF_ACL
+ && (link0->ip == rte_be_to_cpu_32(*dst_addr0))
+ #endif
+ )) {
+
+ #ifdef VNF_ACL
+ out_port0 = p_arp->outport_id[pkt[0]->port];
+ process_arpicmp_pkt(pkt[0], out_port0, pkt_mask0);
+ #else
+ process_arpicmp_pkt(pkt[0], ifm_get_port(in_port_id));
+ #endif
+
+ goto PKT1;
+ }
+ #ifdef IPV6
+ else if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV6)
+ && (*protocol0 == ICMPV6_PROTOCOL_ID)) {
+
+ #ifdef VNF_ACL
+ out_port0 = p_arp->outport_id[pkt[0]->port];
+ process_icmpv6_pkt(pkt[0], out_port0, pkt_mask0);
+ #else
+ process_icmpv6_pkt(pkt[0], ifm_get_port(in_port_id));
+ #endif
+
+ goto PKT1;
+ }
+ #endif
+
+ /* Drop the pkt if not ARP/ICMP */
+ rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask0);
+ p_arp->droppedPktCount++;
+
+PKT1:
+ if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
+ print_pkt1(pkt[1]);
+ arpicmp_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);
+ }
+
+ if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_ARP) ||
+ ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
+ && (*protocol1 == IP_PROTOCOL_ICMP)
+ #ifdef VNF_ACL
+ && (link1->ip == rte_be_to_cpu_32(*dst_addr1))
+ #endif
+ )) {
+
+ #ifdef VNF_ACL
+ out_port1 = p_arp->outport_id[pkt[1]->port];
+ process_arpicmp_pkt(pkt[1], out_port1, pkt_mask1);
+ #else
+ process_arpicmp_pkt(pkt[1], ifm_get_port(in_port_id));
+ #endif
+ goto PKT2;
+ }
+ #ifdef IPV6
+ else if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV6)
+ && (*protocol1 == ICMPV6_PROTOCOL_ID)) {
+
+ #ifdef VNF_ACL
+ out_port1 = p_arp->outport_id[pkt[1]->port];
+ process_icmpv6_pkt(pkt[1], out_port1, pkt_mask1);
+ #else
+ process_icmpv6_pkt(pkt[1], ifm_get_port(in_port_id));
+ #endif
+
+ goto PKT2;
+ }
+ #endif
+
+ /* Drop the pkt if not ARP/ICMP */
+ rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask1);
+ p_arp->droppedPktCount++;
+
+PKT2:
+ if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
+ print_pkt1(pkt[2]);
+ arpicmp_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);
+ }
+
+ if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_ARP) ||
+ ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
+ && (*protocol2 == IP_PROTOCOL_ICMP)
+ #ifdef VNF_ACL
+ && (link2->ip == rte_be_to_cpu_32(*dst_addr2))
+ #endif
+ )) {
+
+ #ifdef VNF_ACL
+ out_port2 = p_arp->outport_id[pkt[2]->port];
+ process_arpicmp_pkt(pkt[2], out_port2, pkt_mask2);
+ #else
+ process_arpicmp_pkt(pkt[2], ifm_get_port(in_port_id));
+ #endif
+
+ goto PKT3;
+ }
+ #ifdef IPV6
+ else if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV6)
+ && (*protocol2 == ICMPV6_PROTOCOL_ID)) {
+
+ #ifdef VNF_ACL
+ out_port2 = p_arp->outport_id[pkt[2]->port];
+ process_icmpv6_pkt(pkt[2], out_port2, pkt_mask2);
+ #else
+ process_icmpv6_pkt(pkt[2], ifm_get_port(in_port_id));
+ #endif
+
+ goto PKT3;
+ }
+ #endif
+
+ /* Drop the pkt if not ARP/ICMP */
+ rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask2);
+ p_arp->droppedPktCount++;
+
+PKT3:
+ if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
+ print_pkt1(pkt[3]);
+ arpicmp_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);
+ }
+
+ if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_ARP) ||
+ ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
+ && (*protocol3 == IP_PROTOCOL_ICMP)
+
+ #ifdef VNF_ACL
+ && (link3->ip == rte_be_to_cpu_32(*dst_addr3))
+ #endif
+ )) {
+
+ #ifdef VNF_ACL
+ out_port3 = p_arp->outport_id[pkt[3]->port];
+ process_arpicmp_pkt(pkt[3], out_port3, pkt_mask3);
+ #else
+ process_arpicmp_pkt(pkt[3], ifm_get_port(in_port_id));
+ #endif
+
+ return;
+ }
+ #ifdef IPV6
+ else if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV6)
+ && (*protocol3 == ICMPV6_PROTOCOL_ID)) {
+
+ #ifdef VNF_ACL
+ out_port3 = p_arp->outport_id[pkt[3]->port];
+ process_icmpv6_pkt(pkt[3], out_port3, pkt_mask3);
+ #else
+ process_icmpv6_pkt(pkt[3], ifm_get_port(in_port_id));
+ #endif
+ return;
+ }
+ #endif
+
+ /* Drop the pkt if not ARP/ICMP */
+ rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask3);
+ p_arp->droppedPktCount++;
+
+
+}
+
+PIPELINE_ARPICMP_KEY_PORT_IN_AH(
+ port_in_ah_arpicmp,
+ pkt_key_arpicmp,
+ pkt4_key_arpicmp);
+
+static void *pipeline_arpicmp_init(struct pipeline_params *params,
+ __rte_unused void *arg)
+{
+ struct pipeline *p;
+ struct pipeline_arpicmp *p_arp;
+ uint32_t size, i, in_ports_arg_size;
+
+ printf("Start pipeline_arpicmp_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_arpicmp));
+ p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ p_arp = (struct pipeline_arpicmp *)p;
+ if (p == NULL)
+ return NULL;
+
+ //gp_arp = p_arp;
+ struct app_params *app = (struct app_params *)arg;
+ myApp = arg;
+
+ PLOG(p, HIGH, "ARPICMP");
+ strcpy(p->name, params->name);
+ p->log_level = params->log_level;
+
+ p_arp->receivedPktCount = 0;
+ p_arp->droppedPktCount = 0;
+
+#ifdef VNF_ACL
+ for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
+ p_arp->links_map[i] = 0xff;
+
+ p_arp->pipeline_num = 0;
+
+ /* Parse arguments */
+ if (pipeline_arpicmp_parse_args(p_arp, params))
+ return NULL;
+#endif
+ #ifndef VNF_ACL
+ lib_arp_init(params, app);
+ #endif
+
+ /* Pipeline */
+ {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "ARPICMP",
+ .socket_id = params->socket_id,
+ .offset_port_id = 0,
+ //.offset_port_id = arp_meta_offset,
+ };
+
+ 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 = 1;
+
+ /* Memory allocation for in_port_h_arg */
+ in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
+ (sizeof(struct pipeline_arpicmp_in_port_h_arg)) *
+ (params->n_ports_in));
+ struct pipeline_arpicmp_in_port_h_arg *ap =
+ (struct pipeline_arpicmp_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_arp;
+ (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_arpicmp;
+
+ 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) {
+ return NULL;
+ printf("Unable to read pipeline number\n");
+ }
+
+ p_arp->pipeline_num = (uint8_t) pipeline_num;
+
+ register_pipeline_Qs(p_arp->pipeline_num, p);
+ set_phy_outport_id(p_arp->pipeline_num, p, p_arp->outport_id);
+
+ /* Tables */
+ {
+ 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[0]);
+
+ 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[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;
+ }
+ }
+
+ /* 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));
+
+#ifdef VNF_ACL
+
+ /* create the arpicmp mbuf rx pool */
+ lib_arp_pktmbuf_tx_pool = rte_pktmbuf_pool_create(
+ "lib_arp_mbuf_tx_pool",
+ NB_ARPICMP_MBUF, 32,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+
+ if (lib_arp_pktmbuf_tx_pool == NULL) {
+ printf("ARP mbuf pool create failed.\n");
+ return NULL;
+ }
+
+ lib_arp_pkt = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
+ if (lib_arp_pkt == NULL) {
+ printf("ARP lib_arp_pkt alloc failed.\n");
+ return NULL;
+ }
+
+ /* ARP Table */
+ arp_hash_params.socket_id = rte_socket_id();
+ arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
+ arp_hash_handle = rte_hash_create(&arp_hash_params);
+
+ if (arp_hash_handle == NULL) {
+ printf("ARP rte_hash_create failed. socket %d ...\n",
+ arp_hash_params.socket_id);
+ return NULL;
+ }
+ printf("arp_hash_handle %p\n\n", (void *)arp_hash_handle);
+
+ /* ND IPv6 */
+ nd_hash_params.socket_id = rte_socket_id();
+ nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
+ nd_hash_handle = rte_hash_create(&nd_hash_params);
+
+ if (nd_hash_handle == NULL) {
+ printf("ND rte_hash_create failed. socket %d ...\n",
+ nd_hash_params.socket_id);
+ return NULL;
+ }
+
+ printf("nd_hash_handle %p\n\n", (void *)nd_hash_handle);
+#endif
+ return p;
+}
+
+static int pipeline_arpicmp_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_arpicmp_timer(void *pipeline)
+{
+ struct pipeline *p = (struct pipeline *)pipeline;
+
+ pipeline_msg_req_handle(p);
+ rte_pipeline_flush(p->p);
+
+ return 0;
+}
+
+static int
+pipeline_arpicmp_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_arpicmp_be_ops = {
+ .f_init = pipeline_arpicmp_init,
+ .f_free = pipeline_arpicmp_free,
+ .f_run = NULL,
+ .f_timer = pipeline_arpicmp_timer,
+ .f_track = pipeline_arpicmp_track,
+};
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.h b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.h
new file mode 100644
index 00000000..2c7fce2e
--- /dev/null
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.h
@@ -0,0 +1,343 @@
+/*
+// 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_ARPICMP_BE_H__
+#define __INCLUDE_PIPELINE_ARPICMP_BE_H__
+
+#include "pipeline_common_be.h"
+#define PIPELINE_ARPICMP_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]); \
+ \
+ 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 app_params *myApp;
+void print_pkt1(struct rte_mbuf *pkt);
+struct ether_addr *get_link_hw_addr(uint8_t out_port);
+#ifdef VNF_ACL
+
+#include <rte_pipeline.h>
+#include "rte_ether.h"
+#include "app.h"
+
+#if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
+// x86 == little endian
+// network == big endian
+#define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
+#define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
+#else
+#define CHECK_ENDIAN_16(x) (x)
+#define CHECK_ENDIAN_32(x) (x)
+#endif
+
+
+#define MAX_ARP_RT_ENTRY 16
+#define MAX_ND_RT_ENTRY 16
+
+#define ND_IPV6_ADDR_SIZE 16 /* 16 Byte of IPv6 Address */
+
+enum {
+ARP_FOUND,
+ARP_NOT_FOUND,
+NH_NOT_FOUND,
+};
+
+enum arp_key_type {
+ ARP_IPV4,
+ /* ND IPv6 */
+ ND_IPV6,
+};
+
+struct arp_key_ipv4 {
+ uint32_t ip;
+ uint8_t port_id;
+ uint8_t filler1;
+ uint8_t filler2;
+ uint8_t filler3;
+};
+
+/* ND IPv6 */
+struct nd_key_ipv6 {
+ /*128 Bit of IPv6 Address */
+ /*<48bit Network> <16bit Subnet> <64bit Interface> */
+ uint8_t ipv6[ND_IPV6_ADDR_SIZE];
+ uint8_t port_id;
+ uint8_t filler1;
+ uint8_t filler2;
+ uint8_t filler3;
+};
+
+struct arp_key {
+ enum arp_key_type type;
+ union {
+ struct arp_key_ipv4 ipv4;
+ } key;
+};
+
+struct lib_arp_route_table_entry {
+ uint32_t ip;
+ uint32_t mask;
+ uint32_t port;
+ uint32_t nh;
+};
+
+struct lib_nd_route_table_entry {
+ uint8_t ipv6[16];
+ uint8_t depth;
+ uint32_t port;
+ uint8_t nhipv6[16];
+};
+extern struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY];
+extern struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY];
+
+extern uint8_t prv_in_port_a[PIPELINE_MAX_PORT_IN];
+extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
+ uint8_t netmask_ipv6[]);
+uint32_t get_nh(uint32_t, uint32_t*);
+void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
+
+extern uint32_t ARPICMP_DEBUG;
+
+
+/* ARP entry populated and echo reply recieved */
+#define COMPLETE 1
+/* ARP entry populated and either awaiting echo reply or stale entry */
+#define INCOMPLETE 0
+
+/* ND IPv6 */
+extern uint32_t NDIPV6_DEBUG;
+
+/* ICMPv6 entry populated and echo reply recieved */
+#define ICMPv6_COMPLETE 1
+/* ICMPv6 entry populated and either awaiting echo reply or stale entry */
+#define ICMPv6_INCOMPLETE 0
+
+struct arp_entry_data {
+ struct ether_addr eth_addr;
+ uint8_t port;
+ uint8_t status;
+ uint32_t ip;
+} __attribute__ ((__packed__));
+
+/*ND IPv6*/
+struct nd_entry_data {
+ struct ether_addr eth_addr;
+ uint8_t port;
+ uint8_t status;
+ uint8_t ipv6[ND_IPV6_ADDR_SIZE];
+} __attribute__ ((__packed__));
+
+int get_dest_mac_address(const uint32_t ipaddr, const uint32_t phy_port,
+ struct ether_addr *hw_addr, uint32_t *nhip);
+int get_dest_mac_addr(const uint32_t ipaddr, const uint32_t phy_port,
+ struct ether_addr *hw_addr);
+
+int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t phy_port,
+ struct ether_addr *hw_addr, uint8_t nhipv6[]);
+
+void lib_arp_request_arp(
+ const uint32_t ipaddr,
+ const uint32_t phy_port,
+ struct rte_pipeline *rte_p);
+
+void print_arp_table(void);
+void print_nd_table(void);
+void remove_arp_entry(uint32_t ipaddr, uint8_t portid);
+void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid);
+void populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
+ uint8_t portid);
+/*ND IPv6*/
+int populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ip[],
+ uint8_t portid);
+void request_arp(uint8_t port_id, uint32_t ip, struct rte_pipeline *rte_p);
+void request_arp_wrap(uint8_t port_id, uint32_t ip);
+void request_echo(unsigned int port_id, uint32_t ip);
+
+void process_arpicmp_pkt(struct rte_mbuf *pkt, uint32_t out_port,
+ uint32_t pkt_num);
+
+struct arp_entry_data *retrieve_arp_entry(const struct arp_key_ipv4 arp_key);
+struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key);
+
+struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key);
+
+void lib_nd_init(/*struct pipeline_params *params, */ struct app_params *app);
+void print_pkt1(struct rte_mbuf *pkt);
+
+#endif
+
+uint8_t lb_outport_id[PIPELINE_MAX_PORT_IN];
+struct pipeline *loadb_pipeline[PIPELINE_MAX_PORT_IN];
+struct pipeline *all_pipeline[PIPELINE_MAX_PORT_IN];
+uint8_t vnf_to_loadb_map[PIPELINE_MAX_PORT_IN];
+uint8_t port_to_loadb_map[PIPELINE_MAX_PORT_IN];
+uint8_t loadb_pipeline_nums[PIPELINE_MAX_PORT_IN];
+
+#if 0
+uint8_t lb_outport_id[PIPELINE_MAX_PORT_IN];
+struct pipeline *arp_pipeline[PIPELINE_MAX_PORT_IN];
+uint8_t vnf_to_arp_map[PIPELINE_MAX_PORT_IN];
+uint8_t port_to_arp_map[PIPELINE_MAX_PORT_IN];
+uint8_t arp_pipeline_nums[PIPELINE_MAX_PORT_IN];
+#endif
+
+void set_port_to_loadb_map(uint8_t pipeline_num);
+uint8_t get_port_to_loadb_map(uint8_t phy_port_id);
+/* acts on port_to_loadb_map */
+
+void set_phy_inport_map(uint8_t pipeline_num, uint8_t *map);
+void set_phy_outport_map(uint8_t pipeline_num, uint8_t *map);
+
+void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map);
+/* acts on lb_outport_id */
+uint8_t get_loadb_outport_id(uint8_t actual_phy_port);
+/* acts on lb_outport_id */
+uint8_t get_vnf_set_num(uint8_t pipeline_num);
+
+void pipelines_port_info(void);
+void pipelines_map_info(void);
+void register_loadb_to_arp(uint8_t pipeline_num, struct pipeline *p,
+ __rte_unused struct app_params *app);
+/* vnf_to_loadb_map[] and loadb_pipelines[] */
+uint8_t SWQ_to_Port_map[128];
+
+extern struct pipeline_be_ops pipeline_arpicmp_be_ops;
+void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p);
+void set_link_map(uint8_t pipeline_num, struct pipeline *p, uint8_t *map);
+void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map);
+void set_phy_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map);
+void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map);
+
+/*
+ * Messages
+ */
+enum pipeline_arpicmp_msg_req_type {
+ PIPELINE_ARPICMP_MSG_REQ_ENTRY_DBG,
+ PIPELINE_ARPICMP_MSG_REQS
+};
+
+/*
+ * MSG ENTRY DBG
+ */
+struct pipeline_arpicmp_entry_dbg_msg_req {
+ enum pipeline_msg_req_type type;
+ enum pipeline_arpicmp_msg_req_type subtype;
+
+ /* data */
+ uint8_t data[2];
+};
+
+/*
+ * ARPICMP Entry
+ */
+
+struct pipeline_arpicmp_in_port_h_arg {
+ struct pipeline_arpicmp *p;
+ uint8_t in_port_id;
+};
+
+struct pipeline_arpicmp_entry_dbg_msg_rsp {
+ int status;
+};
+
+#ifdef VNF_ACL
+
+ /* ICMPv6 Header */
+struct icmpv6_hdr {
+ uint8_t icmpv6_type; /* ICMPV6 packet type. */
+ uint8_t icmpv6_code; /* ICMPV6 packet code. */
+ uint16_t icmpv6_cksum; /* ICMPV6 packet checksum. */
+} __attribute__ ((__packed__));
+
+ /**
+ * ICMPV6 Info Header
+ */
+struct icmpv6_info_hdr {
+ uint16_t icmpv6_ident; /* ICMPV6 packet identifier. */
+ uint16_t icmpv6_seq_nb; /* ICMPV6 packet sequence number. */
+} __attribute__ ((__packed__));
+
+ /**
+ * ICMPV6 ND Header
+ */
+struct icmpv6_nd_hdr {
+ /*ND Advertisement flags */
+ uint32_t icmpv6_reserved;
+ /* bit31-Router, bit30-Solicited, bit29-Override, bit28-bit0 unused */
+
+ uint8_t target_ipv6[16]; /**< target IPv6 address */
+ /*ICMPv6 Option*/
+ uint8_t type;
+ uint8_t length;
+ struct ether_addr link_layer_address;
+} __attribute__ ((__packed__));
+
+ /* Icmpv6 types */
+ #define ICMPV6_PROTOCOL_ID 58
+ #define ICMPV6_ECHO_REQUEST 0x0080
+ #define ICMPV6_ECHO_REPLY 0x0081
+ #define ICMPV6_NEIGHBOR_SOLICITATION 0x0087
+ #define ICMPV6_NEIGHBOR_ADVERTISEMENT 0x0088
+ #define IPV6_MULTICAST 0xFF02
+
+ #define NEIGHBOR_SOLICITATION_SET 0x40000000
+enum icmpv6_link_layer_Address_type {
+ e_Source_Link_Layer_Address = 1,
+ e_Target_Link_Layer_Address,
+ e_Link_Layer_Address
+};
+
+uint8_t is_multicast_ipv6_addr(uint8_t ipv6[]);
+struct icmpv6_port_address {
+ uint32_t ipv6[16];
+ uint64_t mac_addr;
+};
+
+struct icmpv6_port_address icmpv6_port_addresses[RTE_MAX_ETHPORTS];
+
+ #define MAX_NUM_ICMPv6_ENTRIES 64
+ //struct rte_pipeline *myicmpP;
+struct rte_mbuf *lib_icmpv6_pkt;
+void request_icmpv6_echo(uint32_t port_id, uint8_t ipv6[]);
+void request_icmpv6_echo_message(uint16_t port_id, uint8_t ipv6[],
+ struct ether_addr *gw_addr);
+void
+process_icmpv6_pkt(struct rte_mbuf *pkt, uint32_t out_port, uint32_t pkt_num);
+
+int get_dest_mac_addr_port(const uint32_t ipaddr,
+ uint32_t *phy_port, struct ether_addr *hw_addr);
+
+int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
+ struct ether_addr *hw_addr, uint8_t nhipv6[]);
+#endif
+#endif