X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fip_reassembly%2Fmain.c;h=c4427b3a237b24ad2f01908ebb4dd0a5866aadf7;hb=361b2e9559fc;hp=e18dfe89c5b288cadec7230a3ec3e9f707fc85c5;hpb=cc8f4d020c0b7c721e3056bc6aef331672dd95c6;p=dpdk.git diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c index e18dfe89c5..c4427b3a23 100644 --- a/examples/ip_reassembly/main.c +++ b/examples/ip_reassembly/main.c @@ -1,35 +1,34 @@ /*- * BSD LICENSE - * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions + * + * 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 + * + * * 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 + * * 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 Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived + * * Neither the name of Intel Corporation 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 + * + * 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 @@ -74,9 +73,7 @@ #include #include #include - #include "main.h" -#include "ipv4_rsmbl.h" #define APP_LOOKUP_EXACT_MATCH 0 #define APP_LOOKUP_LPM 1 @@ -95,6 +92,10 @@ #error "APP_LOOKUP_METHOD set to incorrect value" #endif +#define MAX_PKT_BURST 32 + +#include "ipv4_rsmbl.h" + #ifndef IPv6_BYTES #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ "%02x%02x:%02x%02x:%02x%02x:%02x%02x" @@ -156,7 +157,6 @@ static uint32_t max_flow_ttl = DEF_FLOW_TTL; #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ -#define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 8 @@ -169,6 +169,7 @@ static uint32_t max_flow_ttl = DEF_FLOW_TTL; */ #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; @@ -181,8 +182,10 @@ static int promiscuous_on = 0; /**< Ports set in promiscuous mode off by default static int numa_on = 1; /**< NUMA is enabled by default. */ struct mbuf_table { - uint16_t len; - struct rte_mbuf *m_table[MAX_PKT_BURST]; + uint32_t len; + uint32_t head; + uint32_t tail; + struct rte_mbuf *m_table[0]; }; struct lcore_rx_queue { @@ -220,7 +223,8 @@ static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / static struct rte_eth_conf port_conf = { .rxmode = { - .max_rx_pkt_len = ETHER_MAX_LEN, + .mq_mode = ETH_MQ_RX_RSS, + .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ @@ -380,11 +384,23 @@ static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; static lookup6_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; #endif +struct tx_lcore_stat { + uint64_t call; + uint64_t drop; + uint64_t queue; + uint64_t send; +}; + +#ifdef IPV4_FRAG_TBL_STAT +#define TX_LCORE_STAT_UPDATE(s, f, v) ((s)->f += (v)) +#else +#define TX_LCORE_STAT_UPDATE(s, f, v) do {} while (0) +#endif /* IPV4_FRAG_TBL_STAT */ + struct lcore_conf { uint16_t n_rx_queue; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[MAX_PORTS]; - struct mbuf_table tx_mbufs[MAX_PORTS]; lookup_struct_t * ipv4_lookup_struct; #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) lookup6_struct_t * ipv6_lookup_struct; @@ -393,54 +409,75 @@ struct lcore_conf { #endif struct ipv4_frag_tbl *frag_tbl[MAX_RX_QUEUE_PER_LCORE]; struct rte_mempool *pool[MAX_RX_QUEUE_PER_LCORE]; + struct ipv4_frag_death_row death_row; + struct mbuf_table *tx_mbufs[MAX_PORTS]; + struct tx_lcore_stat tx_stat; } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; -/* Send burst of packets on an output interface */ -static inline int -send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) +/* + * If number of queued packets reached given threahold, then + * send burst of packets on an output interface. + */ +static inline uint32_t +send_burst(struct lcore_conf *qconf, uint32_t thresh, uint8_t port) { - struct rte_mbuf **m_table; - int ret; - uint16_t queueid; + uint32_t fill, len, k, n; + struct mbuf_table *txmb; + + txmb = qconf->tx_mbufs[port]; + len = txmb->len; + + if ((int32_t)(fill = txmb->head - txmb->tail) < 0) + fill += len; - queueid = qconf->tx_queue_id[port]; - m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; + if (fill >= thresh) { + n = RTE_MIN(len - txmb->tail, fill); - ret = rte_eth_tx_burst(port, queueid, m_table, n); - if (unlikely(ret < n)) { - do { - rte_pktmbuf_free(m_table[ret]); - } while (++ret < n); + k = rte_eth_tx_burst(port, qconf->tx_queue_id[port], + txmb->m_table + txmb->tail, (uint16_t)n); + + TX_LCORE_STAT_UPDATE(&qconf->tx_stat, call, 1); + TX_LCORE_STAT_UPDATE(&qconf->tx_stat, send, k); + + fill -= k; + if ((txmb->tail += k) == len) + txmb->tail = 0; } - return 0; + return (fill); } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { - uint32_t lcore_id; - uint16_t len; + uint32_t fill, lcore_id, len; struct lcore_conf *qconf; + struct mbuf_table *txmb; lcore_id = rte_lcore_id(); - qconf = &lcore_conf[lcore_id]; - len = qconf->tx_mbufs[port].len; - qconf->tx_mbufs[port].m_table[len] = m; - len++; - - /* enough pkts to be sent */ - if (unlikely(len == MAX_PKT_BURST)) { - send_burst(qconf, MAX_PKT_BURST, port); - len = 0; + + txmb = qconf->tx_mbufs[port]; + len = txmb->len; + + fill = send_burst(qconf, MAX_PKT_BURST, port); + + if (fill == len - 1) { + TX_LCORE_STAT_UPDATE(&qconf->tx_stat, drop, 1); + rte_pktmbuf_free(txmb->m_table[txmb->tail]); + if (++txmb->tail == len) + txmb->tail = 0; } - qconf->tx_mbufs[port].len = len; - return 0; + TX_LCORE_STAT_UPDATE(&qconf->tx_stat, queue, 1); + txmb->m_table[txmb->head] = m; + if(++txmb->head == len) + txmb->head = 0; + + return (0); } #ifdef DO_RFC_1812_CHECKS @@ -637,16 +674,18 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, uint32_t queue, struct rte_mbuf *mo; struct ipv4_frag_tbl *tbl; + struct ipv4_frag_death_row *dr; tbl = qconf->frag_tbl[queue]; + dr = &qconf->death_row; /* prepare mbuf: setup l2_len/l3_len. */ m->pkt.vlan_macip.f.l2_len = sizeof(*eth_hdr); m->pkt.vlan_macip.f.l3_len = sizeof(*ipv4_hdr); /* process this fragment. */ - if ((mo = ipv4_frag_mbuf(tbl, m, tms, ipv4_hdr, - ip_ofs, ip_flag)) == NULL) + if ((mo = ipv4_frag_mbuf(tbl, dr, m, tms, ipv4_hdr, + ip_ofs, ip_flag)) == NULL) /* no packet to send out. */ return; @@ -659,8 +698,10 @@ l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, uint32_t queue, } } - dst_port = get_ipv4_dst_port(ipv4_hdr, portid, qconf->ipv4_lookup_struct); - if (dst_port >= MAX_PORTS || (enabled_port_mask & 1 << dst_port) == 0) + dst_port = get_ipv4_dst_port(ipv4_hdr, portid, + qconf->ipv4_lookup_struct); + if (dst_port >= MAX_PORTS || + (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; /* 02:00:00:00:00:xx */ @@ -743,12 +784,8 @@ main_loop(__attribute__((unused)) void *dummy) * portid), but it is not called so often */ for (portid = 0; portid < MAX_PORTS; portid++) { - if (qconf->tx_mbufs[portid].len == 0) - continue; - send_burst(&lcore_conf[lcore_id], - qconf->tx_mbufs[portid].len, - portid); - qconf->tx_mbufs[portid].len = 0; + if ((enabled_port_mask & (1 << portid)) != 0) + send_burst(qconf, 1, portid); } prev_tsc = cur_tsc; @@ -784,6 +821,9 @@ main_loop(__attribute__((unused)) void *dummy) l3fwd_simple_forward(pkts_burst[j], portid, i, qconf, cur_tsc); } + + ipv4_frag_free_death_row(&qconf->death_row, + PREFETCH_OFFSET); } } } @@ -918,8 +958,8 @@ parse_flow_ttl(const char *str, uint32_t min, uint32_t max, uint32_t *val) char *end; uint64_t v; - static const char frmt_sec[] = "s"; - static const char frmt_msec[] = "ms"; + static const char frmt_sec[] = "s"; + static const char frmt_msec[] = "ms"; /* parse decimal string */ errno = 0; @@ -1078,7 +1118,7 @@ parse_args(int argc, char **argv) printf("numa is disabled \n"); numa_on = 0; } - + if (!strncmp(lgopts[option_index].name, "maxflows", 8)) { if ((ret = parse_flow_num(optarg, MIN_FLOW_NUM, @@ -1092,7 +1132,7 @@ parse_args(int argc, char **argv) return (ret); } } - + if (!strncmp(lgopts[option_index].name, "flowttl", 7)) { if ((ret = parse_flow_ttl(optarg, MIN_FLOW_TTL, MAX_FLOW_TTL, @@ -1111,8 +1151,8 @@ parse_args(int argc, char **argv) printf("jumbo frame is enabled \n"); port_conf.rxmode.jumbo_frame = 1; - - /* if no max-pkt-len set, use the default value ETHER_MAX_LEN */ + + /* if no max-pkt-len set, use the default value ETHER_MAX_LEN */ if (0 == getopt_long(argc, argvopt, "", &lenopts, &option_index)) { ret = parse_max_pkt_len(optarg); if ((ret < 64) || (ret > MAX_JUMBO_PKT_LEN)){ @@ -1122,10 +1162,10 @@ parse_args(int argc, char **argv) } port_conf.rxmode.max_rx_pkt_len = ret; } - printf("set jumbo frame max packet length to %u\n", + printf("set jumbo frame max packet length to %u\n", (unsigned int)port_conf.rxmode.max_rx_pkt_len); } - + break; default: @@ -1262,10 +1302,10 @@ setup_lpm(int socketid) ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); } - + /* create the LPM6 table */ rte_snprintf(s, sizeof(s), "IPV6_L3FWD_LPM_%d", socketid); - + config.max_rules = IPV6_L3FWD_LPM_MAX_RULES; config.number_tbl8s = IPV6_L3FWD_LPM_NUMBER_TBL8S; config.flags = 0; @@ -1384,9 +1424,29 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) } } } +static void +setup_port_tbl(struct lcore_conf *qconf, uint32_t lcore, int socket, + uint32_t port) +{ + struct mbuf_table *mtb; + uint32_t n; + size_t sz; + + n = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST); + sz = sizeof (*mtb) + sizeof (mtb->m_table[0]) * n; + + if ((mtb = rte_zmalloc_socket(__func__, sz, CACHE_LINE_SIZE, + socket)) == NULL) + rte_exit(EXIT_FAILURE, "%s() for lcore: %u, port: %u " + "failed to allocate %zu bytes\n", + __func__, lcore, port, sz); + + mtb->len = n; + qconf->tx_mbufs[port] = mtb; +} static void -setup_queue_frag_tbl(struct lcore_conf *qconf, uint32_t lcore, int socket, +setup_queue_tbl(struct lcore_conf *qconf, uint32_t lcore, int socket, uint32_t queue) { uint32_t nb_mbuf; @@ -1403,12 +1463,18 @@ setup_queue_frag_tbl(struct lcore_conf *qconf, uint32_t lcore, int socket, "lcore: %u for queue: %u failed\n", max_flow_num, lcore, queue); - nb_mbuf = max_flow_num * MAX_FRAG_NUM; + /* + * At any given moment up to + * mbufs could be stored int the fragment table. + * Plus, each TX queue can hold up to packets. + */ + + nb_mbuf = 2 * RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * MAX_FRAG_NUM; nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE; - nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + MAX_PKT_BURST + - RTE_TEST_TX_DESC_DEFAULT; + nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + RTE_TEST_TX_DESC_DEFAULT; + nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)DEF_MBUF_NUM); - + rte_snprintf(buf, sizeof(buf), "mbuf_pool_%u_%u", lcore, queue); if ((qconf->pool[queue] = rte_mempool_create(buf, nb_mbuf, MBUF_SIZE, 0, @@ -1419,7 +1485,7 @@ setup_queue_frag_tbl(struct lcore_conf *qconf, uint32_t lcore, int socket, } static void -queue_frag_tbl_dump_stat(void) +queue_dump_stat(void) { uint32_t i, lcore; const struct lcore_conf *qconf; @@ -1436,6 +1502,14 @@ queue_frag_tbl_dump_stat(void) lcore, qconf->rx_queue_list[i].port_id, qconf->rx_queue_list[i].queue_id); ipv4_frag_tbl_dump_stat(stdout, qconf->frag_tbl[i]); + fprintf(stdout, "TX bursts:\t%" PRIu64 "\n" + "TX packets _queued:\t%" PRIu64 "\n" + "TX packets dropped:\t%" PRIu64 "\n" + "TX packets send:\t%" PRIu64 "\n", + qconf->tx_stat.call, + qconf->tx_stat.queue, + qconf->tx_stat.drop, + qconf->tx_stat.send); } } } @@ -1443,7 +1517,7 @@ queue_frag_tbl_dump_stat(void) static void signal_handler(int signum) { - queue_frag_tbl_dump_stat(); + queue_dump_stat(); if (signum != SIGUSR1) rte_exit(0, "received signal: %d, exiting\n", signum); } @@ -1479,10 +1553,6 @@ MAIN(int argc, char **argv) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - /* init driver(s) */ - if (rte_pmd_init_all() < 0) - rte_exit(EXIT_FAILURE, "Cannot init pmd\n"); - if (rte_eal_pci_probe() < 0) rte_exit(EXIT_FAILURE, "Cannot probe PCI\n"); @@ -1549,6 +1619,7 @@ MAIN(int argc, char **argv) qconf = &lcore_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; + setup_port_tbl(qconf, lcore_id, socketid, portid); queueid++; } printf("\n"); @@ -1573,7 +1644,7 @@ MAIN(int argc, char **argv) printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); - setup_queue_frag_tbl(qconf, lcore_id, socketid, queue); + setup_queue_tbl(qconf, lcore_id, socketid, queue); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, &rx_conf, qconf->pool[queue]);