diff options
author | Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com> | 2017-06-07 07:39:25 +0530 |
---|---|---|
committer | Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com> | 2017-07-14 06:27:31 +0530 |
commit | ef07d20e9777bf0e1af54629eb390a8a5ccd0091 (patch) | |
tree | 7f069fadab80cdae4b55cb52f164fcdf90b108e0 /VNFs/UDP_Replay | |
parent | 82416b375a275837689cddfd1782d82996fecaca (diff) |
[UDP_Replay] Adding the dynamic arp support
This patch adds dynamic arp support to UDP Replay VNF.
This patch fixes the performance issue observed with
arp support for UDP replay.
The arp support can be simply not used by not providing the
"-s option" which will revert to a plain UDP replay
functionality
Change-Id: I565eb83cd825470d4603ed5cb8fbe32f311eb0af
Signed-off-by: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
Diffstat (limited to 'VNFs/UDP_Replay')
-rw-r--r-- | VNFs/UDP_Replay/main.c | 791 |
1 files changed, 507 insertions, 284 deletions
diff --git a/VNFs/UDP_Replay/main.c b/VNFs/UDP_Replay/main.c index 5242adba..e6bc8aa3 100644 --- a/VNFs/UDP_Replay/main.c +++ b/VNFs/UDP_Replay/main.c @@ -80,9 +80,22 @@ performance of the solution should be sufficient for testing the UDP NAT perform #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> #include <cmdline_parse_ipaddr.h> +#include <rte_errno.h> +#include <rte_cfgfile.h> #include "parse_obj_list.h" +#include <lib_arp.h> +#include "l2_proto.h" +#include "interface.h" +#include "l3fwd_common.h" +#include "l3fwd_lpm4.h" +#include "l3fwd_lpm6.h" +#include "lib_icmpv6.h" +#include "app.h" +#include "vnf_common.h" +#define IN6ADDRSZ 16 +#define INADDRSZ 4 #define APP_LOOKUP_EXACT_MATCH 0 #define APP_LOOKUP_LPM 1 #define DO_RFC_1812_CHECKS @@ -171,38 +184,55 @@ performance of the solution should be sufficient for testing the UDP NAT perform */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; static uint64_t rcv_pkt_count[32] = {0}; static uint64_t tx_pkt_count[32] = {0}; +static uint32_t arp_support; +unsigned num_ports; +struct sockaddr_in ipaddr1, ipaddr2; /* ethernet addresses of ports */ static uint64_t dest_eth_addr[RTE_MAX_ETHPORTS]; -static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; - static __m128i val_eth[RTE_MAX_ETHPORTS]; cmdline_parse_ctx_t main_ctx[]; +uint32_t timer_lcore; +uint32_t exit_loop = 1; +port_config_t *port_config; +#define MEMPOOL_SIZE 32 * 1024 +#define BUFFER_SIZE 2048 +#define CACHE_SIZE 256 /* replace first 12B of the ethernet header. */ #define MASK_ETH 0x3f +#define IP_TYPE_IPV4 0 +#define IP_TYPE_IPV6 1 +#define MAX_IP 32 +const char* ipv4[MAX_IP]; +uint8_t link_ipv6[MAX_IP][16]; +uint32_t type, numports; /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; static int promiscuous_on = 0; /**< Ports set in promiscuous mode off by default. */ static int numa_on = 1; /**< NUMA is enabled by default. */ static int csum_on = 1; /**< NUMA is enabled by default. */ +struct pipeline_params def_pipeline_params = { + .n_ports_in = 0, + .n_ports_out = 0, + .n_msgq = 0, + .socket_id = 0, + .n_args = 0, + .log_level = 0, +}; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static int ipv6 = 0; /**< ipv6 is false by default. */ #endif +void convert_ipstr_to_numeric(void); -static void -print_ethaddr(const char *name, const struct ether_addr *eth_addr); - -int print_stats(void); +int print_l4stats(void); int clear_stats(void); struct mbuf_table { @@ -265,7 +295,29 @@ static struct rte_eth_conf port_conf = { }, }; -static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; +/* empty vmdq configuration structure. Filled in programatically */ +static struct rte_eth_rxconf rx_conf = { + .rx_thresh = { + .pthresh = 8, + .hthresh = 8, + .wthresh = 4, + }, + .rx_free_thresh = 64, + .rx_drop_en = 0, + .rx_deferred_start = 0, +}; +static struct rte_eth_txconf tx_conf = { + .tx_thresh = { + .pthresh = 36, + .hthresh = 0, + .wthresh = 0, + }, + .tx_rs_thresh = 0, + .tx_free_thresh = 0, + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | + ETH_TXQ_FLAGS_NOOFFLOADS, + .tx_deferred_start = 0, +}; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) @@ -362,8 +414,6 @@ static struct ipv6_udp_replay_route ipv6_udp_replay_route_array[] = { }; typedef struct rte_hash lookup_struct_t; -static lookup_struct_t *ipv4_udp_replay_lookup_struct[NB_SOCKETS]; -static lookup_struct_t *ipv6_udp_replay_lookup_struct[NB_SOCKETS]; #ifdef RTE_ARCH_X86_64 /* default to 4 million hash entries (approx) */ @@ -375,6 +425,185 @@ static lookup_struct_t *ipv6_udp_replay_lookup_struct[NB_SOCKETS]; #define HASH_ENTRY_NUMBER_DEFAULT 4 static uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT; +void +app_link_up_internal(__rte_unused struct app_params *app, struct app_link_params *cp) +{ + cp->state = 1; +} +void +app_link_down_internal(__rte_unused struct app_params *app, struct app_link_params *cp) +{ + cp->state = 0; +} + +/* 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; + if ((pch = strchr(digits, ch)) != 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 dbloct_count = 0; + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + if (*src == ':') + if (*++src != ':') + return 0; + curtok = src; + saw_xdigit = count_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + if ((pch = strchr((xdigits = xdigits_l), ch)) == 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 (dbloct_count == 8) + return 0; + 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; +} +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; + } +} +void convert_ipstr_to_numeric(void) +{ + uint32_t i; + for (i = 0; i < numports; i++) + { + if (type == IP_TYPE_IPV4) { + memset(&ipaddr1, '\0', sizeof(struct sockaddr_in)); + ipaddr1.sin_addr.s_addr = inet_addr(ipv4[i]); + ifm_add_ipv4_port(i, ipaddr1.sin_addr.s_addr, 24); + } else if (type == IP_TYPE_IPV6) { + ifm_add_ipv6_port(i, &link_ipv6[i][0], 128); + } + } +} static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, @@ -401,6 +630,43 @@ ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ return (init_val); } +static int arp_pkts; +static inline int check_arpicmp(struct rte_mbuf *pkt) +{ + uint8_t in_port_id = pkt->port; + uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12; + uint16_t *eth_proto = + RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset); + uint8_t *protocol; + uint32_t prot_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST; + protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset); + 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))) { + process_arpicmp_pkt(pkt, ifm_get_port(in_port_id)); + arp_pkts++; + return 0; + } + return 1; +} +static inline int check_arpicmpv6(struct rte_mbuf *pkt) +{ + struct ether_hdr *eth_h; + struct ipv6_hdr *ipv6_h; + uint8_t in_port_id = pkt->port; + uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12; + uint16_t *eth_proto = + RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset); + eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr)); + if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV6) + && (ipv6_h->proto == ICMPV6_PROTOCOL_ID)) { + process_icmpv6_pkt(pkt, ifm_get_port(in_port_id)); + return 0; + } + return 1; +} static inline uint32_t ipv6_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val) @@ -650,7 +916,7 @@ send_packetsx4(struct lcore_conf *qconf, uint8_t port, #ifdef DO_RFC_1812_CHECKS static inline int -is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len) +is_valid_pkt_ipv4(struct ipv4_hdr *pkt, uint32_t link_len) { /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ /* @@ -777,6 +1043,22 @@ simple_ipv4_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_con struct ether_hdr tmp; struct ipv4_hdr *ipv4_hdr[8]; struct udp_hdr *udp_hdr[8]; + int i; + l2_phy_interface_t *port = ifm_get_port(portid); + if (port == NULL) { + printf("port may be un initialized\n"); + return; + } + if (unlikely(arp_support)) { + check_arpicmp(m[0]); + check_arpicmp(m[1]); + check_arpicmp(m[2]); + check_arpicmp(m[3]); + check_arpicmp(m[4]); + check_arpicmp(m[5]); + check_arpicmp(m[6]); + check_arpicmp(m[7]); + } eth_hdr[0] = rte_pktmbuf_mtod(m[0], struct ether_hdr *); eth_hdr[1] = rte_pktmbuf_mtod(m[1], struct ether_hdr *); @@ -790,7 +1072,6 @@ simple_ipv4_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_con memset(&tmp,0,sizeof (struct ether_hdr)); - int i; for(i=0;i<8;i++) { @@ -817,12 +1098,30 @@ simple_ipv4_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_con ipv4_hdr[7] = rte_pktmbuf_mtod_offset(m[7], struct ipv4_hdr *, sizeof(struct ether_hdr)); struct ipv4_hdr temp_ipv4; - for(i=0;i<8;i++) - { - temp_ipv4.dst_addr = ipv4_hdr[i]->dst_addr; - ipv4_hdr[i]->dst_addr = ipv4_hdr[i]->src_addr; - ipv4_hdr[i]->src_addr = temp_ipv4.dst_addr; - } + temp_ipv4.dst_addr = ipv4_hdr[0]->dst_addr; + ipv4_hdr[0]->dst_addr = ipv4_hdr[0]->src_addr; + ipv4_hdr[0]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[1]->dst_addr; + ipv4_hdr[1]->dst_addr = ipv4_hdr[1]->src_addr; + ipv4_hdr[1]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[2]->dst_addr; + ipv4_hdr[2]->dst_addr = ipv4_hdr[2]->src_addr; + ipv4_hdr[2]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[3]->dst_addr; + ipv4_hdr[3]->dst_addr = ipv4_hdr[3]->src_addr; + ipv4_hdr[3]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[4]->dst_addr; + ipv4_hdr[4]->dst_addr = ipv4_hdr[4]->src_addr; + ipv4_hdr[4]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[5]->dst_addr; + ipv4_hdr[5]->dst_addr = ipv4_hdr[5]->src_addr; + ipv4_hdr[5]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[6]->dst_addr; + ipv4_hdr[6]->dst_addr = ipv4_hdr[6]->src_addr; + ipv4_hdr[6]->src_addr = temp_ipv4.dst_addr; + temp_ipv4.dst_addr = ipv4_hdr[7]->dst_addr; + ipv4_hdr[7]->dst_addr = ipv4_hdr[7]->src_addr; + ipv4_hdr[7]->src_addr = temp_ipv4.dst_addr; /* Handle UDP headers.*/ udp_hdr[0] = rte_pktmbuf_mtod_offset(m[0], struct udp_hdr *, @@ -845,44 +1144,62 @@ simple_ipv4_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_con /*1) memcpy or assignment.*/ struct udp_hdr temp_udp; - for(i=0;i<8;i++) - { - temp_udp.dst_port = udp_hdr[i]->dst_port; - udp_hdr[i]->dst_port = udp_hdr[i]->src_port; - udp_hdr[i]->src_port = temp_udp.dst_port; - } + temp_udp.dst_port = udp_hdr[0]->dst_port; + udp_hdr[0]->dst_port = udp_hdr[0]->src_port; + udp_hdr[0]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[1]->dst_port; + udp_hdr[1]->dst_port = udp_hdr[1]->src_port; + udp_hdr[1]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[2]->dst_port; + udp_hdr[2]->dst_port = udp_hdr[2]->src_port; + udp_hdr[2]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[3]->dst_port; + udp_hdr[3]->dst_port = udp_hdr[3]->src_port; + udp_hdr[3]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[4]->dst_port; + udp_hdr[4]->dst_port = udp_hdr[4]->src_port; + udp_hdr[4]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[5]->dst_port; + udp_hdr[5]->dst_port = udp_hdr[5]->src_port; + udp_hdr[5]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[6]->dst_port; + udp_hdr[6]->dst_port = udp_hdr[6]->src_port; + udp_hdr[6]->src_port = temp_udp.dst_port; + temp_udp.dst_port = udp_hdr[7]->dst_port; + udp_hdr[7]->dst_port = udp_hdr[7]->src_port; + udp_hdr[7]->src_port = temp_udp.dst_port; #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ uint8_t valid_mask = MASK_ALL_PKTS; - if (is_valid_ipv4_pkt(ipv4_hdr[0], m[0]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[0], m[0]->pkt_len) < 0) { rte_pktmbuf_free(m[0]); valid_mask &= EXCLUDE_1ST_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[1], m[1]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[1], m[1]->pkt_len) < 0) { rte_pktmbuf_free(m[1]); valid_mask &= EXCLUDE_2ND_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[2], m[2]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[2], m[2]->pkt_len) < 0) { rte_pktmbuf_free(m[2]); valid_mask &= EXCLUDE_3RD_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[3], m[3]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[3], m[3]->pkt_len) < 0) { rte_pktmbuf_free(m[3]); valid_mask &= EXCLUDE_4TH_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[4], m[4]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[4], m[4]->pkt_len) < 0) { rte_pktmbuf_free(m[4]); valid_mask &= EXCLUDE_5TH_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[5], m[5]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[5], m[5]->pkt_len) < 0) { rte_pktmbuf_free(m[5]); valid_mask &= EXCLUDE_6TH_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[6], m[6]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[6], m[6]->pkt_len) < 0) { rte_pktmbuf_free(m[6]); valid_mask &= EXCLUDE_7TH_PKT; } - if (is_valid_ipv4_pkt(ipv4_hdr[7], m[7]->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr[7], m[7]->pkt_len) < 0) { rte_pktmbuf_free(m[7]); valid_mask &= EXCLUDE_8TH_PKT; } @@ -948,10 +1265,28 @@ static inline void simple_ipv6_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_conf *qconf) { struct ether_hdr *eth_hdr[8],tmp; + int i; __attribute__((unused)) struct ipv6_hdr *ipv6_hdr[8], temp_ipv6; int32_t ret[8]; union ipv6_5tuple_host key[8]; struct udp_hdr *udp_hdr[8]; + l2_phy_interface_t *port = ifm_get_port(portid); + if (port == NULL) { + printf("port may be un initialized\n"); + return; + } + + if (unlikely(arp_support)) { + check_arpicmpv6(m[0]); + check_arpicmpv6(m[1]); + check_arpicmpv6(m[2]); + check_arpicmpv6(m[3]); + check_arpicmpv6(m[4]); + check_arpicmpv6(m[5]); + check_arpicmpv6(m[6]); + check_arpicmpv6(m[7]); + } + eth_hdr[0] = rte_pktmbuf_mtod(m[0], struct ether_hdr *); eth_hdr[1] = rte_pktmbuf_mtod(m[1], struct ether_hdr *); @@ -964,7 +1299,6 @@ simple_ipv6_replay_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_con memset(&tmp,0,sizeof (struct ether_hdr)); - int i; for(i=0;i<8;i++) { ether_addr_copy(ð_hdr[i]->s_addr, &tmp.s_addr); @@ -1046,9 +1380,23 @@ udp_replay_simple_replay(struct rte_mbuf *m, uint8_t portid, struct lcore_conf * { struct ether_hdr *eth_hdr,tmp; struct ipv4_hdr *ipv4_hdr,temp_ipv4; - uint8_t dst_port; struct udp_hdr *udp_hdr,temp_udp; + l2_phy_interface_t *port = ifm_get_port(portid); + if (port == NULL) { + printf("port may be un initialized\n"); + return; + } + if (m == NULL) { + printf("Null packet received\n"); + return; + } + if (unlikely(arp_support)) { + if (!check_arpicmp(m)) + return; + } + if (qconf == NULL) + printf("qconf configuration is NULL\n"); eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); ether_addr_copy(ð_hdr->s_addr, &tmp.s_addr); ether_addr_copy(ð_hdr->d_addr, ð_hdr->s_addr); @@ -1064,15 +1412,12 @@ udp_replay_simple_replay(struct rte_mbuf *m, uint8_t portid, struct lcore_conf * ipv4_hdr->src_addr = temp_ipv4.dst_addr; #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ - if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { + if (is_valid_pkt_ipv4(ipv4_hdr, m->pkt_len) < 0) { rte_pktmbuf_free(m); return; } #endif - dst_port = get_ipv4_dst_port(ipv4_hdr, portid, - qconf->ipv4_lookup_struct); - dst_port = portid; #ifdef DO_RFC_1812_CHECKS /* Update time to live and header checksum */ @@ -1088,7 +1433,7 @@ udp_replay_simple_replay(struct rte_mbuf *m, uint8_t portid, struct lcore_conf * udp_hdr->dst_port = udp_hdr->src_port; udp_hdr->src_port = temp_udp.dst_port; - send_single_packet(m, dst_port); + send_single_packet(m, portid); } else if ((rte_cpu_to_be_16(eth_h->ether_type)) == ETHER_TYPE_IPv6) { /* Handle IPv6 headers.*/ struct ipv6_hdr *ipv6_hdr,temp_ipv6; @@ -1101,8 +1446,6 @@ udp_replay_simple_replay(struct rte_mbuf *m, uint8_t portid, struct lcore_conf * memcpy(ipv6_hdr->dst_addr,ipv6_hdr->src_addr,16); memcpy(ipv6_hdr->src_addr,temp_ipv6.dst_addr,16); - - dst_port = get_ipv6_dst_port(ipv6_hdr, portid, qconf->ipv6_lookup_struct); /* Handle UDP headers.*/ udp_hdr = rte_pktmbuf_mtod_offset(m, struct udp_hdr *, (sizeof(struct ether_hdr)+sizeof(struct ipv6_hdr))); @@ -1513,6 +1856,7 @@ main_loop(__attribute__((unused)) void *dummy) int i, j, nb_rx; uint8_t portid, queueid; struct lcore_conf *qconf; + l2_phy_interface_t *port; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; @@ -1547,7 +1891,7 @@ main_loop(__attribute__((unused)) void *dummy) portid, queueid); } - while (1) { + while (exit_loop) { cur_tsc = rte_rdtsc(); @@ -1579,8 +1923,15 @@ main_loop(__attribute__((unused)) void *dummy) for (i = 0; i < qconf->n_rx_queue; ++i) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; - nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, - MAX_PKT_BURST); + port = ifm_get_port(portid); + if (port != NULL) { + nb_rx = port->retrieve_bulk_pkts(portid, + queueid, pkts_burst); + port->n_rxpkts += nb_rx; + } else { + printf("port may be un initialized\n"); + return 0; + } if(nb_rx) rcv_pkt_count[portid] += nb_rx; if (nb_rx == 0) @@ -1595,20 +1946,37 @@ main_loop(__attribute__((unused)) void *dummy) */ int32_t n = RTE_ALIGN_FLOOR(nb_rx, 8); for (j = 0; j < n; j += 8) { - uint32_t pkt_type = - pkts_burst[j]->packet_type & - pkts_burst[j+1]->packet_type & - pkts_burst[j+2]->packet_type & - pkts_burst[j+3]->packet_type & - pkts_burst[j+4]->packet_type & - pkts_burst[j+5]->packet_type & - pkts_burst[j+6]->packet_type & - pkts_burst[j+7]->packet_type; - if (pkt_type & RTE_PTYPE_L3_IPV4) { + struct ether_hdr *eth_h0 = + rte_pktmbuf_mtod(pkts_burst[j], struct ether_hdr *); + struct ether_hdr *eth_h1 = + rte_pktmbuf_mtod(pkts_burst[j+1], struct ether_hdr *); + struct ether_hdr *eth_h2 = + rte_pktmbuf_mtod(pkts_burst[j+2], struct ether_hdr *); + struct ether_hdr *eth_h3 = + rte_pktmbuf_mtod(pkts_burst[j+3], struct ether_hdr *); + struct ether_hdr *eth_h4 = + rte_pktmbuf_mtod(pkts_burst[j+4], struct ether_hdr *); + struct ether_hdr *eth_h5 = + rte_pktmbuf_mtod(pkts_burst[j+5], struct ether_hdr *); + struct ether_hdr *eth_h6 = + rte_pktmbuf_mtod(pkts_burst[j+6], struct ether_hdr *); + struct ether_hdr *eth_h7 = + rte_pktmbuf_mtod(pkts_burst[j+7], struct ether_hdr *); + + uint16_t ether_type; + ether_type = (rte_cpu_to_be_16(eth_h0->ether_type) & + rte_cpu_to_be_16(eth_h1->ether_type) & + rte_cpu_to_be_16(eth_h2->ether_type) & + rte_cpu_to_be_16(eth_h3->ether_type) & + rte_cpu_to_be_16(eth_h4->ether_type) & + rte_cpu_to_be_16(eth_h5->ether_type) & + rte_cpu_to_be_16(eth_h6->ether_type) & + rte_cpu_to_be_16(eth_h7->ether_type)); + + if (ether_type == ETHER_TYPE_IPv4) { simple_ipv4_replay_8pkts( &pkts_burst[j], portid, qconf); - } else if (pkt_type & - RTE_PTYPE_L3_IPV6) { + } else if (ether_type == ETHER_TYPE_IPv6) { simple_ipv6_replay_8pkts(&pkts_burst[j], portid, qconf); } else { @@ -1630,6 +1998,7 @@ main_loop(__attribute__((unused)) void *dummy) portid, qconf); } } + for (; j < nb_rx ; j++) { udp_replay_simple_replay(pkts_burst[j], portid, qconf); @@ -1780,17 +2149,17 @@ main_loop(__attribute__((unused)) void *dummy) /* display usage */ int -print_stats(void) +print_l4stats(void) { unsigned portid; - uint16_t i; + uint16_t i, j=0; printf ("\n"); printf ("UDP_Replay stats:\n"); printf ("--------------\n"); - printf (" Port Rx Packet Tx Packet Rx Pkt Drop Tx Pkt Drop \n"); + printf (" Port Rx Packet Tx Packet Rx Pkt Drop Tx Pkt Drop arp_pkts\n"); for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; - printf (" %u %lu %lu 0 0", portid, rcv_pkt_count[(uint64_t)portid], tx_pkt_count[(uint64_t)portid]); + printf ("%5u%15lu%15lu%17d%17d%14u",portid, rcv_pkt_count[portid], tx_pkt_count[portid],j,j, arp_pkts); printf ("\n"); } printf ("\n"); @@ -1806,7 +2175,7 @@ clear_stats(void) rcv_pkt_count[i] = 0; tx_pkt_count[i] = 0; } - print_stats(); + print_l4stats(); return 0; } @@ -1931,6 +2300,32 @@ static int parse_max_pkt_len(const char *pktlen) } static int +parse_link_ip(const char *file_name) +{ + uint32_t i, type; + struct rte_cfgfile *file; + const char *entry; + char buf[256]; + file = rte_cfgfile_load(file_name, 0); + entry = rte_cfgfile_get_entry(file, "linkip", "num_ports"); + numports = (uint32_t)atoi(entry); + if (numports <= 0 || numports > 32) + rte_panic("numports is not valid\n"); + entry = rte_cfgfile_get_entry(file, "linkip", "ip_type"); + type = (uint32_t)atoi(entry); + for (i = 0;i < numports; i++) { + sprintf(buf, "port%d", i); + entry = rte_cfgfile_get_entry(file, "linkip", buf); + if (entry == NULL) + continue; + if (!type) + ipv4[i] = strdup(entry); + else if (type) + my_inet_pton_ipv6(AF_INET6, entry, &link_ipv6[i][0]); + } + return 0; +} +static int parse_portmask(const char *portmask) { char *end = NULL; @@ -2073,10 +2468,14 @@ parse_args(int argc, char **argv) argvopt = argv; - while ((opt = getopt_long(argc, argvopt, "p:P", + while ((opt = getopt_long(argc, argvopt, "s:p:P", lgopts, &option_index)) != EOF) { switch (opt) { + case 's': + parse_link_ip(optarg); + arp_support = 1; + break; /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); @@ -2118,6 +2517,7 @@ parse_args(int argc, char **argv) sizeof(CMD_LINE_OPT_NO_HW_CSUM))) { printf("numa is hw ip checksum \n"); port_conf.rxmode.hw_ip_checksum = 0; + rx_conf.rx_free_thresh = 30; csum_on = 0; } @@ -2178,14 +2578,6 @@ parse_args(int argc, char **argv) return ret; } -static void -print_ethaddr(const char *name, const struct ether_addr *eth_addr) -{ - char buf[ETHER_ADDR_FMT_SIZE]; - ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); - printf("%s%s", name, buf); -} - #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void convert_ipv4_5tuple(struct ipv4_5tuple* key1, @@ -2349,69 +2741,6 @@ populate_ipv6_many_flow_into_table(const struct rte_hash* h, printf("Hash: Adding 0x%x keys\n", nr_flow); } -static void -setup_hash(int socketid) -{ - struct rte_hash_parameters ipv4_udp_replay_hash_params = { - .name = NULL, - .entries = UDP_Replay_HASH_ENTRIES, - .key_len = sizeof(union ipv4_5tuple_host), - .hash_func = ipv4_hash_crc, - .hash_func_init_val = 0, - }; - - struct rte_hash_parameters ipv6_udp_replay_hash_params = { - .name = NULL, - .entries = UDP_Replay_HASH_ENTRIES, - .key_len = sizeof(union ipv6_5tuple_host), - .hash_func = ipv6_hash_crc, - .hash_func_init_val = 0, - }; - - char s[64]; - - /* create ipv4 hash */ - snprintf(s, sizeof(s), "ipv4_udp_replay_hash_%d", socketid); - ipv4_udp_replay_hash_params.name = s; - ipv4_udp_replay_hash_params.socket_id = socketid; - ipv4_udp_replay_lookup_struct[socketid] = rte_hash_create(&ipv4_udp_replay_hash_params); - if (ipv4_udp_replay_lookup_struct[socketid] == NULL) - rte_exit(EXIT_FAILURE, "Unable to create the udp_replay hash on " - "socket %d\n", socketid); - - /* create ipv6 hash */ - snprintf(s, sizeof(s), "ipv6_udp_replay_hash_%d", socketid); - ipv6_udp_replay_hash_params.name = s; - ipv6_udp_replay_hash_params.socket_id = socketid; - ipv6_udp_replay_lookup_struct[socketid] = rte_hash_create(&ipv6_udp_replay_hash_params); - if (ipv6_udp_replay_lookup_struct[socketid] == NULL) - rte_exit(EXIT_FAILURE, "Unable to create the udp_replay hash on " - "socket %d\n", socketid); - - if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { - /* For testing hash matching with a large number of flows we - * generate millions of IP 5-tuples with an incremented dst - * address to initialize the hash table. */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_many_flow_into_table( - ipv4_udp_replay_lookup_struct[socketid], hash_entry_number); - } else { - /* populate the ipv6 hash */ - populate_ipv6_many_flow_into_table( - ipv6_udp_replay_lookup_struct[socketid], hash_entry_number); - } - } else { - /* Use data in ipv4/ipv6 udp_replay lookup table directly to initialize the hash table */ - if (ipv6 == 0) { - /* populate the ipv4 hash */ - populate_ipv4_few_flow_into_table(ipv4_udp_replay_lookup_struct[socketid]); - } else { - /* populate the ipv6 hash */ - populate_ipv6_few_flow_into_table(ipv6_udp_replay_lookup_struct[socketid]); - } - } -} #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) @@ -2495,51 +2824,10 @@ setup_lpm(int socketid) } #endif -static int -init_mem(unsigned nb_mbuf) -{ - struct lcore_conf *qconf; - int socketid; - unsigned lcore_id; - char s[64]; - for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) == 0) - continue; - if (numa_on) - socketid = rte_lcore_to_socket_id(lcore_id); - else - socketid = 0; - if (socketid >= NB_SOCKETS) { - rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", - socketid, lcore_id, NB_SOCKETS); - } - if (pktmbuf_pool[socketid] == NULL) { - snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); - pktmbuf_pool[socketid] = - rte_pktmbuf_pool_create(s, nb_mbuf, - MEMPOOL_CACHE_SIZE, 0, - RTE_MBUF_DEFAULT_BUF_SIZE, socketid); - if (pktmbuf_pool[socketid] == NULL) - rte_exit(EXIT_FAILURE, - "Cannot init mbuf pool on socket %d\n", socketid); - else - printf("Allocated mbuf pool on socket %d\n", socketid); -#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) - setup_lpm(socketid); -#else - setup_hash(socketid); -#endif - } - qconf = &lcore_conf[lcore_id]; - qconf->ipv4_lookup_struct = ipv4_udp_replay_lookup_struct[socketid]; - qconf->ipv6_lookup_struct = ipv6_udp_replay_lookup_struct[socketid]; - } - return 0; -} /* Check the link status of all ports in up to 9s, and print them finally */ static void @@ -2599,16 +2887,14 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) int main(int argc, char **argv) { - struct lcore_conf *qconf; - struct rte_eth_dev_info dev_info; - struct rte_eth_txconf *txconf; int ret; unsigned nb_ports; - uint16_t queueid; unsigned lcore_id; uint32_t n_tx_queue, nb_lcores; - uint8_t portid, nb_rx_queue, queue, socketid; + uint8_t portid, nb_rx_queue; struct cmdline *cl; + uint32_t size; + struct pipeline_params *params; /* init EAL */ ret = rte_eal_init(argc, argv); @@ -2616,6 +2902,7 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; + timer_lcore = rte_lcore_id(); /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) @@ -2628,7 +2915,12 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); + params = rte_malloc(NULL, sizeof(*params), RTE_CACHE_LINE_SIZE); + memcpy(params, &def_pipeline_params, sizeof(def_pipeline_params)); + lib_arp_init(params, NULL); + ifm_init(); nb_ports = rte_eth_dev_count(); + num_ports = nb_ports; if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; @@ -2637,11 +2929,19 @@ main(int argc, char **argv) nb_lcores = rte_lcore_count(); + /* + *Configuring port_config_t structure for interface manager initialization + */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(port_config_t)); + port_config = rte_zmalloc(NULL, (RTE_MAX_ETHPORTS * size), RTE_CACHE_LINE_SIZE); + if (port_config == NULL) + rte_panic("port_config is NULL: Memory Allocation failure\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); + num_ports--; continue; } @@ -2650,116 +2950,38 @@ main(int argc, char **argv) fflush(stdout); nb_rx_queue = get_port_n_rx_queues(portid); - n_tx_queue = nb_rx_queue; + n_tx_queue = nb_rx_queue; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; - printf("Creating queues: nb_rxq=%d nb_txq=%u... ", - nb_rx_queue, (unsigned)n_tx_queue ); - ret = rte_eth_dev_configure(portid, nb_rx_queue, - (uint16_t)n_tx_queue, &port_conf); - if (ret < 0) { - printf("Port configuration failed : port: %d... Try with hw-ip-checksum disabled\n", portid); - port_conf.rxmode.hw_ip_checksum = 0; - ret = rte_eth_dev_configure(portid, nb_rx_queue, - (uint16_t)n_tx_queue, &port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", - ret, portid); - } - /*Since its just swapping of MAC we dont have to fill our own src mac*/ - rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); - print_ethaddr(" Address:", &ports_eth_addr[portid]); - - /* init memory */ - ret = init_mem(NB_MBUF); - if (ret < 0) - rte_exit(EXIT_FAILURE, "init_mem failed\n"); - - /* init one TX queue per couple (lcore,port) */ - queueid = 0; - for (lcore_id = 0; lcore_id < n_tx_queue; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) == 0) - continue; - - if (numa_on) - socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); - else - socketid = 0; - - printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); - fflush(stdout); - - rte_eth_dev_info_get(portid, &dev_info); - txconf = &dev_info.default_txconf; - if (port_conf.rxmode.jumbo_frame) - txconf->txq_flags = 0; - ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, - socketid, txconf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " - "port=%d\n", ret, portid); - - qconf = &lcore_conf[lcore_id]; - qconf->tx_queue_id[portid] = queueid; - queueid++; - } - printf("\n"); - } - - for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) == 0) - continue; - qconf = &lcore_conf[lcore_id]; - printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); - fflush(stdout); - /* init RX queues */ - for(queue = 0; queue < qconf->n_rx_queue; ++queue) { - portid = qconf->rx_queue_list[queue].port_id; - queueid = qconf->rx_queue_list[queue].queue_id; - - if (numa_on) - socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); - else - socketid = 0; - - printf("rxq=%d,%d,%d ", portid, queueid, socketid); - fflush(stdout); - - ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, - socketid, - NULL, - pktmbuf_pool[socketid]); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," - "port=%d\n", ret, portid); - } - } - - printf("\n"); - /* start ports */ - for (portid = 0; portid < nb_ports; portid++) { - if ((enabled_port_mask & (1 << portid)) == 0) { - continue; - } - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", - ret, portid); - - /* - * If enabled, put device in promiscuous mode. - * This allows IO forwarding mode to forward packets - * to itself through 2 cross-connected ports of the - * target machine. - */ - if (promiscuous_on) - rte_eth_promiscuous_enable(portid); + port_config[portid].port_id = portid; + port_config[portid].nrx_queue = nb_rx_queue; + port_config[portid].ntx_queue = n_tx_queue; + port_config[portid].state = 1; + port_config[portid].promisc = promiscuous_on; + port_config[portid].mempool.pool_size = MEMPOOL_SIZE; + port_config[portid].mempool.buffer_size = BUFFER_SIZE + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM; + port_config[portid].mempool.cache_size = CACHE_SIZE; + port_config[portid].mempool.cpu_socket_id = rte_socket_id(); + memcpy (&port_config[portid].port_conf, &port_conf, sizeof(struct rte_eth_conf)); + memcpy (&port_config[portid].rx_conf, &rx_conf, sizeof(struct rte_eth_rxconf)); + memcpy (&port_config[portid].tx_conf, &tx_conf, sizeof(struct rte_eth_txconf)); + + /* Enable TCP and UDP HW Checksum , when required */ + //port_config[portid].tx_conf.txq_flags &= + // ~(ETH_TXQ_FLAGS_NOXSUMTCP|ETH_TXQ_FLAGS_NOXSUMUDP); + + if (ifm_port_setup (portid, &port_config[portid])) + rte_panic ("Port Setup Failed: %"PRIu32"\n", portid); } check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); + l3fwd_init(); + create_arp_table(); + create_nd_table(); + populate_lpm_routes(); + convert_ipstr_to_numeric(); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); cl = cmdline_stdin_new(main_ctx, "Replay>"); @@ -2767,6 +2989,7 @@ main(int argc, char **argv) rte_panic("Cannot create cmdline instance\n"); cmdline_interact(cl); cmdline_stdin_exit(cl); + exit_loop = 0; rte_exit(0, "Bye!\n"); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) @@ -2821,7 +3044,7 @@ static void cmd_udp_replay_stats_parsed( __rte_unused struct cmdline *cl, __attribute__((unused)) void *data) { - print_stats(); + print_l4stats(); } cmdline_parse_token_string_t cmd_udp_replay_stats_udp_replay_string = |