From: Jerin Jacob <jerinjacobk@gmail.com>
To: Felix Moessbauer <felix.moessbauer@siemens.com>
Cc: dev@dpdk.org, henning.schild@siemens.com, jan.kiszka@siemens.com,
thomas@monjalon.net
Subject: Re: [PATCH v6 2/2] Add l2reflect measurement application
Date: Wed, 21 Sep 2022 20:12:21 +0530 [thread overview]
Message-ID: <CALBAE1PR4YHo27AmoDn1J+PE-mgFD8X1e6yPfdG0WoiQLc2H5g@mail.gmail.com> (raw)
In-Reply-To: <20220902084533.675698-3-felix.moessbauer@siemens.com>
On Fri, Sep 2, 2022 at 2:16 PM Felix Moessbauer
<felix.moessbauer@siemens.com> wrote:
>
> The l2reflect application implements a ping-pong benchmark to
> measure the latency between two instances. For communication,
> we use raw ethernet and send one packet at a time. The timing data
> is collected locally and min/max/avg values are displayed in a TUI.
> Finally, a histogram of the latencies is printed which can be
One highlevel comment,
IMO, We don't need to add code for capturing in histogram and analyze
it in C code.
We can simply use, rte_trace and so that we can visualize with
standard trace viewers.
Also add add python based script parse the CTF emitted by trace and find
min/max/avg values to simply the code.
> further processed with the jitterdebugger visualization scripts.
> To debug latency spikes, a max threshold can be defined.
> If it is hit, a trace point is created on both instances.
>
> Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
> Signed-off-by: Henning Schild <henning.schild@siemens.com>
> ---
> app/l2reflect/colors.c | 34 ++
> app/l2reflect/colors.h | 19 +
> app/l2reflect/l2reflect.h | 53 ++
> app/l2reflect/main.c | 1007 +++++++++++++++++++++++++++++++++++++
> app/l2reflect/meson.build | 21 +
> app/l2reflect/payload.h | 26 +
> app/l2reflect/stats.c | 225 +++++++++
> app/l2reflect/stats.h | 67 +++
> app/l2reflect/utils.c | 67 +++
> app/l2reflect/utils.h | 20 +
> app/meson.build | 1 +
Need to add a doc for this example at doc/guides/sample_app_ug/
>
> diff --git a/app/l2reflect/colors.c b/app/l2reflect/colors.c
> new file mode 100644
> index 0000000000..af881d8788
> --- /dev/null
> +++ b/app/l2reflect/colors.c
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2020 Siemens AG
2022. Please fix in all files.
> diff --git a/app/l2reflect/l2reflect.h b/app/l2reflect/l2reflect.h
> new file mode 100644
> index 0000000000..922bd7c281
> --- /dev/null
> +++ b/app/l2reflect/l2reflect.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2020 Siemens AG
> + */
> +
> +#include <stdatomic.h>
> +
> +#ifndef _L2REFLECT_L2REFLECT_H_
> +#define _L2REFLECT_L2REFLECT_H_
> +
> +#define RTE_LOGTYPE_L2REFLECT RTE_LOGTYPE_USER1
Don't define RTE_ symbols in application.
> +
> +/* max size that common 1G NICs support */
> +#define MAX_JUMBO_PKT_LEN 9600
> +
> +/* Used to compare MAC addresses. */
> +#define MAC_ADDR_CMP 0xFFFFFFFFFFFFull
> +
> +#define MAX(x, y) (((x) > (y)) ? (x) : (y))
> +#define MIN(x, y) (((x) < (y)) ? (x) : (y))
Use RTE_MAX and friends. Similar comments for other macros.
> +extern int l2reflect_hist;
> +extern unsigned int l2reflect_hist_buckets;
> +extern atomic_int l2reflect_output_hist;
> +extern int l2reflect_interrupt;
> +extern uint64_t l2reflect_sleep_msec;
> +extern uint64_t l2reflect_pkt_bytes;
> +extern uint16_t l2reflect_port_number;
> +extern atomic_int l2reflect_state;
> +extern struct rte_ether_addr l2reflect_port_eth_addr;
> +extern struct rte_ether_addr l2reflect_remote_eth_addr;
It is better to move all global variables to app_ctx kind of structure and
allocate from hugepage as some of them are used in fastpath and easy to track.
> +/* Configurable number of RX/TX ring descriptors */
> +#define RTE_TEST_RX_DESC_DEFAULT 128
> +#define RTE_TEST_TX_DESC_DEFAULT 128
Don't define RTE_ symbols in application.
> +/* Send a burst of one packet */
> +static inline int
> +l2reflect_send_packet(struct rte_mbuf **m, uint16_t port)
> +{
> + unsigned int ret;
> + struct rte_ether_hdr *eth;
> + struct my_magic_packet *pkt;
> + uint16_t type;
> +
> + eth = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *);
> + pkt = (struct my_magic_packet *)eth;
> + type = pkt->type;
> +
> + if (likely(type == TRACE_TYPE_DATA))
> + clock_gettime(CLOCK_MONOTONIC, &last_sent);
Use rte_rdtsc_precise() instead of system call in fastpath
> + ret = rte_eth_tx_burst(port, l2reflect_q, m, 1);
> + if (unlikely(ret < 1))
> + rte_pktmbuf_free(*m);
> + return 0;
> +}
> +
> +static inline void
> +l2reflect_simple_forward(struct rte_mbuf *m)
> +{
> + struct rte_ether_hdr *eth;
> + struct my_magic_packet *pkt;
> +
> + eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
> + pkt = (struct my_magic_packet *)eth;
> +
> + /* dst addr */
> + rte_ether_addr_copy(ð->src_addr, ð->dst_addr);
> + /* src addr */
> + rte_ether_addr_copy(&l2reflect_port_eth_addr, ð->src_addr);
> +
> + if (unlikely(pkt->magic == MAGIC_TRACE_PAYLOAD))
> + rte_eal_trace_generic_str("sending traced packet");
Create app_trace tracepoint specific to application with new type to
avoid emit the string.
> +
> + l2reflect_send_packet(&m, l2reflect_port_number);
> +}
> +
> +/*
> + * process a single packet.
> + * return false if latency threshold is hit
> + */
> +static inline int
> +process_packet(
> + struct my_magic_packet *pkt,
> + struct timespec *rx_time,
> + uint64_t *diff)
> +{
> + if (pkt->type == TRACE_TYPE_DATA) {
> + rte_memcpy(&last_recv, rx_time, sizeof(*rx_time));
> + *diff = calcdiff_ns(last_recv, last_sent);
> + if (!unlikely(add_to_record(*diff))) {
> + /* TODO: improve tracing */
> + rte_eal_trace_generic_u64(record.max_round_ns / 1000);
Add a new trace point as an application specific item.
> + return 0;
> + }
> + }
> + if (pkt->magic == MAGIC_TRACE_PAYLOAD)
> + rte_eal_trace_generic_str("received traced packet");
Add a new trace point as an application specific item.
> +
> + return 1;
> +}
> +
> +/*
> + * free all packet buffers in the range [begin, end[.
> + */
> +static void
> +free_pktbufs(
> + struct rte_mbuf **bufs,
> + int begin,
> + int end)
> +{
> + int i = begin;
> + for (; i < end; i++)
> + rte_pktmbuf_free(bufs[0]);
Freeing the same packet multiple times?
Use burst varint if possible.
> +}
> +
> +/*
> + * return 1 in case the ball was lost (cheap check)
> + */
> +static inline void
> +check_ball_lost(const uint64_t dp_idle) {
> + /* only check if we are in running state and have a breakval */
> + if (unlikely(dp_idle & RX_TIMEOUT_MASK) &&
> + l2reflect_state == S_RUNNING &&
> + l2reflect_break_usec &&
> + record.rounds > WARMUP_ROUNDS) {
> + RTE_LOG(INFO, L2REFLECT, "lost ball after %" PRIu64 " rounds\n", record.rounds);
> + l2reflect_state = S_LOCAL_TERM;
> + }
> +}
> +}
> +
> + /*
> + * in quiet mode the primary executes the main packet loop
> + * otherwise the one worker does it and the primary prints stats
> + */
> + if (quiet) {
> + assert(rte_lcore_count() == 1);
> +#ifdef HAS_SYS_IO
> + if (disable_int) {
> + iopl(3);
> + asm("cli");
Do we need x86 specific items in application?
> + }
> +#endif
> + RTE_LOG(INFO, L2REFLECT, "PID %i, Parent %i\n", getpid(), getppid());
> + l2reflect_launch_one_lcore(NULL);
> + } else {
> + assert(rte_lcore_count() == 2);
> + /* the worker reflects the packets */
> + RTE_LCORE_FOREACH_WORKER(lcore_id)
> + {
> + rte_eal_remote_launch(l2reflect_launch_one_lcore, NULL,
> + lcore_id);
> + }
> +
> + /* the primary prints the stats */
> + init_record();
> + l2reflect_stats_loop();
> + rte_eal_mp_wait_lcore();
> + }
> + rte_eal_cleanup();
> +
> + if (l2reflect_hist)
> + output_histogram_snapshot();
> +
> + cleanup_record();
> +
> + return 0;
> +}
> diff --git a/app/l2reflect/meson.build b/app/l2reflect/meson.build
> new file mode 100644
> index 0000000000..14b154ef06
> --- /dev/null
> +++ b/app/l2reflect/meson.build
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2022 Siemens AG
> +
> +cc = meson.get_compiler('c')
> +
> +jansson = dependency('libjansson', required: false)
> +
> +if not jansson.found()
> + jansson = cc.find_library('jansson', required: false)
> +endif
> +
> +if cc.has_header('sys/io.h')
> + cflags += '-DHAS_SYS_IO'
> +endif
> +
> +sources = files('main.c', 'utils.c', 'stats.c', 'colors.c')
> +deps += ['ethdev']
> +if jansson.found()
> + ext_deps += jansson
> + cflags += '-DRTE_HAS_JANSSON'
> +endif
> diff --git a/app/l2reflect/payload.h b/app/l2reflect/payload.h
> new file mode 100644
> index 0000000000..c1fae5d5e4
> --- /dev/null
> +++ b/app/l2reflect/payload.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2022 Siemens AG
> + */
> +#include <rte_ether.h>
> +
> +#ifndef _L2REFLECT_PAYLOAD_H_
> +#define _L2REFLECT_PAYLOAD_H_
> +
> +#define MAGIC_TRACE_PAYLOAD 0xd00faffeaffed00full
> +/* IEEE Std 802 - Local Experimental Ethertype */
> +#define ETHER_TYPE_L2REFLECT 0x88B5
> +
> +struct my_magic_packet {
> + /* l2 packet header */
> + struct rte_ether_hdr eth;
> + /* type of the l2reflect packet */
> + uint8_t type;
> + /* magic easy-to-spot pattern for tracing */
> + uint64_t magic;
> + /* break if latency is larger than this */
> + uint64_t breakval;
> + /* intended size of the packet */
> + uint64_t req_pkt_bytes;
> +};
> +
> +#endif /* _L2REFLECT_PAYLOAD_H_ */
next prev parent reply other threads:[~2022-09-21 14:42 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-02 8:45 [PATCH v6 0/2] " Felix Moessbauer
2022-09-02 8:45 ` [PATCH v6 1/2] Fix build of apps with external dependencies Felix Moessbauer
2022-09-20 12:33 ` Maxime Coquelin
2022-09-02 8:45 ` [PATCH v6 2/2] Add l2reflect measurement application Felix Moessbauer
2022-09-20 14:01 ` Maxime Coquelin
2022-09-25 8:01 ` Moessbauer, Felix
2022-10-20 12:45 ` Maxime Coquelin
2022-09-21 14:42 ` Jerin Jacob [this message]
2022-09-21 15:07 ` Thomas Monjalon
2022-09-21 15:13 ` Henning Schild
2022-09-22 5:55 ` Jerin Jacob
2022-09-21 9:43 ` [PATCH v6 0/2] " Morten Brørup
2022-09-21 11:27 ` Henning Schild
2022-09-21 12:22 ` Morten Brørup
2022-09-21 12:59 ` Henning Schild
2022-09-21 13:48 ` Morten Brørup
2023-09-12 14:30 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CALBAE1PR4YHo27AmoDn1J+PE-mgFD8X1e6yPfdG0WoiQLc2H5g@mail.gmail.com \
--to=jerinjacobk@gmail.com \
--cc=dev@dpdk.org \
--cc=felix.moessbauer@siemens.com \
--cc=henning.schild@siemens.com \
--cc=jan.kiszka@siemens.com \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).