From 168dfa61667e0a46bdbbed2b30a3117f91b62537 Mon Sep 17 00:00:00 2001 From: Ivan Boule Date: Wed, 30 Apr 2014 15:30:11 +0200 Subject: [PATCH] app/testpmd: add engine that replies to ARP and ICMP echo requests Add a new specific packet processing engine in the "testpmd" application that only replies to ARP requests and to ICMP echo requests. For this purpose, a new "icmpecho" forwarding mode is provided that can be dynamically selected with the following testpmd command: set fwd icmpecho before starting the receipt of packets on the selected ports. Then, the "icmpecho" engine performs the following actions on all received packets: - replies to a received ARP request by sending back on the RX port a ARP reply with a "sender hardware address" field containing the MAC address of the RX port, - replies to a ICMP echo request by sending back on the RX port a ICMP echo reply, swapping the IP source and the IP destination address in the IP header, - otherwise, simply drops the received packet. When replying to a received packet that was encapsulated into a VLAN tunnel, the reply is sent back with the same VLAN identifier. By default, the testpmd configures VLAN header stripping RX option on each port. This option is not managed by the icmpecho engine which won't detect packets that were encapsulated into a VLAN. To address this issue, the VLAN header stripping option must be previously switched off with the following testpmd command: vlan set strip off When the "verbose" mode has been set with the testpmd command "set verbose 1", the "icmpecho" engine displays informations about each received packet. The "icmpecho" forwarding engine can also be used to simply check port connectivity at the hardware level (check that cables are well-plugged) and at the software level (receipt of VLAN packets, for instance). Signed-off-by: Ivan Boule Acked-by: Thomas Monjalon --- app/test-pmd/Makefile | 1 + app/test-pmd/config.c | 59 +++++ app/test-pmd/icmpecho.c | 504 ++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + lib/librte_net/Makefile | 2 +- lib/librte_net/rte_arp.h | 84 +++++++ lib/librte_net/rte_icmp.h | 101 ++++++++ 8 files changed, 752 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/icmpecho.c create mode 100644 lib/librte_net/rte_arp.h create mode 100644 lib/librte_net/rte_icmp.h diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index 7eccf4ae17..fc58ed9514 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_TEST_PMD) += flowgen.c SRCS-$(CONFIG_RTE_TEST_PMD) += rxonly.c SRCS-$(CONFIG_RTE_TEST_PMD) += txonly.c SRCS-$(CONFIG_RTE_TEST_PMD) += csumonly.c +SRCS-$(CONFIG_RTE_TEST_PMD) += icmpecho.c ifeq ($(CONFIG_RTE_LIBRTE_IEEE1588),y) SRCS-$(CONFIG_RTE_TEST_PMD) += ieee1588fwd.c endif diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 41326fe987..20ad0a81ba 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -970,10 +970,69 @@ dcb_fwd_config_setup(void) } } +static void +icmp_echo_config_setup(void) +{ + portid_t rxp; + queueid_t rxq; + lcoreid_t lc_id; + uint16_t sm_id; + + if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores) + cur_fwd_config.nb_fwd_lcores = (lcoreid_t) + (nb_txq * nb_fwd_ports); + else + cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; + cur_fwd_config.nb_fwd_ports = nb_fwd_ports; + cur_fwd_config.nb_fwd_streams = + (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); + if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) + cur_fwd_config.nb_fwd_lcores = + (lcoreid_t)cur_fwd_config.nb_fwd_streams; + if (verbose_level > 0) { + printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n", + __FUNCTION__, + cur_fwd_config.nb_fwd_lcores, + cur_fwd_config.nb_fwd_ports, + cur_fwd_config.nb_fwd_streams); + } + + /* reinitialize forwarding streams */ + init_fwd_streams(); + setup_fwd_config_of_each_lcore(&cur_fwd_config); + rxp = 0; rxq = 0; + for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { + if (verbose_level > 0) + printf(" core=%d: \n", lc_id); + for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { + struct fwd_stream *fs; + fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; + fs->rx_port = fwd_ports_ids[rxp]; + fs->rx_queue = rxq; + fs->tx_port = fs->rx_port; + fs->tx_queue = lc_id; + fs->peer_addr = fs->tx_port; + if (verbose_level > 0) + printf(" stream=%d port=%d rxq=%d txq=%d\n", + sm_id, fs->rx_port, fs->rx_queue, + fs->tx_queue); + rxq = (queueid_t) (rxq + 1); + if (rxq == nb_rxq) { + rxq = 0; + rxp = (portid_t) (rxp + 1); + } + } + } +} + void fwd_config_setup(void) { cur_fwd_config.fwd_eng = cur_fwd_eng; + if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) { + icmp_echo_config_setup(); + return; + } if ((nb_rxq > 1) && (nb_txq > 1)){ if (dcb_config) dcb_fwd_config_setup(); diff --git a/app/test-pmd/icmpecho.c b/app/test-pmd/icmpecho.c new file mode 100644 index 0000000000..c28ff5a3e2 --- /dev/null +++ b/app/test-pmd/icmpecho.c @@ -0,0 +1,504 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2013 6WIND + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +static const char * +arp_op_name(uint16_t arp_op) +{ + switch (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 const char * +ip_proto_name(uint8_t ip_proto) +{ + static const char * ip_proto_names[] = { + "IP6HOPOPTS", /**< IP6 hop-by-hop options */ + "ICMP", /**< control message protocol */ + "IGMP", /**< group mgmt protocol */ + "GGP", /**< gateway^2 (deprecated) */ + "IPv4", /**< IPv4 encapsulation */ + + "UNASSIGNED", + "TCP", /**< transport control protocol */ + "ST", /**< Stream protocol II */ + "EGP", /**< exterior gateway protocol */ + "PIGP", /**< private interior gateway */ + + "RCC_MON", /**< BBN RCC Monitoring */ + "NVPII", /**< network voice protocol*/ + "PUP", /**< pup */ + "ARGUS", /**< Argus */ + "EMCON", /**< EMCON */ + + "XNET", /**< Cross Net Debugger */ + "CHAOS", /**< Chaos*/ + "UDP", /**< user datagram protocol */ + "MUX", /**< Multiplexing */ + "DCN_MEAS", /**< DCN Measurement Subsystems */ + + "HMP", /**< Host Monitoring */ + "PRM", /**< Packet Radio Measurement */ + "XNS_IDP", /**< xns idp */ + "TRUNK1", /**< Trunk-1 */ + "TRUNK2", /**< Trunk-2 */ + + "LEAF1", /**< Leaf-1 */ + "LEAF2", /**< Leaf-2 */ + "RDP", /**< Reliable Data */ + "IRTP", /**< Reliable Transaction */ + "TP4", /**< tp-4 w/ class negotiation */ + + "BLT", /**< Bulk Data Transfer */ + "NSP", /**< Network Services */ + "INP", /**< Merit Internodal */ + "SEP", /**< Sequential Exchange */ + "3PC", /**< Third Party Connect */ + + "IDPR", /**< InterDomain Policy Routing */ + "XTP", /**< XTP */ + "DDP", /**< Datagram Delivery */ + "CMTP", /**< Control Message Transport */ + "TPXX", /**< TP++ Transport */ + + "ILTP", /**< IL transport protocol */ + "IPv6_HDR", /**< IP6 header */ + "SDRP", /**< Source Demand Routing */ + "IPv6_RTG", /**< IP6 routing header */ + "IPv6_FRAG", /**< IP6 fragmentation header */ + + "IDRP", /**< InterDomain Routing*/ + "RSVP", /**< resource reservation */ + "GRE", /**< General Routing Encap. */ + "MHRP", /**< Mobile Host Routing */ + "BHA", /**< BHA */ + + "ESP", /**< IP6 Encap Sec. Payload */ + "AH", /**< IP6 Auth Header */ + "INLSP", /**< Integ. Net Layer Security */ + "SWIPE", /**< IP with encryption */ + "NHRP", /**< Next Hop Resolution */ + + "UNASSIGNED", + "UNASSIGNED", + "UNASSIGNED", + "ICMPv6", /**< ICMP6 */ + "IPv6NONEXT", /**< IP6 no next header */ + + "Ipv6DSTOPTS",/**< IP6 destination option */ + "AHIP", /**< any host internal protocol */ + "CFTP", /**< CFTP */ + "HELLO", /**< "hello" routing protocol */ + "SATEXPAK", /**< SATNET/Backroom EXPAK */ + + "KRYPTOLAN", /**< Kryptolan */ + "RVD", /**< Remote Virtual Disk */ + "IPPC", /**< Pluribus Packet Core */ + "ADFS", /**< Any distributed FS */ + "SATMON", /**< Satnet Monitoring */ + + "VISA", /**< VISA Protocol */ + "IPCV", /**< Packet Core Utility */ + "CPNX", /**< Comp. Prot. Net. Executive */ + "CPHB", /**< Comp. Prot. HeartBeat */ + "WSN", /**< Wang Span Network */ + + "PVP", /**< Packet Video Protocol */ + "BRSATMON", /**< BackRoom SATNET Monitoring */ + "ND", /**< Sun net disk proto (temp.) */ + "WBMON", /**< WIDEBAND Monitoring */ + "WBEXPAK", /**< WIDEBAND EXPAK */ + + "EON", /**< ISO cnlp */ + "VMTP", /**< VMTP */ + "SVMTP", /**< Secure VMTP */ + "VINES", /**< Banyon VINES */ + "TTP", /**< TTP */ + + "IGP", /**< NSFNET-IGP */ + "DGP", /**< dissimilar gateway prot. */ + "TCF", /**< TCF */ + "IGRP", /**< Cisco/GXS IGRP */ + "OSPFIGP", /**< OSPFIGP */ + + "SRPC", /**< Strite RPC protocol */ + "LARP", /**< Locus Address Resoloution */ + "MTP", /**< Multicast Transport */ + "AX25", /**< AX.25 Frames */ + "4IN4", /**< IP encapsulated in IP */ + + "MICP", /**< Mobile Int.ing control */ + "SCCSP", /**< Semaphore Comm. security */ + "ETHERIP", /**< Ethernet IP encapsulation */ + "ENCAP", /**< encapsulation header */ + "AES", /**< any private encr. scheme */ + + "GMTP", /**< GMTP */ + "IPCOMP", /**< payload compression (IPComp) */ + "UNASSIGNED", + "UNASSIGNED", + "PIM", /**< Protocol Independent Mcast */ + }; + + if (ip_proto < sizeof(ip_proto_names) / sizeof(ip_proto_names[0])) + return ip_proto_names[ip_proto]; + switch (ip_proto) { + case IPPROTO_PGM: /**< PGM */ + return "PGM"; + case IPPROTO_SCTP: /**< Stream Control Transport Protocol */ + return "SCTP"; + case IPPROTO_DIVERT: /**< divert pseudo-protocol */ + return "DIVERT"; + case IPPROTO_RAW: /**< raw IP packet */ + return "RAW"; + default: + break; + } + return "UNASSIGNED"; +} + +static void +ether_addr_to_hexa(const struct ether_addr *ea, char *buf) +{ + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + ea->addr_bytes[0], + ea->addr_bytes[1], + ea->addr_bytes[2], + ea->addr_bytes[3], + ea->addr_bytes[4], + ea->addr_bytes[5]); +} + +static void +ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf) +{ + uint32_t ipv4_addr; + + ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr); + sprintf(buf, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF, + (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF, + ipv4_addr & 0xFF); +} + +static void +ether_addr_dump(const char *what, const struct ether_addr *ea) +{ + char buf[18]; + + ether_addr_to_hexa(ea, buf); + if (what) + printf("%s", what); + printf("%s", buf); +} + +static void +ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr) +{ + char buf[16]; + + ipv4_addr_to_dot(be_ipv4_addr, buf); + if (what) + printf("%s", what); + printf("%s", buf); +} + +/* + * Receive a burst of packets, lookup for ICMP echo requets, and, if any, + * send back ICMP echo replies. + */ +static void +reply_to_icmp_echo_rqsts(struct fwd_stream *fs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_mbuf *pkt; + struct ether_hdr *eth_h; + struct vlan_hdr *vlan_h; + struct arp_hdr *arp_h; + struct ipv4_hdr *ip_h; + struct icmp_hdr *icmp_h; + struct ether_addr eth_addr; + uint32_t ip_addr; + uint16_t nb_rx; + uint16_t nb_tx; + uint16_t nb_replies; + uint16_t eth_type; + uint16_t vlan_id; + uint16_t arp_op; + uint16_t arp_pro; + uint8_t i; + int l2_len; +#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 + + /* + * First, 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; + nb_replies = 0; + for (i = 0; i < nb_rx; i++) { + pkt = pkts_burst[i]; + eth_h = (struct ether_hdr *) pkt->pkt.data; + eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type); + l2_len = sizeof(struct ether_hdr); + if (verbose_level > 0) { + printf("\nPort %d pkt-len=%u nb-segs=%u\n", + fs->rx_port, pkt->pkt.pkt_len, pkt->pkt.nb_segs); + ether_addr_dump(" ETH: src=", ð_h->s_addr); + ether_addr_dump(" dst=", ð_h->d_addr); + } + if (eth_type == ETHER_TYPE_VLAN) { + vlan_h = (struct vlan_hdr *) + ((char *)eth_h + sizeof(struct ether_hdr)); + l2_len += sizeof(struct vlan_hdr); + eth_type = rte_be_to_cpu_16(vlan_h->eth_proto); + if (verbose_level > 0) { + vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci) + & 0xFFF; + printf(" [vlan id=%u]", vlan_id); + } + } + if (verbose_level > 0) { + printf(" type=0x%04x\n", eth_type); + } + + /* Reply to ARP requests */ + if (eth_type == ETHER_TYPE_ARP) { + arp_h = (struct arp_hdr *) ((char *)eth_h + l2_len); + arp_op = RTE_BE_TO_CPU_16(arp_h->arp_op); + arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_pro); + if (verbose_level > 0) { + printf(" ARP: hrd=%d proto=0x%04x hln=%d " + "pln=%d op=%u (%s)\n", + RTE_BE_TO_CPU_16(arp_h->arp_hrd), + arp_pro, arp_h->arp_hln, + arp_h->arp_pln, arp_op, + arp_op_name(arp_op)); + } + if ((RTE_BE_TO_CPU_16(arp_h->arp_hrd) != + ARP_HRD_ETHER) || + (arp_pro != ETHER_TYPE_IPv4) || + (arp_h->arp_hln != 6) || + (arp_h->arp_pln != 4) + ) { + rte_pktmbuf_free(pkt); + if (verbose_level > 0) + printf("\n"); + continue; + } + if (verbose_level > 0) { + memcpy(ð_addr, + arp_h->arp_data.arp_ip.arp_sha, 6); + ether_addr_dump(" sha=", ð_addr); + memcpy(&ip_addr, + arp_h->arp_data.arp_ip.arp_sip, 4); + ipv4_addr_dump(" sip=", ip_addr); + printf("\n"); + memcpy(ð_addr, + arp_h->arp_data.arp_ip.arp_tha, 6); + ether_addr_dump(" tha=", ð_addr); + memcpy(&ip_addr, + arp_h->arp_data.arp_ip.arp_tip, 4); + ipv4_addr_dump(" tip=", ip_addr); + printf("\n"); + } + if (arp_op != ARP_OP_REQUEST) { + rte_pktmbuf_free(pkt); + continue; + } + + /* + * Build ARP reply. + */ + + /* Use source MAC address as destination MAC address. */ + ether_addr_copy(ð_h->s_addr, ð_h->d_addr); + /* Set source MAC address with MAC address of TX port */ + ether_addr_copy(&ports[fs->tx_port].eth_addr, + ð_h->s_addr); + + arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); + memcpy(ð_addr, arp_h->arp_data.arp_ip.arp_tha, 6); + memcpy(arp_h->arp_data.arp_ip.arp_tha, + arp_h->arp_data.arp_ip.arp_sha, 6); + memcpy(arp_h->arp_data.arp_ip.arp_sha, + ð_h->s_addr, 6); + + /* Swap IP addresses in ARP payload */ + memcpy(&ip_addr, arp_h->arp_data.arp_ip.arp_sip, 4); + memcpy(arp_h->arp_data.arp_ip.arp_sip, + arp_h->arp_data.arp_ip.arp_tip, 4); + memcpy(arp_h->arp_data.arp_ip.arp_tip, &ip_addr, 4); + pkts_burst[nb_replies++] = pkt; + continue; + } + + if (eth_type != ETHER_TYPE_IPv4) { + rte_pktmbuf_free(pkt); + continue; + } + ip_h = (struct ipv4_hdr *) ((char *)eth_h + l2_len); + if (verbose_level > 0) { + ipv4_addr_dump(" IPV4: src=", ip_h->src_addr); + ipv4_addr_dump(" dst=", ip_h->dst_addr); + printf(" proto=%d (%s)\n", + ip_h->next_proto_id, + ip_proto_name(ip_h->next_proto_id)); + } + + /* + * Check if packet is a ICMP echo request. + */ + icmp_h = (struct icmp_hdr *) ((char *)ip_h + + sizeof(struct ipv4_hdr)); + if (! ((ip_h->next_proto_id == IPPROTO_ICMP) && + (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST) && + (icmp_h->icmp_code == 0))) { + rte_pktmbuf_free(pkt); + continue; + } + + if (verbose_level > 0) + printf(" ICMP: echo request seq id=%d\n", + rte_be_to_cpu_16(icmp_h->icmp_seq_nb)); + + /* + * Prepare ICMP echo reply to be sent back. + * - switch ethernet source and destinations addresses, + * - switch IPv4 source and destinations addresses, + * - set IP_ICMP_ECHO_REPLY in ICMP header. + * No need to re-compute the IP header checksum. + * Reset ICMP checksum. + */ + ether_addr_copy(ð_h->s_addr, ð_addr); + ether_addr_copy(ð_h->d_addr, ð_h->s_addr); + ether_addr_copy(ð_addr, ð_h->d_addr); + ip_addr = ip_h->src_addr; + ip_h->src_addr = ip_h->dst_addr; + ip_h->dst_addr = ip_addr; + icmp_h->icmp_type = IP_ICMP_ECHO_REPLY; + icmp_h->icmp_cksum = 0; + pkts_burst[nb_replies++] = pkt; + } + + /* Send back ICMP echo replies, if any. */ + if (nb_replies > 0) { + nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, + nb_replies); + 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_replies)) { + fs->fwd_dropped += (nb_replies - nb_tx); + do { + rte_pktmbuf_free(pkts_burst[nb_tx]); + } while (++nb_tx < nb_replies); + } + } + +#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 icmp_echo_engine = { + .fwd_mode_name = "icmpecho", + .port_fwd_begin = NULL, + .port_fwd_end = NULL, + .packet_fwd = reply_to_icmp_echo_rqsts, +}; diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 5b3781a5d3..8b3e5c4152 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -150,6 +150,7 @@ struct fwd_engine * fwd_engines[] = { &rx_only_engine, &tx_only_engine, &csum_fwd_engine, + &icmp_echo_engine, #ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 2b4529534e..83193ef1e4 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -205,6 +205,7 @@ extern struct fwd_engine flow_gen_engine; extern struct fwd_engine rx_only_engine; extern struct fwd_engine tx_only_engine; extern struct fwd_engine csum_fwd_engine; +extern struct fwd_engine icmp_echo_engine; #ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine; #endif diff --git a/lib/librte_net/Makefile b/lib/librte_net/Makefile index 0585d94a1e..a59a4fb760 100644 --- a/lib/librte_net/Makefile +++ b/lib/librte_net/Makefile @@ -34,7 +34,7 @@ include $(RTE_SDK)/mk/rte.vars.mk CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 # install includes -SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h rte_sctp.h +SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h rte_sctp.h rte_icmp.h rte_arp.h include $(RTE_SDK)/mk/rte.install.mk diff --git a/lib/librte_net/rte_arp.h b/lib/librte_net/rte_arp.h new file mode 100644 index 0000000000..c7b0e51416 --- /dev/null +++ b/lib/librte_net/rte_arp.h @@ -0,0 +1,84 @@ +/* BSD LICENSE + * + * Copyright(c) 2013 6WIND. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_ARP_H_ +#define _RTE_ARP_H_ + +/** + * @file + * + * ARP-related defines + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ARP header IPv4 payload. + */ +struct arp_ipv4 { + uint8_t arp_sha[6]; /* sender hardware address */ + uint8_t arp_sip[4]; /* sender IP address */ + uint8_t arp_tha[6]; /* target hardware address */ + uint8_t arp_tip[4]; /* target IP address */ +} __attribute__((__packed__)); + +/** + * ARP header. + */ +struct arp_hdr { + uint16_t arp_hrd; /* format of hardware address */ +#define ARP_HRD_ETHER 1 /* ARP Ethernet address format */ + + uint16_t arp_pro; /* format of protocol address */ + uint8_t arp_hln; /* length of hardware address */ + uint8_t arp_pln; /* length of protocol address */ + uint16_t arp_op; /* ARP opcode (command) */ +#define ARP_OP_REQUEST 1 /* request to resolve address */ +#define ARP_OP_REPLY 2 /* response to previous request */ +#define ARP_OP_REVREQUEST 3 /* request proto addr given hardware */ +#define ARP_OP_REVREPLY 4 /* response giving protocol address */ +#define ARP_OP_INVREQUEST 8 /* request to identify peer */ +#define ARP_OP_INVREPLY 9 /* response identifying peer */ + + union { + struct arp_ipv4 arp_ip; + } arp_data; +} __attribute__((__packed__)); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ARP_H_ */ diff --git a/lib/librte_net/rte_icmp.h b/lib/librte_net/rte_icmp.h new file mode 100644 index 0000000000..8b287f6d03 --- /dev/null +++ b/lib/librte_net/rte_icmp.h @@ -0,0 +1,101 @@ +/* BSD LICENSE + * + * Copyright(c) 2013 6WIND. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in.h 8.3 (Berkeley) 1/3/94 + * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ + */ + +#ifndef _RTE_ICMP_H_ +#define _RTE_ICMP_H_ + +/** + * @file + * + * ICMP-related defines + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ICMP Header + */ +struct icmp_hdr { + uint8_t icmp_type; /* ICMP packet type. */ + uint8_t icmp_code; /* ICMP packet code. */ + uint16_t icmp_cksum; /* ICMP packet checksum. */ + uint16_t icmp_ident; /* ICMP packet identifier. */ + uint16_t icmp_seq_nb; /* ICMP packet sequence number. */ +} __attribute__((__packed__)); + +/* ICMP packet types */ +#define IP_ICMP_ECHO_REPLY 0 +#define IP_ICMP_ECHO_REQUEST 8 + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_ICMP_H_ */ -- 2.20.1