From 3726dc50dd2a9873ac05847be80ca615ea4a708b Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Fri, 24 Nov 2017 15:54:01 +0000 Subject: l4fwd: allow to specify TX payload contents for rxtx mode Introduce a new command-line option that specifies the file with response payload. Change-Id: I1a208eeebe1d87970da23956fb08949abf601422 Signed-off-by: Konstantin Ananyev --- examples/l4fwd/README | 1 + examples/l4fwd/common.h | 48 ++++++++++++++++++++++++++++++---------- examples/l4fwd/main.c | 5 +++++ examples/l4fwd/netbe.h | 7 ++++++ examples/l4fwd/parse.c | 59 +++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 104 insertions(+), 16 deletions(-) diff --git a/examples/l4fwd/README b/examples/l4fwd/README index a7ae56a..dc3dc67 100644 --- a/examples/l4fwd/README +++ b/examples/l4fwd/README @@ -128,6 +128,7 @@ -s | --streams /* streams to open per context. */ \ -b | --becfg /* backend configuration file. */ \ -f | --fecfg /* frontend configuration file. */ \ + -c | --txcnt /* file with TX payload (used by rxtx mode). */ \ -U | --udp /* run the app to handle UDP streams only. */ \ -T | --tcp /* run the app to handle TCP streams only. */ \ -L | --listen /* open TCP streams in server mode (listen). */ \ diff --git a/examples/l4fwd/common.h b/examples/l4fwd/common.h index ae4f266..b7750d7 100644 --- a/examples/l4fwd/common.h +++ b/examples/l4fwd/common.h @@ -634,23 +634,24 @@ netfe_rxtx_get_mss(struct netfe_stream *fes) */ return RTE_MBUF_DEFAULT_DATAROOM - TLE_DST_MAX_HDR; default: - NETFE_TRACE("%s(%u): Unhandled MSS query (family=%i)\n", - __func__, lcore, fes->proto, fes->family); return -EINVAL; } } static inline int netfe_rxtx_dispatch_reply(uint32_t lcore, struct netfe_stream *fes) - { struct pkt_buf *pb; int32_t sid; - int32_t cnt_mtu_pkts; - int32_t cnt_all_pkts; - int32_t idx_pkt; - int32_t len_tail; - int32_t mtu; + uint32_t n; + uint32_t cnt_mtu_pkts; + uint32_t cnt_all_pkts; + uint32_t idx_pkt; + uint32_t len_tail; + uint32_t mtu; + size_t csz, len; + char *dst; + const uint8_t *src; pb = &fes->pbuf; sid = rte_lcore_to_socket_id(lcore) + 1; @@ -675,14 +676,37 @@ netfe_rxtx_dispatch_reply(uint32_t lcore, struct netfe_stream *fes) return -ENOMEM; } + csz = tx_content.sz; + src = tx_content.data; + + n = pb->num; + /* Full MTU packets */ - for (idx_pkt = 0; idx_pkt < cnt_mtu_pkts; idx_pkt++) { - rte_pktmbuf_append(pb->pkt[pb->num++], mtu); + for (idx_pkt = 0; idx_pkt < cnt_mtu_pkts; idx_pkt++, n++) { + rte_pktmbuf_reset(pb->pkt[n]); + dst = rte_pktmbuf_append(pb->pkt[n], mtu); + if (csz > 0) { + len = RTE_MIN(mtu, csz); + rte_memcpy(dst, src, len); + src += len; + csz -= len; + } } /* Last non-MTU packet, if any */ - if (len_tail > 0) - rte_pktmbuf_append(pb->pkt[pb->num++], len_tail); + if (len_tail > 0) { + rte_pktmbuf_reset(pb->pkt[n]); + dst = rte_pktmbuf_append(pb->pkt[n], len_tail); + if (csz > 0) { + len = RTE_MIN(len_tail, csz); + rte_memcpy(dst, src, len); + src += len; + csz -= len; + } + n++; + } + + pb->num = n; return 0; } diff --git a/examples/l4fwd/main.c b/examples/l4fwd/main.c index c43b8d7..ff572be 100644 --- a/examples/l4fwd/main.c +++ b/examples/l4fwd/main.c @@ -73,6 +73,11 @@ static const struct rte_eth_conf port_conf_default = { }, }; +struct tx_content tx_content = { + .sz = 0, + .data = NULL, +}; + /* function pointers */ static TLE_RX_BULK_FUNCTYPE tle_rx_bulk; static TLE_TX_BULK_FUNCTYPE tle_tx_bulk; diff --git a/examples/l4fwd/netbe.h b/examples/l4fwd/netbe.h index 134ce3d..ebb1345 100644 --- a/examples/l4fwd/netbe.h +++ b/examples/l4fwd/netbe.h @@ -251,6 +251,13 @@ struct lcore_prm { struct netfe_lcore_prm fe; }; +struct tx_content { + size_t sz; + uint8_t *data; +}; + +extern struct tx_content tx_content; + /* * debug/trace macros. */ diff --git a/examples/l4fwd/parse.c b/examples/l4fwd/parse.c index 97cf20d..40adee4 100644 --- a/examples/l4fwd/parse.c +++ b/examples/l4fwd/parse.c @@ -16,6 +16,10 @@ #include #include #include +#include +#include +#include + #include "netbe.h" #include "parse.h" @@ -32,9 +36,6 @@ static const struct { { .name = "fwd", .op = FWD,}, }; -#define OPT_SHORT_ARP 'a' -#define OPT_LONG_ARP "enable-arp" - #define OPT_SHORT_SBULK 'B' #define OPT_LONG_SBULK "sburst" @@ -50,9 +51,15 @@ static const struct { #define OPT_SHORT_SBUFS 'S' #define OPT_LONG_SBUFS "sbufs" +#define OPT_SHORT_ARP 'a' +#define OPT_LONG_ARP "enable-arp" + #define OPT_SHORT_BECFG 'b' #define OPT_LONG_BECFG "becfg" +#define OPT_SHORT_TXCNT 'c' +#define OPT_LONG_TXCNT "txcnt" + #define OPT_SHORT_FECFG 'f' #define OPT_LONG_FECFG "fecfg" @@ -101,6 +108,7 @@ static const struct option long_opt[] = { {OPT_LONG_VERBOSE, 1, 0, OPT_SHORT_VERBOSE}, {OPT_LONG_WINDOW, 1, 0, OPT_SHORT_WINDOW}, {OPT_LONG_TIMEWAIT, 1, 0, OPT_SHORT_TIMEWAIT}, + {OPT_LONG_TXCNT, 1, 0, OPT_SHORT_TXCNT}, {NULL, 0, 0, 0} }; @@ -759,6 +767,42 @@ parse_hash_alg(const char *val) return TLE_HASH_NUM; } +static int +read_tx_content(const char *fname, struct tx_content *tx) +{ + int32_t fd, rc; + ssize_t sz; + struct stat st; + + rc = stat(fname, &st); + if (rc != 0) + return -errno; + + tx->data = rte_malloc(NULL, st.st_size, RTE_CACHE_LINE_SIZE); + if (tx->data == NULL) { + RTE_LOG(ERR, USER1, "%s(%s): failed to alloc %zu bytes;\n", + __func__, fname, st.st_size); + return -ENOMEM; + } + + fd = open(fname, O_RDONLY); + sz = read(fd, tx->data, st.st_size); + + RTE_LOG(NOTICE, USER1, "%s(%s): read %zd bytes from fd=%d;\n", + __func__, fname, sz, fd); + + close(fd); + + if (sz != st.st_size) { + rc = -errno; + sz = 0; + rte_free(tx->data); + } + + tx->sz = sz; + return rc; +} + int parse_app_options(int argc, char **argv, struct netbe_cfg *cfg, struct tle_ctx_param *ctx_prm, @@ -772,7 +816,7 @@ parse_app_options(int argc, char **argv, struct netbe_cfg *cfg, optind = 0; optarg = NULL; - while ((opt = getopt_long(argc, argv, "aB:C:LPR:S:TUb:f:s:v:H:K:W:w:", + while ((opt = getopt_long(argc, argv, "aB:C:c:LPR:S:TUb:f:s:v:H:K:W:w:", long_opt, &opt_idx)) != EOF) { if (opt == OPT_SHORT_ARP) { cfg->arp = 1; @@ -869,6 +913,13 @@ parse_app_options(int argc, char **argv, struct netbe_cfg *cfg, "for option: \'%c\'\n", __func__, optarg, opt); ctx_prm->timewait = v; + } else if (opt == OPT_SHORT_TXCNT) { + rc = read_tx_content(optarg, &tx_content); + if (rc < 0) + rte_exit(EXIT_FAILURE, + "%s: failed to read tx contents " + "from \'%s\', error code: %d(%s)\n", + __func__, optarg, rc, strerror(-rc)); } else { rte_exit(EXIT_FAILURE, "%s: unknown option: \'%c\'\n", -- cgit 1.2.3-korg