X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=VNFs%2FUDP_Replay%2Fmain.c;h=e6bc8aa3c3e0ae83c336b588177906261d15a049;hb=ef07d20e9777bf0e1af54629eb390a8a5ccd0091;hp=5242adbad87cab57eea847a9be1920277b963f5d;hpb=b72cbc3b1b8bce7c35f2f2970304280fa7f32f23;p=samplevnf.git 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 #include #include +#include +#include #include "parse_obj_list.h" +#include +#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; } @@ -1930,6 +2299,32 @@ static int parse_max_pkt_len(const char *pktlen) return len; } +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) { @@ -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 =