diff options
author | Vishwesh M Rudramuni <vishweshmr@gmail.com> | 2017-04-18 19:41:40 +0530 |
---|---|---|
committer | Deepak S <deepak.s@linux.intel.com> | 2017-04-18 02:59:07 -0700 |
commit | 51cd08d9a3f2826088d122e2a5683315c77a2786 (patch) | |
tree | 3fac17a8f7bf362f0c77f1003615b2063d900d35 /common/VIL/pipeline_arpicmp | |
parent | 03aef84e240c5be8813634735d825420129f1460 (diff) |
common: Adding common library for sample vnf
JIRA: SAMPLEVNF-3
This patch adds common libraries required as part of the
sample vnf.
This includes the following libraries
1. ACL library
2. SIP
3. FTP
4. Connection tracker
5. L2l3 stack
- Interface Manager
- ARP & ICMPv4
- ND & ICMPv6
and other common libraries needed for ip pipeline framework
Change-Id: I117690b6b63fbcd76974cd7274518484e60980ab
Signed-off-by: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
[Push patch to gerrit]
Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Diffstat (limited to 'common/VIL/pipeline_arpicmp')
-rw-r--r-- | common/VIL/pipeline_arpicmp/pipeline_arpicmp.c | 2118 | ||||
-rw-r--r-- | common/VIL/pipeline_arpicmp/pipeline_arpicmp.h | 122 | ||||
-rw-r--r-- | common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c | 3484 | ||||
-rw-r--r-- | common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.h | 343 |
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(¶ms->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(¶ms->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=", ð_hdr->s_addr); + print_ether_addr(" - dst=", ð_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, ð_h->d_addr); + ether_addr_copy((struct ether_addr *) + &arp_port_addresses[port_id].mac_addr, ð_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, ð_h->d_addr); + ether_addr_copy((struct ether_addr *) + &arp_port_addresses[port_id].mac_addr, ð_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(ð_h->s_addr, ð_h->d_addr); + + // set sender mac address - + ether_addr_copy((struct ether_addr *)& + arp_port_addresses[in_port_id].mac_addr, + ð_h->s_addr); + + arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); + ether_addr_copy(ð_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(ð_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, ð_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(ð_h->s_addr, + ð_h->d_addr); + ether_addr_copy((struct ether_addr *) + &arp_port_addresses + [in_port_id].mac_addr, + ð_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, + ð_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(ð_h->s_addr, + ð_h->d_addr); + ether_addr_copy((struct ether_addr *) + &icmpv6_port_addresses + [in_port_id].mac_addr, + ð_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 = ð_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(ð_h->s_addr, + ð_h->d_addr); + ether_addr_copy((struct ether_addr *) + &icmpv6_port_addresses + [in_port_id].mac_addr, + ð_h->s_addr); + + // set sender mac address + ether_addr_copy(ð_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 = ð_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, ð_h->d_addr); + ether_addr_copy((struct ether_addr *)&icmpv6_port_addresses[port_id]. + mac_addr, ð_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(¶ms-> + port_in[i]), + .arg_create = + pipeline_port_in_params_convert(¶ms-> + port_in[i]), + .f_action = NULL, + .arg_ah = &(ap[i]), + .burst_size = params->port_in[i].burst_size, + }; + + port_params.f_action = port_in_ah_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(¶ms-> + port_out[i]), + .arg_create = + pipeline_port_out_params_convert(¶ms-> + port_out[i]), + .f_action = NULL, + .arg_ah = NULL, + }; + + int status = rte_pipeline_port_out_create(p->p, + &port_params, + &p->port_out_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + int pipeline_num = 0; + + int status = sscanf(params->name, "PIPELINE%d", &pipeline_num); + + if (status < 0) { + 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 |