Skip to content

Conversation

@ovsrobot
Copy link
Owner

@ovsrobot ovsrobot commented Nov 26, 2025

NOTE: This is an auto submission for "[RFC] pcapng: improve performance of timestamping".

See "http://patchwork.dpdk.org/project/dpdk/list/?series=36795" for details.

Summary by Sourcery

Improve pcapng timestamp conversion and adjust related driver capabilities while extending and tightening various sample app configurations and documentation build/install behavior.

New Features:

  • Add configurable RX and TX burst sizes and optional forced link speed to l3fwd and l3fwd-power examples.
  • Introduce a structured time conversion helper for pcapng timestamping to reduce overhead and improve precision.

Bug Fixes:

  • Prevent overly long names in ip_reassembly mbuf pool and server_node_efd queues and MAC cache, and vdpa iface options by bounding buffer sizes and validating indices.
  • Ensure hns3, ngbe, txgbe, ntnic, and softnic drivers consistently set tx_pkt_prepare to the dummy handler instead of NULL when disabling TX datapaths or using simple paths.
  • Fix mlx5 flex parser handling for header length offset based on firmware capabilities and update PRM structures accordingly.

Enhancements:

  • Simplify mlx5 shared device flow configuration by removing HWS/SWS steering mode negotiation and always enabling duplicate pattern support where DV is enabled.
  • Optimize pcapng timestamp calculation by replacing per-call division with precomputed scaling factors and masked TSC deltas to avoid wraparound.
  • Refine l3fwd send and receive paths to use separate RX/TX burst size controls instead of a single shared parameter.
  • Tighten example code argument parsing and logging, including clearer usage strings and validation of unsupported fixed link speeds.
  • Tag generated HTML/man API docs and guides with an install tag to integrate better with packaging and installation tools.
  • Drop no-longer-needed example build compiler flag suppression for format truncation warnings.

Documentation:

  • Update documentation build rules to tag installed HTML/man pages and guides as documentation artifacts.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added command-line options for l3fwd example: --rx-burst, --tx-burst, and --eth-link-speed for configurable burst sizes and link speed configuration.
    • Enhanced documentation for Ionic driver with new Pollara 400 AI NIC model.
  • Documentation

    • Updated platform support matrices for i40e and ice drivers.
    • Expanded mlx5 driver documentation with raw pattern flow guidance, traffic management options, and configuration clarifications.
    • Added tested platforms subsection to release notes with Intel and NVIDIA configurations.
    • Updated Windows build prerequisites and Visual Studio guidance.
    • Enhanced l3fwd-power example documentation with new eth-link-speed option.
  • Chores

    • Version bumped to 25.11.0-rc4.
    • Updated copyright years and added installation tags for documentation artifacts in build system.

✏️ Tip: You can customize this high-level summary in your review settings.

MaayanKashani1 and others added 24 commits November 24, 2025 09:24
Enhance the documentation by adding information about limitations
specific to the synchronous API when used with hardware steering.
This update provides users with a more comprehensive understanding
of the constraints in this configuration.

Signed-off-by: Maayan Kashani <mkashani@nvidia.com>
Signed-off-by: Bing Zhao <bingz@nvidia.com>
Add tested, and hence recommended, firmware and other versions for i40e
and ice drivers. In the process remove version inform for obsolete DPDK
releases.

Signed-off-by: Hailin Xu <hailinx.xu@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
There is the updated firmware providing the new capability
bit "header_length_field_offset_mode". If this bit is set
the length field offset in flex parser configuration should
not be adjusted by the supported field mask left margin,
and the bit "header_length_field_offset_mode" should be set
in configuration command on the flex parser creation
firmware call.

Fixes: b04b06f ("net/mlx5: fix flex item header length field translation")
Cc: stable@dpdk.org

Signed-off-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
The update of flow engine devargs introduced a regression
with untrusted VFs/SFs.
Using HWS engine caused a degradation in probing 1K SFs,
because memzone segments exceeds maximum 2560.

Fixes: 53fdc23 ("common/mlx5: read SW steering capability bits")
Fixes: d1ac7b6 ("net/mlx5: update flow devargs handling for future HW")

Signed-off-by: Raslan Darawsheh <rasland@nvidia.com>
Count flow action is supported on root table with HW Steering
flow engine with upstream drivers/libraries and
drivers/libraries packaged with recently released DOCA.
This patch updates relevant docs with minimum DOCA version.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Bing Zhao <bingz@nvidia.com>
Previously, the Tx burst size in l3fwd was fixed at 256, which could
lead to suboptimal performance in certain scenarios.

This patch introduces separate --rx-burst and --tx-burst options to
explicitly configure Rx and Tx burst sizes. By default, the Tx burst
size now matches the Rx burst size for better efficiency and pipeline
balance.

Fixes: d5c4897 ("examples/l3fwd: add option to set Rx burst size")

Signed-off-by: Sivaprasad Tummala <sivaprasad.tummala@amd.com>
Tested-by: Venkat Kumar Ande <venkatkumar.ande@amd.com>
Tested-by: Dengdui Huang <huangdengdui@huawei.com>
Tested-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
Acked-by: Chengwen Feng <fengchengwen@huawei.com>
Currently, l3fwd starts in auto-negotiation mode, but it may fail to
link up when auto-negotiation is not supported. Therefore, it is
necessary to support starting with a specified speed for port.

Additionally, this patch does not support changing the duplex mode.
So speeds like 10M, 100M are not configurable using this method.

Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
Currently, l3fwd-power starts in auto-negotiation mode, but it may fail
to link up when auto-negotiation is not supported. Therefore, it is
necessary to support starting with a specified speed for port.

Additionally, this patch does not support changing the duplex mode.
 So speeds like 10M, 100M are not configurable using this method.

Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>
If format-truncation is enabled, the compiler detects a string overflow
since the snprintf() is putting ethernet address and new line
in buffer only sized for the address.

Since get_rx_queue_name() is used to create a ring name.
The buffer should be sized to be a valid ring name.
This fixes some format-overflow warnings and also corrects
for future errors.

In file included from ../examples/server_node_efd/efd_server/main.c:31:
In function ‘get_printable_mac_addr’,
    inlined from ‘do_stats_display’ at ../examples/server_node_efd/efd_server/main.c:136:3:
../lib/net/rte_ether.h:248:36: warning: ‘snprintf’ output truncated before the last format character [-Wformat-truncation=]
  248 | #define RTE_ETHER_ADDR_PRT_FMT     "%02X:%02X:%02X:%02X:%02X:%02X"
      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../examples/server_node_efd/efd_server/main.c:86:33: note: in expansion of macro ‘RTE_ETHER_ADDR_PRT_FMT’
   86 |                                 RTE_ETHER_ADDR_PRT_FMT "\n",
      |                                 ^~~~~~~~~~~~~~~~~~~~~~
../examples/server_node_efd/efd_server/main.c: In function ‘do_stats_display’:
../examples/server_node_efd/efd_server/main.c:86:59: note: format string is defined here
   86 |                                 RTE_ETHER_ADDR_PRT_FMT "\n",
      |

Fixes: 39aad0e ("examples/flow_distributor: new example to demonstrate EFD")
Cc: stable@dpdk.org

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
The ifname is limited to 128 characters, but it would allow up
to 128 characters as prefix then could overflow creating ifname.

Change to limit path prefix (iface) to 123 (128 - sizeof("1024"))
to avoid possible format overflow

../examples/vdpa/main.c:501:76: warning: ‘snprintf’ output may be truncated before the last format character [-Wformat-truncation=]
  501 |                         snprintf(vports[devcnt].ifname, MAX_PATH_LEN, "%s%d",
      |                                                                            ^
../examples/vdpa/main.c:501:25: note: ‘snprintf’ output between 2 and 139 bytes into a destination of size 128
  501 |                         snprintf(vports[devcnt].ifname, MAX_PATH_LEN, "%s%d",
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  502 |                                         iface, devcnt);
      |

Fixes: 38f8ab0 ("vhost: make vDPA framework bus agnostic")
Cc: stable@dpdk.org

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
In theory, lcore and queue could be so large that mbuf pool name
could overflow. But that can never happen since lcore and queue
will be in range. Add a check so that static tools know that.
Format overflow warnings seen on older versions of Gcc only.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
There were several hidden bugs in examples because format
truncation warning was disabled.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
After removing callback checks from ethdev fast path,
some drivers crashed because tx_pkt_prepare was set to NULL.

Some drivers (hns3, ngbe, txgbe) need to use rte_eth_tx_pkt_prepare_dummy
when configuring queues.
Other drivers (ntnic, softnic) does not need to set tx_pkt_prepare
as it was set by eth_dev_set_dummy_fops() called by rte_eth_dev_allocate().

Bugzilla ID: 1834
Fixes: 066f3d9 ("ethdev: remove callback checks from fast path")

Reported-by: Jiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Reviewed-by: Morten Brørup <mb@smartsharesystems.com>
Tested-by: Jiawen Wu <jiawenwu@trustnetic.com>
The Pollara 400 AI NIC is supported without any PMD changes.
Add a link to the product brief.

Cc: stable@dpdk.org

Signed-off-by: Andrew Boyer <andrew.boyer@amd.com>
changes:

 1. fix spelling from `SIENNA` to `SIENA`
 2. add tuning guide for zen5 AMD Epyc 9005
 3. add uncore power details
 4. update on using AMD Solarflare X4 and X2

Signed-off-by: Vipin Varghese <vipin.varghese@amd.com>
Tested-by: Thiyagarajan P <thiyagarajan.p@amd.com>
Updated some external links and removed a note which does not
apply to MSVC builds anymore.

Also reworded a sentence clarifying how to open a Visual Studio
Developer Command Prompt from CMD and Powershell, as the
original text could induce people to run VsDevCmd.bat from
a Powershell prompt, which does not work.

Signed-off-by: Andre Muezerie <andremue@linux.microsoft.com>
The note about the prefix of the package pyelftools was not showed
in the documentation output because the syntax was missing a colon,
so it was considered as a simple comment in the source file.

Fixes: 9e6f75e ("doc: update build section of FreeBSD guide")
Cc: stable@dpdk.org

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
The version python used in current FreeBSD stable release 14.3
is now 3.11. Update documentation accordingly.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
KNI was removed from DPDK but the diagrams in the documentation
were left behind.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Chengwen Feng <fengchengwen@huawei.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
This allows building and installing only the documentation, without
recompiling the whole project, using:

meson build -Denable_docs=true
meson compile -C build doc
meson install -C build --no-rebuild --tags doc

In Debian/Ubuntu the documentation is built separately from the binaries,
in a separate architecture-independent build job, so that it has to be
done only once, instead of once per supported architecture.

Signed-off-by: Luca Boccassi <bluca@debian.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
Add tested platforms with NVIDIA NICs to the 25.11 release notes.

Signed-off-by: Raslan Darawsheh <rasland@nvidia.com>
Add tested Intel platforms with Intel NICs to v25.11 release note.

Signed-off-by: Yu Jiang <yux.jiang@intel.com>
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Avoid doing expensive divide operations when converting
timestamps from cycles (TSC) to pcapng scaled value (ns).
This logic was derived from the math used by Linux kernel
virtual system call with help from AI.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: 0-day Robot <robot@bytheb.org>
@sourcery-ai
Copy link

sourcery-ai bot commented Nov 26, 2025

Reviewer's Guide

Refactors l3fwd burst handling into separate RX/TX burst sizes and exposes them via new CLI options, introduces an efficient TSC→ns conversion scheme in pcapng, and adjusts mlx5 and several PMDs/utilities for new capabilities and safer defaults while tightening a few example limits and doc build/install behavior.

Sequence diagram for pcapng timestamp initialization and usage

sequenceDiagram
    participant App
    participant rte_pcapng as rte_pcapng_instance
    participant TimeConv as pcapng_time_conv

    App->>rte_pcapng: rte_pcapng_fdopen(fd, port_list)
    activate rte_pcapng
    rte_pcapng->>TimeConv: pcapng_timestamp_init(tc)
    activate TimeConv
    TimeConv->>TimeConv: rte_get_tsc_cycles()
    TimeConv->>TimeConv: clock_gettime(CLOCK_REALTIME, &ts)
    TimeConv->>TimeConv: rte_get_tsc_cycles()
    TimeConv-->>rte_pcapng: tc initialized (tsc_base, ns_base, mult, shift, mask)
    deactivate TimeConv
    rte_pcapng-->>App: rte_pcapng_t *self
    deactivate rte_pcapng

    loop For each stats sample
        App->>rte_pcapng: rte_pcapng_write_stats(self, port_id, stats)
        activate rte_pcapng
        rte_pcapng->>TimeConv: pcapng_timestamp(tc, rte_get_tsc_cycles())
        activate TimeConv
        TimeConv->>TimeConv: delta = (cycles - tsc_base) & mask
        TimeConv->>TimeConv: ns_delta = (delta * mult) >> shift
        TimeConv-->>rte_pcapng: ns = ns_base + ns_delta
        deactivate TimeConv
        rte_pcapng-->>App: stats block written with ns timestamp
        deactivate rte_pcapng
    end

    loop For each captured packet
        App->>rte_pcapng: rte_pcapng_write_packets(self, port_id, pkts, num)
        activate rte_pcapng
        rte_pcapng->>TimeConv: pcapng_timestamp(tc, packet_cycles)
        activate TimeConv
        TimeConv->>TimeConv: delta, ns_delta computed
        TimeConv-->>rte_pcapng: ns timestamp
        deactivate TimeConv
        rte_pcapng-->>App: packet block written with ns timestamp
        deactivate rte_pcapng
    end
Loading

Class diagram for updated pcapng timestamping structures

classDiagram
    class rte_pcapng {
        int outfd
        unsigned int ports
        uint32_t port_index[RTE_MAX_ETHPORTS]
        pcapng_time_conv tc
        int (*close)(rte_pcapng_t *self)
        int (*interface_add)(rte_pcapng_t *self, uint16_t port_id, const char *ifname)
        int (*write_packets)(rte_pcapng_t *self, uint16_t port_id, struct rte_mbuf **pkts, uint32_t num)
        int (*write_stats)(rte_pcapng_t *self, uint16_t port_id, const struct rte_eth_stats *stats)
    }

    class pcapng_time_conv {
        uint64_t tsc_base
        uint64_t ns_base
        uint64_t mult
        uint32_t shift
        uint64_t mask
    }

    class pcapng_timestamp_init {
        +pcapng_timestamp_init(pcapng_time_conv *tc)
    }

    class pcapng_timestamp_fn {
        +pcapng_timestamp(pcapng_time_conv *tc, uint64_t cycles) uint64_t
    }

    rte_pcapng --> pcapng_time_conv : has
    pcapng_timestamp_init ..> pcapng_time_conv : initializes
    pcapng_timestamp_fn ..> pcapng_time_conv : reads
Loading

Class diagram for l3fwd burst size configuration and usage

classDiagram
    class l3fwd_globals {
        uint16_t nb_rxd
        uint16_t nb_txd
        uint32_t rx_burst_size
        uint32_t tx_burst_size
        uint32_t mb_mempool_cache_size
    }

    class l3fwd_cli {
        +print_usage(const char *prgname)
        +parse_pkt_burst(const char *optarg, bool is_rx_burst, uint32_t *burst_sz)
        +parse_args(int argc, char **argv) int
    }

    class lcore_conf {
        uint16_t tx_queue_id[RTE_MAX_ETHPORTS]
        struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]
        struct rte_mbuf *tx_mbufs[RTE_MAX_ETHPORTS][MAX_PKT_BURST]
        uint16_t tx_mbufs_len[RTE_MAX_ETHPORTS]
    }

    class send_burst_fn {
        +send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port)
    }

    class send_single_packet_fn {
        +send_single_packet(struct lcore_conf *qconf, struct rte_mbuf *m, uint16_t port)
    }

    class send_packetsx4_fn {
        +send_packetsx4(struct lcore_conf *qconf, uint16_t port, struct rte_mbuf *m[], uint16_t num)
    }

    class acl_main_loop_fn {
        +acl_main_loop(void *dummy)
    }

    class em_main_loop_fn {
        +em_main_loop(void *dummy)
    }

    class fib_main_loop_fn {
        +fib_main_loop(void *dummy)
    }

    class lpm_main_loop_fn {
        +lpm_main_loop(void *dummy)
    }

    l3fwd_cli --> l3fwd_globals : configures rx_burst_size, tx_burst_size
    send_burst_fn --> lcore_conf : uses
    send_single_packet_fn --> lcore_conf : uses
    send_single_packet_fn --> send_burst_fn : calls when len == rx_burst_size
    send_packetsx4_fn --> l3fwd_globals : checks tx_burst_size
    acl_main_loop_fn --> l3fwd_globals : uses rx_burst_size for rte_eth_rx_burst
    em_main_loop_fn --> l3fwd_globals : uses rx_burst_size for rte_eth_rx_burst
    fib_main_loop_fn --> l3fwd_globals : uses rx_burst_size for rte_eth_rx_burst
    lpm_main_loop_fn --> l3fwd_globals : uses rx_burst_size for rte_eth_rx_burst
Loading

Class diagram for updated mlx5 flex parser and HCA capability structures

classDiagram
    class mlx5_hca_flex_attr {
        uint32_t flex_parser_protocols
        uint8_t sample_tunnel_inner
        uint8_t sample_tunnel_outer
        uint8_t zero_size_supported
        uint8_t sample_id_in_out
        uint8_t header_length_field_mode_wa
        uint16_t max_base_header_length
        uint8_t max_sample_base_offset
        uint16_t max_next_header_offset
        uint8_t header_length_mask_width
    }

    class mlx5_devx_graph_node_attr {
        uint32_t header_length_base_value
        uint32_t header_length_field_shift
        uint32_t header_length_field_offset
        uint32_t header_length_field_offset_mode
        uint32_t header_length_field_mask
        uint32_t next_header_field_offset
    }

    class mlx5_ifc_parse_graph_node_cap_bits {
        u8 max_base_header_length[0x10]
        u8 max_next_header_offset[0x10]
        u8 header_length_mask_width[0x08]
        u8 reserved_at_78[0x01]
        u8 header_length_field_offset_mode[0x1]
        u8 reserved_at_79[0x01]
        u8 parse_graph_anchor[0x1]
    }

    class mlx5_ifc_parse_graph_flex_bits {
        u8 header_length_mode[0x2]
        u8 header_length_base_value[0x10]
        u8 header_length_field_shift[0x4]
        u8 header_length_field_offset[0x10]
        u8 reserved_at_178[0x1]
        u8 header_length_field_offset_mode[0x1]
        u8 reserved_at_17a[0x1]
        u8 next_header_field_size[0x5]
        u8 header_length_field_mask[0x20]
    }

    class mlx5_flow_flex_logic {
        +mlx5_flex_translate_length(mlx5_hca_flex_attr *attr, mlx5_devx_graph_node_attr *node, const struct field_spec *field, struct rte_flow_error *error) int
    }

    class mlx5_devx_cmd_create_flex_parser_fn {
        +mlx5_devx_cmd_create_flex_parser(void *ctx, struct mlx5_devx_graph_node_attr *data) int
    }

    class mlx5_devx_cmd_query_hca_parse_graph_node_cap_fn {
        +mlx5_devx_cmd_query_hca_parse_graph_node_cap(void *ctx, struct mlx5_hca_flex_attr *attr) int
    }

    mlx5_flow_flex_logic --> mlx5_hca_flex_attr : reads header_length_field_mode_wa
    mlx5_flow_flex_logic --> mlx5_devx_graph_node_attr : sets header_length_field_offset, header_length_field_offset_mode
    mlx5_devx_cmd_query_hca_parse_graph_node_cap_fn --> mlx5_ifc_parse_graph_node_cap_bits : parses header_length_field_offset_mode
    mlx5_devx_cmd_query_hca_parse_graph_node_cap_fn --> mlx5_hca_flex_attr : sets header_length_field_mode_wa
    mlx5_devx_cmd_create_flex_parser_fn --> mlx5_devx_graph_node_attr : reads header_length_field_offset_mode
    mlx5_devx_cmd_create_flex_parser_fn --> mlx5_ifc_parse_graph_flex_bits : writes header_length_field_offset_mode
Loading

File-Level Changes

Change Details Files
Split l3fwd burst handling into distinct RX/TX sizes and add link-speed and burst CLI controls across l3fwd examples.
  • Replace global nb_pkt_per_burst with rx_burst_size and introduce tx_burst_size, adjusting send and receive paths to use these variables
  • Rename --burst CLI option to --rx-burst and add --tx-burst, wiring them to a generalized parse_pkt_burst() that treats 0 specially per-direction
  • Add --eth-link-speed option to l3fwd and l3fwd-power, validating requested speeds and mapping to port_conf.link_speeds
  • Update l3fwd usage strings, defaults, and main() logging to reflect new burst options and variables
examples/l3fwd/main.c
examples/l3fwd/l3fwd.h
examples/l3fwd/l3fwd_common.h
examples/l3fwd/l3fwd_acl.c
examples/l3fwd/l3fwd_em.c
examples/l3fwd/l3fwd_fib.c
examples/l3fwd/l3fwd_lpm.c
examples/l3fwd-power/main.c
Rework pcapng timestamping to use a precomputed TSC→ns conversion with fixed-point arithmetic for better performance and wraparound safety.
  • Embed a pcapng_time_conv struct in rte_pcapng to hold TSC base, ns base, multiplier, shift, and mask
  • Add pcapng_timestamp_init() to capture a consistent base TSC/time pair and precompute conversion parameters from rte_get_tsc_hz()
  • Rewrite pcapng_timestamp() to use masked TSC deltas and fixed-point multiply/shift instead of division, returning ns_base + ns_delta
  • Update statistics and packet-writing paths to call the new conversion routine and initialization
lib/pcapng/rte_pcapng.c
Teach mlx5 flex-parse graph code about a new header-length offset mode and simplify flow steering configuration, removing unused SW owner/HWS logic.
  • Extend HCA flex and parse-graph capability structures and DevX command helpers with header_length_field_offset_mode and header_length_field_mode_wa support
  • Adjust mlx5_alloc_srh_flex_parser() and mlx5_flex_translate_length() to choose header-length offsets and workarounds based on firmware capability
  • Simplify mlx5_shared_dev_ctx_args_config() to always use dv_flow_en=1 and allow_duplicate_pattern=1 by default, dropping HWS/SWS steering checks and KV-arg based mode switching
  • Remove SW owner-related capabilities from mlx5_devx_cmd_query_hca_attr() and associated bitfields from mlx5_prm.h
drivers/net/mlx5/mlx5.c
drivers/common/mlx5/mlx5_devx_cmds.c
drivers/common/mlx5/mlx5_devx_cmds.h
drivers/common/mlx5/mlx5_prm.h
drivers/net/mlx5/mlx5_flow_flex.c
Tighten various example and helper limits and naming to avoid buffer overflows or oversize identifiers.
  • Reduce iface buffer size in vdpa example and base it on MAX_VDPA_SAMPLE_PORTS string length, using sizeof(iface) in rte_strscpy
  • Validate lcore and queue indices in ip_reassembly pool setup before snprintf-based pool name generation
  • Use RTE_RING_NAMESIZE for server_node_efd RX queue name buffer and RTE_ETHER_ADDR_FMT_SIZE+1 for cached MAC string buffers
examples/vdpa/main.c
examples/ip_reassembly/main.c
examples/server_node_efd/shared/common.h
examples/server_node_efd/efd_server/main.c
Normalize tx_pkt_prepare behavior in several PMDs to use the dummy prepare function instead of NULL and clean up a few build/install details.
  • Set tx_pkt_prepare to rte_eth_tx_pkt_prepare_dummy instead of NULL in hns3, ngbe, txgbe, nthw, and softnic stop/init paths for more predictable behavior
  • Remove -Wno-format-truncation from examples default CFLAGS and add install_tag 'doc' to Doxygen and guides Meson targets so documentation can be selectively installed
drivers/net/hns3/hns3_rxtx.c
drivers/net/ngbe/ngbe_rxtx.c
drivers/net/txgbe/txgbe_rxtx.c
drivers/net/ntnic/ntnic_ethdev.c
drivers/net/softnic/rte_eth_softnic.c
examples/meson.build
doc/api/meson.build
doc/guides/meson.build

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link

coderabbitai bot commented Nov 26, 2025

Walkthrough

Version bump to 25.11.0-rc4 combined with documentation updates for new hardware support, build system metadata tagging, infrastructure changes to MLX5 driver including struct field modifications, multiple network driver updates to packet preparation, example application refactoring for burst size handling, and library-level time-tracking refactoring in pcapng.

Changes

Cohort / File(s) Summary
Version Management
VERSION
Bumped version from 25.11.0-rc3 to 25.11.0-rc4
Build System Installation Tagging
doc/api/meson.build, doc/guides/meson.build
Added install_tag: 'doc' metadata to custom_target definitions for example, doxy_html_build, doxy_man_build, and html_guides targets
Documentation: Copyright & Hardware Updates
doc/guides/cryptodevs/ionic.rst, doc/guides/nics/ionic.rst
Updated copyright year to 2025 and added Pollara 400 single-port 400G AI NIC model entries
Documentation: Build Prerequisites
doc/guides/freebsd_gsg/build_dpdk.rst
Replaced Python package from py38-pyelftools to py311-pyelftools; updated references and installation command
Documentation: Platform & Performance Tuning
doc/guides/linux_gsg/amd_platform.rst
Fixed SIENNA typo, added TURIN platform support, expanded power management sections, added NIC section for TURIN with Solarflare PMD specifics
Documentation: Firmware Compatibility
doc/guides/nics/i40e.rst, doc/guides/nics/ice.rst
Added DPDK 25.11 entries with updated kernel driver/firmware versions; removed legacy version entries (16.04–21.08); expanded ice.rst with raw pattern flow documentation and traffic management options
Documentation: MLX5 Flow Configuration
doc/guides/nics/mlx5.rst
Simplified DV flow default documentation, added mandatory asynchronous flow API configuration notes, expanded synchronous flow API limitations and restrictions
Documentation: Release Notes & Sample Apps
doc/guides/rel_notes/release_25_11.rst, doc/guides/sample_app_ug/l3_forward.rst
Added tested platforms subsection; documented --rx-burst and --tx-burst command-line options for l3_forward
Documentation: Windows Build Guidance
doc/guides/windows_gsg/build_dpdk.rst
Removed Visual Studio 2022 limitation note, updated LLVM URLs and download links to HTTPS, reworked Developer Command Prompt guidance with code examples
MLX5 Driver: DevX Commands
drivers/common/mlx5/mlx5_devx_cmds.c
Added header_length_field_offset_mode initialization and computation; removed rx_sw_owner, tx_sw_owner, and esw_sw_owner field usage
MLX5 Driver: DevX Headers
drivers/common/mlx5/mlx5_devx_cmds.h
Added header_length_field_mode_wa:1 to mlx5_hca_flex_attr; removed six sw_owner bitfields from mlx5_hca_attr; added header_length_field_offset_mode:1 to mlx5_devx_graph_node_attr
MLX5 Driver: Protocol Register Macros
drivers/common/mlx5/mlx5_prm.h
Converted steering format enum to macros; added header_length_field_offset_mode fields and adjusted reserved padding in multiple struct definitions
MLX5 Driver: Flex Parser & Flow Config
drivers/net/mlx5/mlx5.c, drivers/net/mlx5/mlx5_flow_flex.c
Conditionally compute header length offset based on header_length_field_mode_wa; removed legacy sws/hws capability checks and dynamic DV flow mode switching; simplified static configuration
Network Drivers: Packet Preparation Updates
drivers/net/hns3/hns3_rxtx.c, drivers/net/txgbe/txgbe_rxtx.c
Changed tx_pkt_prepare from NULL to rte_eth_tx_pkt_prepare_dummy in stopped/simple TX paths
Network Drivers: Packet Preparation Removal
drivers/net/ntnic/ntnic_ethdev.c, drivers/net/softnic/rte_eth_softnic.c
Removed explicit tx_pkt_prepare = NULL assignments
Examples: L3 Forward Burst Refactoring
examples/l3fwd/l3fwd.h, examples/l3fwd/l3fwd_common.h, examples/l3fwd/l3fwd_acl.c, examples/l3fwd/l3fwd_em.c, examples/l3fwd/l3fwd_fib.c, examples/l3fwd/l3fwd_lpm.c, examples/l3fwd/main.c
Split single nb_pkt_per_burst into separate rx_burst_size and tx_burst_size with per-direction command-line options (--rx-burst, --tx-burst); refactored burst argument parsing logic
Examples: L3 Forward Power Link Speed
examples/l3fwd-power/main.c
Added --eth-link-speed command-line option to configure port link speeds with validation
Examples: Build & Buffer Sizing
examples/meson.build, examples/server_node_efd/efd_server/main.c, examples/server_node_efd/shared/common.h, examples/vdpa/main.c
Removed -Wno-format-truncation flag condition; adjusted MAC address and ring name buffer sizes; improved string handling with safer size parameters
Examples: Input Validation
examples/ip_reassembly/main.c
Added bounds checking for lcore and queue indices against RTE limits
Library: Timestamp & Time Tracking
lib/pcapng/rte_pcapng.c
Refactored timestamp conversion from per-instance TSC tracking to dedicated pcapng_time_conv structure; added pcapng_timestamp_init() helper; updated all timestamp computation and call sites to use new time-conversion mechanism

Sequence Diagram(s)

sequenceDiagram
    participant App as L3fwd Application
    participant Parse as parse_pkt_burst()
    participant Main as main()
    
    App->>Main: Start with command-line args
    Main->>Parse: --rx-burst N (is_rx_burst=true)
    Parse->>Parse: Validate and store in rx_burst_size
    Main->>Parse: --tx-burst M (is_rx_burst=false)
    Parse->>Parse: Validate and store in tx_burst_size
    Main->>Main: Log selected RX/TX burst values
    Main->>App: RX loop uses rx_burst_size
    Main->>App: TX loop uses tx_burst_size
    Note over Main: Previously single --burst option<br/>unified rx/tx behavior
Loading
sequenceDiagram
    participant Code as mlx5_alloc_srh_flex_parser()
    participant HCA as hca_attr
    participant Conf as Port Config
    
    Code->>HCA: Read header_length_field_mode_wa flag
    alt header_length_field_mode_wa true (newer FW)
        Code->>Code: offset = 8
        Code->>Code: if mask_width < 8:<br/>offset += 8 - mask_width
    else header_length_field_mode_wa false (legacy FW)
        Code->>Code: offset = 12
    end
    Code->>Conf: Apply computed offset
    Note over Code: Conditional offset calculation<br/>based on firmware generation
Loading
sequenceDiagram
    participant Init as rte_pcapng_fdopen()
    participant TC as pcapng_time_conv
    participant TS as pcapng_timestamp()
    
    Init->>Init: Get current TSC and wall-clock time
    Init->>TC: pcapng_timestamp_init(&self->tc)
    TC->>TC: Compute tsc_base, ns_base, mult, shift, mask
    Note over TC: Time conversion context initialized
    
    TS->>TC: Call with current cycles
    TS->>TS: delta = (cycles - tsc_base) & mask
    TS->>TS: result = ns_base + (delta * mult) >> shift
    TS-->>Init: Return nanosecond timestamp
    Note over TS: Wraparound-safe delta masking<br/>with precise conversion factors
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • MLX5 driver infrastructure changes (drivers/common/mlx5/mlx5_*.{c,h}): Struct field additions/removals and macro conversions require verification that all dependent code is updated; conditional header_length_field_mode_wa logic flows need careful tracing
  • l3fwd burst refactoring (examples/l3fwd/main.c, examples/l3fwd/*.c): Pervasive refactoring of burst size handling across multiple files; verify all call sites use correct variable and that per-direction logic is applied consistently
  • pcapng time-tracking refactoring (lib/pcapng/rte_pcapng.c): Structural reorganization of time-conversion logic; verify all timestamp computation paths and wraparound masking correctness
  • MLX5 flow configuration simplification (drivers/net/mlx5/mlx5.c): Removal of legacy capability checks and dynamic mode switching; confirm implications for older hardware support

Poem

🐰 The version hops to rc4 today,
With burst sizes now split their way—
rx and tx dance their separate tune,
While timestamps tick by lunar moon,
And hardware blooms on platforms new! 🌸

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title references a narrow optimization in pcapng timestamping, but the changeset includes extensive modifications across documentation, drivers, and examples far beyond pcapng performance. Revise the title to reflect the full scope of changes, such as 'Multi-component updates: pcapng timestamping optimization, burst size configurability, driver enhancements, and documentation updates' or split into multiple focused PRs.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch series_36795

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and found some issues that need to be addressed.

  • In ip_reassembly setup_queue_tbl(), the guard if (lcore > RTE_MAX_LCORE || queue > RTE_MAX_QUEUES_PER_PORT) looks off-by-one; if the intent is to reject indexes equal to the max (to avoid overly long pool names), these checks should likely use >= instead of >.
  • The new pcapng timestamp conversion masks the TSC delta with tc->mask (56 bits) relative to a fixed tsc_base, which will cause timestamps to wrap after roughly 2^56 cycles (~tens of seconds on modern CPUs); consider either dropping the mask or updating the base periodically so long-running captures don’t get incorrect (non-monotonic) timestamps.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In ip_reassembly `setup_queue_tbl()`, the guard `if (lcore > RTE_MAX_LCORE || queue > RTE_MAX_QUEUES_PER_PORT)` looks off-by-one; if the intent is to reject indexes equal to the max (to avoid overly long pool names), these checks should likely use `>=` instead of `>`.
- The new pcapng timestamp conversion masks the TSC delta with `tc->mask` (56 bits) relative to a fixed `tsc_base`, which will cause timestamps to wrap after roughly 2^56 cycles (~tens of seconds on modern CPUs); consider either dropping the mask or updating the base periodically so long-running captures don’t get incorrect (non-monotonic) timestamps.

## Individual Comments

### Comment 1
<location> `lib/pcapng/rte_pcapng.c:121-124` </location>
<code_context>
+	tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
+	tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+
+	/* Set conversion factors for reasonabl prescision with no overflow */
+	uint64_t tsc_hz = rte_get_tsc_hz();
+	tc->shift = 24;
+	tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
+	tc->mask = RTE_BIT64(56) - 1;
+}
</code_context>

<issue_to_address>
**issue (bug_risk):** Fixed-point timestamp scaling risks 64-bit overflow for large TSC deltas.

Given `shift = 24` and `mask = RTE_BIT64(56) - 1`, `delta` can be up to ~2^56 and `mult` is on the order of 2^24 for typical 1–3 GHz TSC values. Then `delta * mult` can reach ~2^80 before the shift, which does not fit in 64 bits and will overflow. Linux’s cyclecounter code avoids this by constraining mask/shift/mult. Please either tighten `mask`/`shift` so the intermediate product always fits in 64 bits, or use a 128-bit intermediate for the multiply (where available) and only truncate to 64 bits after the right shift; otherwise timestamps can wrap or jump after long runtimes.
</issue_to_address>

### Comment 2
<location> `examples/ip_reassembly/main.c:887-888` </location>
<code_context>

 	nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)NB_MBUF);

+	/* Should never happen but check so that pool name won't be too long. */
+	if (lcore > RTE_MAX_LCORE || queue > RTE_MAX_QUEUES_PER_PORT) {
+		RTE_LOG(ERR, IP_RSMBL, "invalid lcore %u or queue %u",
+			lcore, queue);
</code_context>

<issue_to_address>
**issue (bug_risk):** Bounds check on lcore/queue is off by one and still allows out-of-range values.

`lcore > RTE_MAX_LCORE || queue > RTE_MAX_QUEUES_PER_PORT` still permits `lcore == RTE_MAX_LCORE` and `queue == RTE_MAX_QUEUES_PER_PORT`, which are out of range if these macros are counts rather than max indices. If you’re validating indices, both comparisons should use `>=` instead of `>`.
</issue_to_address>

### Comment 3
<location> `examples/l3fwd/l3fwd.h:151-152` </location>
<code_context>
 	/* enough pkts to be sent */
-	if (unlikely(len == MAX_PKT_BURST)) {
-		send_burst(qconf, MAX_PKT_BURST, port);
+	if (unlikely(len == rx_burst_size)) {
+		send_burst(qconf, rx_burst_size, port);
 		len = 0;
 	}
</code_context>

<issue_to_address>
**suggestion (performance):** Using RX burst size as the TX flush threshold may change buffering behavior significantly.

Previously the TX flush threshold was fixed at `MAX_TX_BURST` (half of `MAX_PKT_BURST`) to "avoid TX buffering" while still batching. Coupling it to `rx_burst_size` means tuning RX for throughput also implicitly raises the TX flush threshold, which can increase latency and keep packets buffered longer. It would be better to keep a separate TX threshold (e.g. `tx_burst_size` or a derived constant) so RX and TX batching can be tuned independently.

Suggested implementation:

```c
extern uint32_t rx_burst_size;
extern uint32_t tx_burst_size;
extern uint32_t mb_mempool_cache_size;

```

```c
/* Send burst of packets on an output interface */
	len++;

	/* enough pkts to be sent */
	if (unlikely(len == tx_burst_size)) {
		send_burst(qconf, tx_burst_size, port);
		len = 0;
	}

```

1. Define and initialize `tx_burst_size` in the corresponding `.c` file (likely `examples/l3fwd/l3fwd.c` or similar), e.g.:
   - Add a global definition: `uint32_t tx_burst_size = MAX_TX_BURST;`
   - Optionally make it configurable via a command-line option, independent of `rx_burst_size`.
2. Ensure `tx_burst_size` does not exceed the size of the per-port TX buffer array (typically `MAX_PKT_BURST` in l3fwd), to avoid overruns inside `send_burst()`.
3. If any other locations in the codebase were changed to use `rx_burst_size` for TX flushing, update them similarly to use `tx_burst_size` instead.
</issue_to_address>

### Comment 4
<location> `doc/guides/rel_notes/release_25_11.rst:376` </location>
<code_context>
+    * Red Hat Enterprise Linux Server release 9.6
+    * Ubuntu 24.04 LTS
+    * Ubuntu 24.04.3 LTS
+    * Vmware ESXi 8.0.3
+
+  * NICs:
</code_context>

<issue_to_address>
**suggestion (typo):** Use the standard capitalization "VMware" for the product name.

Update this entry to "VMware ESXi 8.0.3" to match the vendor’s standard capitalization and keep it consistent with the rest of the document.

```suggestion
    * VMware ESXi 8.0.3
```
</issue_to_address>

### Comment 5
<location> `doc/guides/linux_gsg/amd_platform.rst:102` </location>
<code_context>
+Uncore
+~~~~~~
+
+AMD EPYC SoC support UNCORE power functions via ``rte_power_uncore`` from `25.03` onwards.
+These are tested and validated on GENOA, SIENA and TURIN.
+Please refer the tuning guides to enable ``HSMP`` and DPDK power management guide.
</code_context>

<issue_to_address>
**issue (typo):** Fix subject-verb agreement in "AMD EPYC SoC support UNCORE".

Change to: "AMD EPYC SoC supports UNCORE power functions…" to match the singular subject.

```suggestion
AMD EPYC SoC supports UNCORE power functions via ``rte_power_uncore`` from `25.03` onwards.
```
</issue_to_address>

### Comment 6
<location> `doc/guides/linux_gsg/amd_platform.rst:104` </location>
<code_context>
+
+AMD EPYC SoC support UNCORE power functions via ``rte_power_uncore`` from `25.03` onwards.
+These are tested and validated on GENOA, SIENA and TURIN.
+Please refer the tuning guides to enable ``HSMP`` and DPDK power management guide.
+
+
</code_context>

<issue_to_address>
**suggestion (typo):** Smooth the sentence "Please refer the tuning guides" and clarify the object.

Consider rephrasing for grammar and clarity, e.g.: "Please refer to the tuning guides and the DPDK power management guide to enable `HSMP`."

```suggestion
Please refer to the tuning guides and the DPDK power management guide to enable ``HSMP``.
```
</issue_to_address>

### Comment 7
<location> `doc/guides/freebsd_gsg/build_dpdk.rst:23-24` </location>
<code_context>
-  The specific package for pyelftools is dependent on the version of python in use,
-  Python 3.8 being the version at type of writing, hence the ``py38`` prefix.
+   The specific package for pyelftools is dependent on the version of python in use,
+   Python 3.11 being the version at type of writing, hence the ``py311`` prefix.

 These can be installed using (as root)::
</code_context>

<issue_to_address>
**issue (typo):** Correct "type of writing" to "time of writing".

Update the phrase to "the version at time of writing".

```suggestion
   The specific package for pyelftools is dependent on the version of python in use,
   Python 3.11 being the version at time of writing, hence the ``py311`` prefix.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (9)
drivers/common/mlx5/mlx5_prm.h (1)

2351-2351: Widened reserved_at_0 in flow_table_esw_cap_bits – please confirm against PRM

Changing reserved_at_0 from 0x200 to 0x800 bits moves ft_header_modify_esw_fdb and following fields in the layout. That’s fine if it’s aligning with the PRM / reference mlx5_ifc definition, but it is a silent ABI change at the HW‑interface level, so worth double‑checking against the spec to avoid subtle offset mismatches.

drivers/common/mlx5/mlx5_devx_cmds.c (1)

916-917: Workaround flag inversion deserves a brief comment

header_length_field_mode_wa is set to the logical negation of the HCA capability bit header_length_field_offset_mode. This likely encodes “apply workaround when offset‑mode is not supported”, but the inverted naming/semantics are non‑obvious. Consider a short comment explaining why this is !cap rather than mirroring it to avoid future confusion.

examples/l3fwd/l3fwd_common.h (1)

28-30: Configurable RX/TX burst sizes are wired correctly into send path; confirm global validation

Switching send_packetsx4() to use a configurable tx_burst_size threshold and exposing rx_burst_size/tx_burst_size via externs fits the per‑direction burst refactor. Locally, the logic remains safe as long as the global values are sane (e.g., >0 and not exceeding the static capacities used elsewhere, such as MAX_PKT_BURST for TX buffers and RX arrays in other files).

Please double‑check that the argument parsing or initialization path clamps both rx_burst_size and tx_burst_size to reasonable bounds (e.g., 1..MAX_PKT_BURST) to avoid any future misuse leading to over‑large bursts against fixed‑size stacks in the RX/TX loops.

Also applies to: 65-85

examples/l3fwd/l3fwd_lpm.c (1)

204-209: Use of rx_burst_size here assumes it never exceeds MAX_PKT_BURST

The change to pass rx_burst_size into rte_eth_rx_burst() is consistent with the new per‑direction burst configuration, but pkts_burst is still sized to MAX_PKT_BURST. If rx_burst_size can be set higher at runtime, this would overflow the stack array.

If the CLI parsing or init path already clamps rx_burst_size <= MAX_PKT_BURST, that’s fine; otherwise, consider either:

  • clamping at parse time, or
  • using a local const uint16_t burst = RTE_MIN((uint16_t)rx_burst_size, MAX_PKT_BURST); and passing burst here.

Also consider making rx_burst_size a uint16_t to match the ethdev API and avoid implicit narrowing.

examples/l3fwd/l3fwd_acl.c (1)

1134-1145: ACL RX path now depends on rx_burst_size staying within MAX_PKT_BURST

Using rx_burst_size here aligns the ACL path with the new configurable RX burst, but pkts_burst and hops are both sized using MAX_PKT_BURST. If rx_burst_size is ever configured larger, you’ll overrun those arrays.

Assuming rx_burst_size is validated globally (e.g., clamped to 1..MAX_PKT_BURST in argument parsing), this is fine. Otherwise, mirroring the safeguard suggested for the LPM path (local burst = RTE_MIN((uint16_t)rx_burst_size, MAX_PKT_BURST)) would make this loop robust against misconfiguration.

examples/l3fwd/l3fwd_em.c (1)

643-648: EM RX loop correctly uses rx_burst_size, but relies on global bound

The EM main loop now reads up to rx_burst_size packets into a pkts_burst[MAX_PKT_BURST] array. Behaviour is correct as long as rx_burst_size is guaranteed not to exceed MAX_PKT_BURST. Please ensure that invariant is enforced centrally (e.g., during option parsing), or add a local RTE_MIN clamp here as a defensive measure.

examples/l3fwd/l3fwd_fib.c (1)

237-248: FIB RX loop follows the new RX burst config; ensure rx_burst_sizeMAX_PKT_BURST

Switching to rx_burst_size here keeps FIB in line with the rest of l3fwd, but pkts_burst is still sized with MAX_PKT_BURST. If users can configure a larger RX burst, this would corrupt the stack.

As with the other paths, please confirm that rx_burst_size is validated not to exceed MAX_PKT_BURST (and ideally is at least 1), or clamp the value locally before passing it to rte_eth_rx_burst().

doc/guides/sample_app_ug/l3_forward.rst (1)

80-82: New --rx-burst / --tx-burst options are documented clearly; consider noting valid range

The added CLI options for per‑direction burst sizes (with default 32) match the new globals used in the code and are described clearly. To set user expectations and align with the fixed MAX_PKT_BURST arrays in the implementation, consider briefly documenting the acceptable range (e.g., that values above the internal maximum will be clamped or rejected).

Also applies to: 118-121

examples/l3fwd/main.c (1)

930-940: Improve error handling and avoid redundant function calls.

  1. Line 931 uses atoi() which doesn't distinguish between invalid input and the value 0. If the user provides non-numeric input, atoi() returns 0, which could be misinterpreted.
  2. Line 938 calls rte_eth_speed_bitflag(speed_num, 0) twice with identical arguments. The result should be computed once and stored.

Apply this diff:

 	case CMD_LINK_OPT_ETH_LINK_SPEED_NUM:
-		speed_num = atoi(optarg);
+		{
+		char *end = NULL;
+		speed_num = strtol(optarg, &end, 10);
+		if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0')) {
+			fprintf(stderr, "Invalid eth-link-speed\n");
+			print_usage(prgname);
+			return -1;
+		}
 		if ((speed_num == RTE_ETH_SPEED_NUM_10M) ||
 		    (speed_num == RTE_ETH_SPEED_NUM_100M)) {
 			fprintf(stderr, "Unsupported fixed speed\n");
 			print_usage(prgname);
 			return -1;
 		}
-		if (speed_num >= 0 && rte_eth_speed_bitflag(speed_num, 0) > 0)
-			port_conf.link_speeds = rte_eth_speed_bitflag(speed_num, 0);
+		uint32_t speed_bitflag = rte_eth_speed_bitflag(speed_num, 0);
+		if (speed_num > 0 && speed_bitflag > 0)
+			port_conf.link_speeds = speed_bitflag;
+		}
 		break;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef98b88 and 49e72ce.

⛔ Files ignored due to path filters (2)
  • doc/guides/prog_guide/img/kni_traffic_flow.png is excluded by !**/*.png
  • doc/guides/prog_guide/img/pkt_flow_kni.png is excluded by !**/*.png
📒 Files selected for processing (37)
  • VERSION (1 hunks)
  • doc/api/meson.build (3 hunks)
  • doc/guides/cryptodevs/ionic.rst (2 hunks)
  • doc/guides/freebsd_gsg/build_dpdk.rst (1 hunks)
  • doc/guides/linux_gsg/amd_platform.rst (2 hunks)
  • doc/guides/meson.build (1 hunks)
  • doc/guides/nics/i40e.rst (2 hunks)
  • doc/guides/nics/ice.rst (2 hunks)
  • doc/guides/nics/ionic.rst (2 hunks)
  • doc/guides/nics/mlx5.rst (11 hunks)
  • doc/guides/rel_notes/release_25_11.rst (1 hunks)
  • doc/guides/sample_app_ug/l3_forward.rst (2 hunks)
  • doc/guides/windows_gsg/build_dpdk.rst (4 hunks)
  • drivers/common/mlx5/mlx5_devx_cmds.c (2 hunks)
  • drivers/common/mlx5/mlx5_devx_cmds.h (2 hunks)
  • drivers/common/mlx5/mlx5_prm.h (4 hunks)
  • drivers/net/hns3/hns3_rxtx.c (2 hunks)
  • drivers/net/mlx5/mlx5.c (2 hunks)
  • drivers/net/mlx5/mlx5_flow_flex.c (2 hunks)
  • drivers/net/ngbe/ngbe_rxtx.c (1 hunks)
  • drivers/net/ntnic/ntnic_ethdev.c (0 hunks)
  • drivers/net/softnic/rte_eth_softnic.c (0 hunks)
  • drivers/net/txgbe/txgbe_rxtx.c (1 hunks)
  • examples/ip_reassembly/main.c (1 hunks)
  • examples/l3fwd-power/main.c (4 hunks)
  • examples/l3fwd/l3fwd.h (2 hunks)
  • examples/l3fwd/l3fwd_acl.c (1 hunks)
  • examples/l3fwd/l3fwd_common.h (2 hunks)
  • examples/l3fwd/l3fwd_em.c (1 hunks)
  • examples/l3fwd/l3fwd_fib.c (1 hunks)
  • examples/l3fwd/l3fwd_lpm.c (1 hunks)
  • examples/l3fwd/main.c (15 hunks)
  • examples/meson.build (1 hunks)
  • examples/server_node_efd/efd_server/main.c (1 hunks)
  • examples/server_node_efd/shared/common.h (1 hunks)
  • examples/vdpa/main.c (3 hunks)
  • lib/pcapng/rte_pcapng.c (6 hunks)
💤 Files with no reviewable changes (2)
  • drivers/net/softnic/rte_eth_softnic.c
  • drivers/net/ntnic/ntnic_ethdev.c
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (58)
examples/server_node_efd/efd_server/main.c (1)

70-88: MAC address buffer sizing update looks correct

Using addresses[RTE_MAX_ETHPORTS][RTE_ETHER_ADDR_FMT_SIZE + 1] aligns the per-port buffer with DPDK’s MAC-format size macro and gives enough room for the formatted address plus the embedded newline and terminator used in snprintf, avoiding truncation issues tied to err_address’s literal size.

drivers/net/hns3/hns3_rxtx.c (2)

4552-4565: Using dummy tx_pkt_prepare in stopped/non-started state is consistent and safe

Setting eth_dev->tx_pkt_prepare = rte_eth_tx_pkt_prepare_dummy; in the non-started/resetting branch gives callers a valid no-op prepare hook instead of leaving the pointer NULL or stale, matching the already-dummy rx/tx_pkt_burst functions in this state and avoiding special‑case checks elsewhere. No behavioral regressions are apparent given hns3_get_tx_prepare() still governs the real prep function when the datapath is running.


4917-4922: Aligning stop‑TX path with dummy tx_pkt_prepare avoids NULL/legacy pointers

Updating hns3_stop_tx_datapath() to set dev->tx_pkt_prepare = rte_eth_tx_pkt_prepare_dummy; alongside tx_pkt_burst = rte_eth_pkt_burst_dummy; keeps the fastpath function pointers self‑consistent while TX is stopped and avoids any remaining references to a driver‑specific or NULL prepare function during that period. The subsequent restart paths correctly restore the real hooks, so this change looks correct.

drivers/net/ngbe/ngbe_rxtx.c (1)

1918-1945: Dummy tx_pkt_prepare in simple TX path is appropriate

In the simple TX path (no offloads, single‑segment assumption), setting dev->tx_pkt_prepare = rte_eth_tx_pkt_prepare_dummy; gives a valid no‑op prepare function instead of leaving the pointer NULL, while the full‑feature path still uses ngbe_prep_pkts. Since offloads are disabled here, this doesn’t change semantics and just makes the API surface more uniform across TX modes.

drivers/net/txgbe/txgbe_rxtx.c (1)

2347-2347: LGTM! Dummy prepare function assignment is appropriate for simple TX path.

The assignment of rte_eth_tx_pkt_prepare_dummy instead of NULL is a good practice for the simple TX path with no offloads. This provides a consistent function pointer and avoids potential NULL checks in the datapath. The function has the correct signature (uint16_t (*eth_tx_prep_t)(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)) and simply returns all packets as-is since no preparation is needed, aligning with the established pattern used across multiple DPDK drivers (ngbe, ixgbe, ice, fm10k, hns3).

lib/pcapng/rte_pcapng.c (6)

44-51: LGTM! Clean refactoring of time-conversion state.

The new pcapng_time_conv structure consolidates timestamp conversion logic with appropriate fields for TSC-based time tracking. The embedded structure design keeps the conversion context self-contained.


128-139: LGTM! Efficient timestamp conversion implementation.

The refactored function correctly:

  • Uses masked delta computation to handle TSC wraparound
  • Employs fixed-point arithmetic (multiply + shift) to avoid expensive division
  • Adds the baseline offset to produce absolute nanosecond timestamps

The const qualifier on the parameter is good defensive programming.


356-356: LGTM! Correct usage of refactored time-conversion state.

The change correctly accesses ns_base from the new tc structure to retrieve the start time.


404-404: LGTM! Correct call to refactored timestamp function.

The call correctly passes the time-conversion context and current TSC cycles to compute the sample timestamp.


670-670: LGTM! Correct call to refactored timestamp function.

The call correctly passes the time-conversion context to convert the packet's captured TSC cycles to nanoseconds.


726-726: LGTM! Proper initialization of time-conversion state.

The time-conversion structure is correctly initialized during handle creation, establishing the baseline TSC and wall-clock time for subsequent timestamp conversions.

drivers/common/mlx5/mlx5_prm.h (3)

1600-1602: New steering logic format macros look consistent and harmless

The added MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 / _CONNECTX_6DX constants are self‑describing, fit the existing style, and do not alter behavior on their own.


2118-2120: Parse-graph node cap: header_length_field_offset_mode wiring looks correct

You’ve split the prior 3‑bit reserved_at_78 into reserved_at_78[0x1], header_length_field_offset_mode[0x1], and reserved_at_79[0x1], so the total width is unchanged and the new capability bit can be read safely. This matches the MLX5_GET(parse_graph_node_cap, …, header_length_field_offset_mode) usage in mlx5_devx_cmds.c.


4990-4992: Flex parser caps: offset-mode bit carved correctly from reserved space

The new header_length_field_offset_mode bit in mlx5_ifc_parse_graph_flex_bits replaces a 3‑bit reserved field with 1+1+1 bits, mirroring the parse‑graph node caps change. This keeps struct size intact and lines up with MLX5_SET(parse_graph_flex, …, header_length_field_offset_mode, …) in the DevX helper.

drivers/common/mlx5/mlx5_devx_cmds.c (1)

787-788: Flex parser creation now passes header_length_field_offset_mode

Plumbing data->header_length_field_offset_mode into the new parse_graph_flex.header_length_field_offset_mode bit is correct and matches the updated PRM struct; no issues spotted.

drivers/net/mlx5/mlx5_flow_flex.c (1)

557-575: LGTM: Conditional offset handling based on firmware capability.

The changes correctly gate the legacy workaround logic behind header_length_field_mode_wa and set the header_length_field_offset_mode flag accordingly. When the workaround is not needed (newer firmware), the offset mode flag is enabled, allowing the firmware to handle offset calculation directly.

drivers/common/mlx5/mlx5_devx_cmds.h (2)

122-122: LGTM: New capability flag for header length field mode workaround.

The header_length_field_mode_wa bitfield is correctly added to mlx5_hca_flex_attr to store the HCA capability indicating whether the legacy offset workaround is needed.


652-652: LGTM: New offset mode flag for graph node configuration.

The header_length_field_offset_mode bitfield is correctly added to mlx5_devx_graph_node_attr for configuring the offset mode when creating flex parsers.

drivers/net/mlx5/mlx5.c (2)

1083-1091: LGTM: Conditional SRH flex parser offset based on firmware capability.

The logic correctly differentiates between legacy firmware (pre-ConnectX-8) requiring the workaround with offset 8 and adjustments, versus newer firmware that supports direct offset specification at 12. The comments clearly document the distinction.


1494-1496: The hardcoded defaults (dv_flow_en = 1, allow_duplicate_pattern = 1) remove automatic Hardware Steering (HWS) detection, requiring explicit devargs configuration.

The original review comment correctly identifies a behavioral change. Verification confirms:

  1. dv_flow_en = 1 (SW steering) is now the hardcoded default — The old code likely auto-detected and set this to 2 (HWS) when supported by the device. The capability check at lines 1512–1519 only validates that the device supports DV flow (boolean check); it cannot upgrade dv_flow_en from 1 to 2 since the capability flag is not HWS-specific.

  2. Users must now explicitly set dv_flow_en=2 via devargs to enable HWS — The devargs handler (line 1402) accepts values 0–2, so this is still supported, but it's no longer automatic.

  3. allow_duplicate_pattern = 1 is a non-issue — It's properly overrideable via devargs and has appropriate compatibility checks (e.g., mlx5_os.c:663 with HAVE_MLX5_DR_ALLOW_DUPLICATE).

This is a legitimate behavioral change affecting deployments that relied on automatic Hardware Steering mode selection based on device capabilities. Existing deployments will silently fall back to SW steering unless explicitly configured with dv_flow_en=2.

examples/vdpa/main.c (4)

40-40: Buffer sizing accounts for concatenation with device count.

The reduced buffer size ensures that when iface is concatenated with devcnt (up to 4 digits for 1023) at line 501, the result fits within MAX_PATH_LEN (128 bytes). The calculation reserves 5 bytes for the device number and null terminator, leaving 123 bytes for the interface path prefix.

This change effectively prevents buffer overflow in the snprintf call at line 501-502.

Note: This relies on MAX_VDPA_STR_LEN correctly evaluating to 5 (see comment on line 25).


78-78: Good fix: strcmp is appropriate for option name comparison.

Changing from strncmp with MAX_PATH_LEN to strcmp is correct. Option names like "iface" are fixed strings, not user-provided paths, so using MAX_PATH_LEN (128) as a comparison limit was inappropriate. The strcmp function is the proper choice for exact string matching of known option names.


79-79: Improved safety: using sizeof(iface) instead of hardcoded constant.

Using sizeof(iface) instead of MAX_PATH_LEN is better defensive programming. This automatically uses the correct buffer size (now 123 bytes after line 40's change) and makes the code more maintainable—if the iface declaration changes, this copy operation remains correct without modification.


25-25: Based on my verification, I can now provide the rewritten review comment:


The RTE_STR macro does not expand MAX_VDPA_SAMPLE_PORTS to its numeric value.

Standard C stringification (the #x operator in _RTE_STR) does not expand macro arguments. Therefore, RTE_STR(MAX_VDPA_SAMPLE_PORTS) produces the literal string "MAX_VDPA_SAMPLE_PORTS" (24 bytes), not "1024" (5 bytes).

This means:

  • MAX_VDPA_STR_LEN = sizeof("MAX_VDPA_SAMPLE_PORTS") = 24 (not 5)
  • iface buffer at line 40 = 128 - 24 = 104 bytes (not 123)

The iface buffer is populated from command-line input at line 79 via rte_strscpy(iface, optarg, sizeof(iface)) and used in snprintf at line 502. While snprintf with MAX_PATH_LEN limit protects the destination buffer, verify that 104 bytes is the intended size for the interface path prefix, especially if longer paths are expected from user input.

doc/guides/cryptodevs/ionic.rst (2)

2-2: LGTM: Copyright year updated.

The copyright year has been appropriately updated to 2025.


19-20: LGTM: New hardware model documented.

The Pollara 400 single-port 400G AI NIC has been added to the list of supported models with proper documentation link.

doc/guides/nics/ionic.rst (2)

2-2: LGTM: Copyright year updated.

The copyright year has been appropriately updated to 2025.


18-19: LGTM: New hardware model documented.

The Pollara 400 single-port 400G AI NIC has been added to the supported models list with proper documentation link, consistent with the cryptodev guide.

examples/ip_reassembly/main.c (1)

887-893: LGTM: Good defensive bounds validation.

The bounds check prevents potential buffer overflow in the snprintf call at line 894 by ensuring lcore and queue indices won't generate overly long pool names. This is appropriate defensive programming.

doc/guides/rel_notes/release_25_11.rst (1)

348-600: LGTM: Comprehensive tested platforms documentation.

The detailed tested platforms section provides thorough information about hardware configurations, firmware versions, and operating systems validated with this release. This is valuable reference material for users deploying DPDK.

examples/meson.build (1)

81-83: LGTM: Removed warning suppression flag.

The removal of the conditional -Wno-format-truncation flag suggests format truncation issues have been addressed (as evidenced by the bounds check added in ip_reassembly/main.c). This is good practice—fixing the underlying issues rather than suppressing warnings.

examples/l3fwd/l3fwd.h (2)

115-115: LGTM: Variable renamed for clarity.

The rename from nb_pkt_per_burst to rx_burst_size better indicates this is RX-specific and aligns with the PR's broader refactoring to support separate RX and TX burst size configuration.


151-152: LGTM: Burst threshold updated to use configurable size.

The change from the MAX_PKT_BURST constant to the rx_burst_size variable enables runtime configuration of burst sizes, improving flexibility while maintaining the same buffering logic.

doc/guides/freebsd_gsg/build_dpdk.rst (2)

19-19: LGTM: Updated to current Python version.

The package has been updated from py38-pyelftools to py311-pyelftools, reflecting a more current Python version (3.11) than the previous 3.8, which reached end of life in 2024.


21-28: LGTM: Documentation updated consistently.

The note and installation command have been updated to reference Python 3.11, maintaining consistency with the package name change.

doc/api/meson.build (1)

30-30: LGTM: Documentation install tagging added.

The install_tag: 'doc' parameter has been added to documentation build targets, enabling selective installation of documentation components. This improves build system organization and aligns with the install tagging introduced in doc/guides/meson.build.

Also applies to: 80-80, 95-95

doc/guides/meson.build (1)

25-25: LGTM!

The addition of install_tag: 'doc' provides proper metadata tagging for documentation installation. This aligns with the broader build system improvements mentioned in the PR context.

VERSION (1)

1-1: LGTM!

Version bump to 25.11.0-rc4 is correctly formatted.

doc/guides/linux_gsg/amd_platform.rst (2)

25-25: LGTM - Typo correction!

The correction from "SIENNA" to "SIENA" is accurate for the AMD EPYC 8004 series processor naming.


112-112: Linux kernel version 6.13 requirement is valid and available.

As of November 2025, the latest stable Linux kernel version is 6.17.9 (released November 24, 2025). The documentation's requirement of Linux 6.13 or higher is well-established and achievable, with 6.13 having been available for several months prior to this date. No update to the documentation is needed.

doc/guides/nics/i40e.rst (2)

107-108: LGTM!

The addition of DPDK 25.11 compatibility information with corresponding kernel driver and firmware versions is properly documented for X710/XL710/XXV710.


140-141: LGTM!

The addition of DPDK 25.11 compatibility information for X722 is correctly formatted and consistent with the X710 series updates.

examples/l3fwd-power/main.c (2)

1504-1504: LGTM!

The addition of the --eth-link-speed option to the usage text properly documents the new command-line parameter.


1958-1970: I'll verify the input validation concerns for the eth-link-speed parameter. Let me start by examining the file and the function being referenced.
<function_calls>

cat -n examples/l3fwd-power/main.c | sed -n '1950,1980p'

</function_calls>

Let me also search for the parse_uint function definition to understand its signature and usage:
<function_calls>

rg -n "parse_uint" examples/l3fwd-power/main.c -A5 -B2

</function_calls>

Now let me check the RTE_ETH_SPEED_NUM constants to understand the validation logic:
<function_calls>

rg -n "RTE_ETH_SPEED_NUM" examples/l3fwd-power/main.c

</function_calls>

Let me also search for how parse_uint is used elsewhere in the file to understand the pattern:
<function_calls>

rg -n "parse_uint\s*(" examples/l3fwd-power/main.c -B3 -A3

</function_calls>

doc/guides/nics/ice.rst (4)

90-91: LGTM!

The DPDK 25.11 entry for E810 with updated kernel driver, DDP, and firmware versions is properly documented.


100-101: LGTM!

The DPDK 25.11 entry for E830 is correctly added with appropriate version information.


633-704: Excellent documentation addition!

The new sections on "Raw Pattern Components" and "Generating Raw Pattern Values" provide clear, comprehensive guidance on protocol-agnostic filtering. The explanation of Pattern Spec and Pattern Mask, along with the VPP tool reference and example, will significantly help users implement raw pattern flows.


905-914: LGTM!

The "Additional Options" section clearly documents the ACL engine disable option with a practical example, providing users with a way to optimize startup time when ACL functionality is not needed.

doc/guides/windows_gsg/build_dpdk.rst (2)

29-32: LGTM - Good security and version updates!

The changes improve security by using HTTPS for the LLVM website link and update the example to a recent LLVM version (19.1.0), making the documentation more relevant for current users.


134-147: Excellent documentation improvement!

The restructured Visual Studio Developer Command Prompt section is much clearer. The addition of:

  • A concrete code block showing the VsDevCmd.bat invocation
  • A note referencing official Microsoft documentation
  • Mention of PowerShell usage

makes this section more actionable and easier to follow for users.

doc/guides/nics/mlx5.rst (3)

648-652: Clarifications on dv_xmeta_en, dv_flow_en default, and allow_duplicate_pattern look coherent

The added tunnel-offload/sync-HWS note, explicit dv_flow_en default (1 when supported, else 0), and the statement that allow_duplicate_pattern defaults to 1 are internally consistent with existing wording and help remove ambiguity about defaults and unsupported combinations. I don’t see technical or structural issues here.

Also applies to: 689-701, 824-837


1366-1372: HWS runtime note and sync-API limitation bullets read clearly and are consistent

The new requirement to call rte_flow_configure() before using the async API, plus recommending it for sync, aligns with the later bullet describing default rte_flow_port_attr/queue settings. The sync-API limitations (match-field size errors vs tree expansion, non-zero-group rule-update behaviour, default allocation of max configurable actions, and the partial-mask caveat) are clearly scoped to dv_flow_en=2 and synchronous API only. No inconsistencies spotted; the “such limitation will be removed in future” remark is also fine as-is.

Also applies to: 1410-1443


2396-2403: New sync‑HWS limitations across PORT_REPRESENTOR/MARK/COUNT/AGE/METER/GRE are aligned and precise

The additional bullets making sync‑HWS behaviour explicit (no PORT_REPRESENTOR item, no transfer rules on representors, proxy‑port rule semantics, lack of ITEM_MARK in favour of META, extra kernel/rdma-core/DOCA requirements for root‑table COUNT/AGE, HWS‑only METER_MARK, and GRE c_rsvd0_ver unsupported in group 0) are all scoped correctly to “synchronous flow API with HW steering” and complement the global HWS Limitations section without contradiction. Wording and cross‑references look good.

Also applies to: 2593-2596, 2771-2773, 2812-2814, 2947-2949, 3816-3821

examples/l3fwd/main.c (5)

60-62: LGTM!

The per-direction burst size variables are properly declared and initialized with appropriate defaults.


404-405: LGTM!

Usage text is consistently updated to reflect the per-direction burst options. The documentation clearly distinguishes between RX and TX burst sizes.

Also applies to: 428-436, 468-469


762-762: LGTM!

Command-line option definitions are properly structured and follow the existing naming conventions. The enum values and long options array are correctly synchronized.

Also applies to: 784-785, 795-795, 817-818, 824-824, 847-848


949-955: LGTM!

The argument parsing correctly routes to parse_pkt_burst with the appropriate direction flag and burst size variable reference.


1690-1691: LGTM!

Runtime logging provides useful visibility into the configured burst sizes. This helps with debugging and performance tuning.

Comment on lines +729 to +732
ret = rte_eth_dev_info_get(0, &dev_info);
if (ret != 0)
return;
burst_size = dev_info.default_rxportconf.burst_size;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash
# First, get the line count of the file to understand its size
wc -l examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

1823 examples/l3fwd/main.c

</shell_result>


Script executed:

#!/bin/bash
# Read the parse_pkt_burst function context around lines 729-732
sed -n '700,760p' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

}

static void
parse_pkt_burst(const char *optarg, bool is_rx_burst, uint32_t *burst_sz)
{
	struct rte_eth_dev_info dev_info;
	unsigned long pkt_burst;
	uint16_t burst_size;
	char *end = NULL;
	int ret;

	/* parse decimal string */
	pkt_burst = strtoul(optarg, &end, 10);
	if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
		return;

	if (pkt_burst > MAX_PKT_BURST) {
		RTE_LOG(INFO, L3FWD, "User provided burst must be <= %d. Using default value %d\n",
			MAX_PKT_BURST, *burst_sz);
		return;
	} else if (pkt_burst > 0) {
		*burst_sz = (uint32_t)pkt_burst;
		return;
	}

	if (is_rx_burst) {
		/* If user gives a value of zero, query the PMD for its recommended
		 * Rx burst size.
		 */
		ret = rte_eth_dev_info_get(0, &dev_info);
		if (ret != 0)
			return;
		burst_size = dev_info.default_rxportconf.burst_size;
		if (burst_size == 0) {
			RTE_LOG(INFO, L3FWD, "PMD does not recommend a burst size. Using default value %d. "
				"User provided value must be in [1, %d]\n",
				rx_burst_size, MAX_PKT_BURST);
			return;
		} else if (burst_size > MAX_PKT_BURST) {
			RTE_LOG(INFO, L3FWD, "PMD recommended burst size %d exceeds maximum value %d. "
				"Using default value %d\n",
				burst_size, MAX_PKT_BURST, rx_burst_size);
			return;
		}
		*burst_sz = burst_size;
		RTE_LOG(INFO, L3FWD, "Using PMD-provided RX burst value %d\n", burst_size);
	} else {
		RTE_LOG(INFO, L3FWD, "User provided TX burst is 0. Using default value %d\n",
			*burst_sz);
	}
}

#define MAX_JUMBO_PKT_LEN  9600

static const char short_options[] =
	"p:"  /* portmask */
	"P"   /* promiscuous */
	"L"   /* legacy enable long prefix match */
	"E"   /* legacy enable exact match */
	;

</shell_result>


Script executed:

#!/bin/bash
# Search for calls to parse_pkt_burst
rg -n 'parse_pkt_burst' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

703:parse_pkt_burst(const char *optarg, bool is_rx_burst, uint32_t *burst_sz)
950:			parse_pkt_burst(optarg, true, &rx_burst_size);
954:			parse_pkt_burst(optarg, false, &tx_burst_size);

</shell_result>


Script executed:

#!/bin/bash
# Read the context around the parse_pkt_burst calls
sed -n '930,970p' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

		case CMD_LINK_OPT_ETH_LINK_SPEED_NUM:
			speed_num = atoi(optarg);
			if ((speed_num == RTE_ETH_SPEED_NUM_10M) ||
			    (speed_num == RTE_ETH_SPEED_NUM_100M)) {
				fprintf(stderr, "Unsupported fixed speed\n");
				print_usage(prgname);
				return -1;
			}
			if (speed_num >= 0 && rte_eth_speed_bitflag(speed_num, 0) > 0)
				port_conf.link_speeds = rte_eth_speed_bitflag(speed_num, 0);
			break;
		case CMD_LINE_OPT_RX_QUEUE_SIZE_NUM:
			parse_queue_size(optarg, &nb_rxd, 1);
			break;

		case CMD_LINE_OPT_TX_QUEUE_SIZE_NUM:
			parse_queue_size(optarg, &nb_txd, 0);
			break;

		case CMD_LINE_OPT_PKT_RX_BURST_NUM:
			parse_pkt_burst(optarg, true, &rx_burst_size);
			break;

		case CMD_LINE_OPT_PKT_TX_BURST_NUM:
			parse_pkt_burst(optarg, false, &tx_burst_size);
			break;

		case CMD_LINE_OPT_MB_CACHE_SIZE_NUM:
			parse_mbcache_size(optarg);
			break;

		case CMD_LINE_OPT_ETH_DEST_NUM:
			parse_eth_dest(optarg);
			break;

		case CMD_LINE_OPT_NO_NUMA_NUM:
			numa_on = 0;
			break;

		case CMD_LINE_OPT_IPV6_NUM:
			ipv6 = 1;

</shell_result>


Script executed:

#!/bin/bash
# Search for main function and port initialization patterns
rg -n 'int main' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 1

</shell_result>


Script executed:

#!/bin/bash
# Search for the entry point and port initialization
rg -n 'rte_eal_init|main\(' examples/l3fwd/main.c | head -20

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

1652:main(int argc, char **argv)
1665:	ret = rte_eal_init(argc, argv);

</shell_result>


Script executed:

#!/bin/bash
# Read the main function starting from line 1652
sed -n '1652,1750p' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

main(int argc, char **argv)
{
#ifdef RTE_LIB_EVENTDEV
	struct l3fwd_event_resources *evt_rsrc;
	int i;
#endif
	struct lcore_conf *qconf;
	uint16_t queueid, portid;
	unsigned int lcore_id;
	uint16_t queue;
	int ret;

	/* init EAL */
	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
	argc -= ret;
	argv += ret;

	force_quit = false;
	signal(SIGINT, signal_handler);
	signal(SIGTERM, signal_handler);

	/* pre-init dst MACs for all ports to 02:00:00:00:00:xx */
	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
		dest_eth_addr[portid] =
			RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40);
		*(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
	}

#ifdef RTE_LIB_EVENTDEV
	evt_rsrc = l3fwd_get_eventdev_rsrc();
#endif
	/* parse application arguments (after the EAL ones) */
	ret = parse_args(argc, argv);
	if (ret < 0)
		rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");

	RTE_LOG(INFO, L3FWD, "Using Rx burst %u Tx burst %u\n", rx_burst_size, tx_burst_size);

	/* Setup function pointers for lookup method. */
	setup_l3fwd_lookup_tables();

	/* Add the config file rules */
	l3fwd_lkp.read_config_files();

#ifdef RTE_LIB_EVENTDEV
	evt_rsrc->per_port_pool = per_port_pool;
	evt_rsrc->pkt_pool = pktmbuf_pool;
	evt_rsrc->vec_pool = vector_pool;
	evt_rsrc->port_mask = enabled_port_mask;
	/* Configure eventdev parameters if user has requested */
	if (evt_rsrc->enabled) {
		l3fwd_event_resource_setup(&port_conf);
		if (lookup_mode == L3FWD_LOOKUP_EM)
			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
		else if (lookup_mode == L3FWD_LOOKUP_FIB)
			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
		else
			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
	} else
#endif
		l3fwd_poll_resource_setup();

	/* start ports */
	RTE_ETH_FOREACH_DEV(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) {
			ret = rte_eth_promiscuous_enable(portid);
			if (ret != 0)
				rte_exit(EXIT_FAILURE,
					"rte_eth_promiscuous_enable: err=%s, port=%u\n",
					rte_strerror(-ret), portid);
		}
	}

#ifdef RTE_LIB_EVENTDEV
	if (evt_rsrc->enabled)
		l3fwd_event_service_setup();
#endif

	printf("\n");

	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {

</shell_result>


Script executed:

#!/bin/bash
# Check if there's any port initialization before parse_args
sed -n '1665,1695p' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
	argc -= ret;
	argv += ret;

	force_quit = false;
	signal(SIGINT, signal_handler);
	signal(SIGTERM, signal_handler);

	/* pre-init dst MACs for all ports to 02:00:00:00:00:xx */
	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
		dest_eth_addr[portid] =
			RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40);
		*(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
	}

#ifdef RTE_LIB_EVENTDEV
	evt_rsrc = l3fwd_get_eventdev_rsrc();
#endif
	/* parse application arguments (after the EAL ones) */
	ret = parse_args(argc, argv);
	if (ret < 0)
		rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");

	RTE_LOG(INFO, L3FWD, "Using Rx burst %u Tx burst %u\n", rx_burst_size, tx_burst_size);

	/* Setup function pointers for lookup method. */
	setup_l3fwd_lookup_tables();

	/* Add the config file rules */

</shell_result>


Script executed:

#!/bin/bash
# Search for other uses of rte_eth_dev_info_get in the codebase
rg -n 'rte_eth_dev_info_get' examples/l3fwd/main.c -B3 -A3

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

726-		/* If user gives a value of zero, query the PMD for its recommended
727-		 * Rx burst size.
728-		 */
729:		ret = rte_eth_dev_info_get(0, &dev_info);
730-		if (ret != 0)
731-			return;
732-		burst_size = dev_info.default_rxportconf.burst_size;
--
1379-		printf("Creating queues: nb_rxq=%d nb_txq=%u... ",
1380-			nb_rx_queue, (unsigned)n_tx_queue );
1381-
1382:		ret = rte_eth_dev_info_get(portid, &dev_info);
1383-		if (ret != 0)
1384-			rte_exit(EXIT_FAILURE,
1385-				"Error during getting device (port %u) info: %s\n",
--
1526-			printf("rxq=%d,%d,%d ", portid, queueid, socketid);
1527-			fflush(stdout);
1528-
1529:			ret = rte_eth_dev_info_get(portid, &dev_info);
1530-			if (ret != 0)
1531-				rte_exit(EXIT_FAILURE,
1532-					"Error during getting device (port %u) info: %s\n",

</shell_result>


Script executed:

#!/bin/bash
# Look for parse_args function to understand the full context
sed -n '1000,1050p' examples/l3fwd/main.c | head -50

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:


		case CMD_LINE_OPT_MODE_NUM:
			parse_mode(optarg);
			break;

#ifdef RTE_LIB_EVENTDEV
		case CMD_LINE_OPT_EVENTQ_SYNC_NUM:
			parse_eventq_sched(optarg);
			eventq_sched = 1;
			break;

		case CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM:
			parse_event_eth_rx_queues(optarg);
			eth_rx_q = 1;
			break;

		case CMD_LINE_OPT_ENABLE_VECTOR_NUM:
			printf("event vectorization is enabled\n");
			evt_rsrc->vector_enabled = 1;
			break;

		case CMD_LINE_OPT_VECTOR_SIZE_NUM:
			evt_rsrc->vector_size = strtol(optarg, NULL, 10);
			break;

		case CMD_LINE_OPT_VECTOR_TMO_NS_NUM:
			evt_rsrc->vector_tmo_ns = strtoull(optarg, NULL, 10);
			break;
#endif

		case CMD_LINE_OPT_LOOKUP_NUM:
			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
				return -1;
			}
			ret = parse_lookup(optarg);
			/*
			 * If parse_lookup was passed an invalid lookup type
			 * then return -1. Error log included within
			 * parse_lookup for simplicity.
			 */
			if (ret)
				return -1;
			break;

		case CMD_LINE_OPT_RULE_IPV4_NUM:
			l3fwd_set_rule_ipv4_name(optarg);
			break;
		case CMD_LINE_OPT_RULE_IPV6_NUM:
			l3fwd_set_rule_ipv6_name(optarg);

</shell_result>


Script executed:

#!/bin/bash
# Search for parse_args function
rg -n 'static.*parse_args' examples/l3fwd/main.c -A 5

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 1

</shell_result>


Script executed:

#!/bin/bash
# Search for parse_args more broadly
rg -n 'parse_args' examples/l3fwd/main.c | head -5

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

869:parse_args(int argc, char **argv)
1686:	ret = parse_args(argc, argv);

</shell_result>


Script executed:

#!/bin/bash
# Read the parse_args function
sed -n '869,920p' examples/l3fwd/main.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

parse_args(int argc, char **argv)
{
	int opt, ret;
	char **argvopt;
	int option_index;
	char *prgname = argv[0];
	uint8_t lcore_params = 0;
#ifdef RTE_LIB_EVENTDEV
	uint8_t eventq_sched = 0;
	uint8_t eth_rx_q = 0;
	struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc();
#endif
	int speed_num;

	argvopt = argv;

	/* Error or normal output strings. */
	while ((opt = getopt_long(argc, argvopt, short_options,
				lgopts, &option_index)) != EOF) {

		switch (opt) {
		/* portmask */
		case 'p':
			enabled_port_mask = parse_portmask(optarg);
			if (enabled_port_mask == 0) {
				fprintf(stderr, "Invalid portmask\n");
				print_usage(prgname);
				return -1;
			}
			break;

		case 'P':
			promiscuous_on = 1;
			break;

		case 'E':
			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
				return -1;
			}
			lookup_mode = L3FWD_LOOKUP_EM;
			break;

		case 'L':
			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
				return -1;
			}
			lookup_mode = L3FWD_LOOKUP_LPM;
			break;

		/* long options */

</shell_result>


Script executed:

#!/bin/bash
# Search for comments about port 0 or port initialization requirements
rg -n 'port 0|port zero|default.*port|PMD.*port' examples/l3fwd/main.c -B2 -A2

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

730-		if (ret != 0)
731-			return;
732:		burst_size = dev_info.default_rxportconf.burst_size;
733-		if (burst_size == 0) {
734-			RTE_LOG(INFO, L3FWD, "PMD does not recommend a burst size. Using default value %d. "

</shell_result>


Script executed:

#!/bin/bash
# Search for RTE_ETH_FOREACH_DEV or port counting to understand when ports are known
rg -n 'RTE_ETH_FOREACH_DEV|rte_eth_dev_count|nb_ports' examples/l3fwd/main.c -B2 -A2 | head -40

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

1218-			return;
1219-		all_ports_up = 1;
1220:		RTE_ETH_FOREACH_DEV(portid) {
1221-			if (force_quit)
1222-				return;
--
1341-	struct lcore_conf *qconf;
1342-	uint16_t queueid, portid;
1343:	unsigned int nb_ports;
1344-	unsigned int lcore_id;
1345-	int ret;
--
1352-		rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
1353-
1354:	nb_ports = rte_eth_dev_count_avail();
1355-
1356-	if (check_port_config() < 0)
--
1360-
1361-	/* initialize all ports */
1362:	RTE_ETH_FOREACH_DEV(portid) {
1363-		struct rte_eth_conf local_port_conf = port_conf;
1364-
--
1463-			 * rather, it signifies that portid is ignored.
1464-			 */
1465:			ret = init_mem(0, NB_MBUF(nb_ports));
1466-		} else {
1467-			ret = init_mem(portid, NB_MBUF(1));
--
1715-
1716-	/* start ports */
1717:	RTE_ETH_FOREACH_DEV(portid) {
1718-		if ((enabled_port_mask & (1 << portid)) == 0) {
1719-			continue;
--
1775-					evt_rsrc->tx_adptr.tx_adptr[i]);
1776-
1777:		RTE_ETH_FOREACH_DEV(portid) {
1778-			if ((enabled_port_mask & (1 << portid)) == 0)

</shell_result>


Script executed:

#!/bin/bash
# Search for any validation of port existence or port count checks
rg -n 'rte_eth_dev_is_valid_port|port.*valid|check_port' examples/l3fwd/main.c -B2 -A2

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

324-
325-static int
326:check_port_config(void)
327-{
328-	uint16_t portid;
--
335-			return -1;
336-		}
337:		if (!rte_eth_dev_is_valid_port(portid)) {
338-			printf("port %u is not present on the board\n", portid);
339-			return -1;
--
1354-	nb_ports = rte_eth_dev_count_avail();
1355-
1356:	if (check_port_config() < 0)
1357:		rte_exit(EXIT_FAILURE, "check_port_config failed\n");
1358-
1359-	nb_lcores = rte_lcore_count();

</shell_result>


Port 0 is hardcoded without validation; consider deferring burst size query or adding safeguards.

The function queries device info from hardcoded port 0 during argument parsing, which occurs immediately after rte_eal_init() but before actual port initialization and validation. While rte_eal_init() discovers available ports, port 0 is not validated to exist before this query. The error handling at line 730-731 silently returns without updating *burst_sz if the query fails, leaving the caller's burst size in an undefined state.

The check_port_config() function (line 326) validates all configured ports using rte_eth_dev_is_valid_port(), but this validation occurs after parse_args() completes. Hardcoding port 0 assumes it will always be available and valid, which may not hold in all configurations.

Consider:

  1. Querying the first valid port (not just port 0), or
  2. Deferring the PMD burst size query until after port validation, or
  3. Documenting that --rx-burst=0 requires port 0 to be present and valid on the platform

Comment on lines +736 to +741
rx_burst_size, MAX_PKT_BURST);
return;
} else if (burst_size > MAX_PKT_BURST) {
RTE_LOG(INFO, L3FWD, "PMD recommended burst size %d exceeds maximum value %d. "
"Using default value %d\n",
burst_size, MAX_PKT_BURST, rx_burst_size);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use the parameter instead of the global variable.

Lines 736 and 741 reference the global rx_burst_size directly instead of using the *burst_sz parameter that was passed to the function. This is inconsistent with the rest of the function (lines 718, 721, 744) which properly use *burst_sz.

Apply this diff:

 		if (burst_size == 0) {
 			RTE_LOG(INFO, L3FWD, "PMD does not recommend a burst size. Using default value %d. "
 				"User provided value must be in [1, %d]\n",
-				rx_burst_size, MAX_PKT_BURST);
+				*burst_sz, MAX_PKT_BURST);
 			return;
 		} else if (burst_size > MAX_PKT_BURST) {
 			RTE_LOG(INFO, L3FWD, "PMD recommended burst size %d exceeds maximum value %d. "
 				"Using default value %d\n",
-				burst_size, MAX_PKT_BURST, rx_burst_size);
+				burst_size, MAX_PKT_BURST, *burst_sz);
 			return;
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rx_burst_size, MAX_PKT_BURST);
return;
} else if (burst_size > MAX_PKT_BURST) {
RTE_LOG(INFO, L3FWD, "PMD recommended burst size %d exceeds maximum value %d. "
"Using default value %d\n",
burst_size, MAX_PKT_BURST, rx_burst_size);
*burst_sz, MAX_PKT_BURST);
return;
} else if (burst_size > MAX_PKT_BURST) {
RTE_LOG(INFO, L3FWD, "PMD recommended burst size %d exceeds maximum value %d. "
"Using default value %d\n",
burst_size, MAX_PKT_BURST, *burst_sz);
🤖 Prompt for AI Agents
In examples/l3fwd/main.c around lines 736 to 741, the log messages incorrectly
reference the global variable rx_burst_size instead of the function parameter
*burst_sz; update those references to use *burst_sz (the parameter passed into
the function) so the log and behavior are consistent with the rest of the
function.

Comment on lines 58 to 64
/*
* Buffer for return value. Size calculated by %u being replaced
* by maximum 3 digits (plus an extra byte for safety)
* Used as ring name, so upper limit is ring name size.
*/
static char buffer[sizeof(MP_NODE_RXQ_NAME) + 2];
static char buffer[RTE_RING_NAMESIZE];

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Align comment with new buffer sizing and make header self-contained for RTE_RING_NAMESIZE.

  • The first part of the comment (“Size calculated by %u being replaced…”) no longer matches the implementation now that the buffer is sized with RTE_RING_NAMESIZE. Consider simplifying the comment to just describe that it’s a ring name buffer bounded by the ring name size.
  • Since this header now depends on RTE_RING_NAMESIZE, it should explicitly include the header that defines it (typically rte_ring.h) so the header is self-contained and doesn’t rely on indirect includes.

Example adjustments:

-#include <rte_hash_crc.h>
-#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_hash.h>
+#include <rte_ring.h>
-	/*
-	 * Buffer for return value. Size calculated by %u being replaced
-	 * by maximum 3 digits (plus an extra byte for safety)
-	 * Used as ring name, so upper limit is ring name size.
-	 */
+	/*
+	 * Buffer for return value used as a ring name;
+	 * size is bounded by the ring name size limit.
+	 */
	static char buffer[RTE_RING_NAMESIZE];

The actual functional change (using RTE_RING_NAMESIZE) looks good and better matches the ring API constraints.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/*
* Buffer for return value. Size calculated by %u being replaced
* by maximum 3 digits (plus an extra byte for safety)
* Used as ring name, so upper limit is ring name size.
*/
static char buffer[sizeof(MP_NODE_RXQ_NAME) + 2];
static char buffer[RTE_RING_NAMESIZE];
/*
* Buffer for return value used as a ring name;
* size is bounded by the ring name size limit.
*/
static char buffer[RTE_RING_NAMESIZE];
🤖 Prompt for AI Agents
In examples/server_node_efd/shared/common.h around lines 58 to 64, the comment
describing buffer sizing is outdated (mentions %u/3 digits) and the header now
depends on RTE_RING_NAMESIZE; update the comment to simply state this char array
is a ring name buffer limited by RTE_RING_NAMESIZE and remove the old %u
explanation, and make the header self-contained by adding an explicit #include
for the header that defines RTE_RING_NAMESIZE (e.g., include rte_ring.h) near
the top of the file so this file doesn't rely on indirect includes.

Comment on lines +107 to +126
/* Initialize time conversion based on logic similar to rte_cyclecounter */
static void
pcapng_timestamp_init(struct pcapng_time_conv *tc)
{
struct timespec ts;
uint64_t cycles = rte_get_tsc_cycles();

/* record start time in ns since 1/1/1970 */
clock_gettime(CLOCK_REALTIME, &ts);

/* Compute baseline TSC which occured during clock_gettime */
tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;

/* Set conversion factors for reasonabl prescision with no overflow */
uint64_t tsc_hz = rte_get_tsc_hz();
tc->shift = 24;
tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
tc->mask = RTE_BIT64(56) - 1;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Script executed:

#!/bin/bash
# Search for tests or documentation related to timestamp conversion parameters
# and verify the typos in the comment

# First, confirm the exact content at lines 107-126
echo "=== Checking file content around lines 107-126 ==="
head -n 126 lib/pcapng/rte_pcapng.c | tail -n 20

# Search for existing tests related to pcapng timestamp
echo -e "\n=== Search for pcapng timestamp tests ==="
rg -n "pcapng.*timestamp|timestamp.*init" --type=c -C 2

# Search for documentation about these conversion parameters
echo -e "\n=== Search for documentation ==="
fd -e md -e rst -e txt --exec grep -l "timestamp\|TSC\|conversion" {} \;

# Search for similar shift and mask patterns in the codebase
echo -e "\n=== Search for shift=24 or mask patterns ==="
rg -n "shift\s*=\s*24|RTE_BIT64\(56\)" --type=c -C 2

# Look for any tests under lib/pcapng
echo -e "\n=== List test files related to pcapng ==="
fd -e c -e h "test|pcapng" | grep -i test

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

=== Checking file content around lines 107-126 ===
/* Initialize time conversion based on logic similar to rte_cyclecounter */
static void
pcapng_timestamp_init(struct pcapng_time_conv *tc)
{
	struct timespec ts;
	uint64_t cycles = rte_get_tsc_cycles();

	/* record start time in ns since 1/1/1970 */
	clock_gettime(CLOCK_REALTIME, &ts);

	/* Compute baseline TSC which occured during clock_gettime */
	tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
	tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;

	/* Set conversion factors for reasonabl prescision with no overflow */
	uint64_t tsc_hz = rte_get_tsc_hz();
	tc->shift = 24;
	tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
	tc->mask = RTE_BIT64(56) - 1;
}

=== Search for pcapng timestamp tests ===
lib/pcapng/rte_pcapng.c-107-/* Initialize time conversion based on logic similar to rte_cyclecounter */
lib/pcapng/rte_pcapng.c-108-static void
lib/pcapng/rte_pcapng.c:109:pcapng_timestamp_init(struct pcapng_time_conv *tc)
lib/pcapng/rte_pcapng.c-110-{
lib/pcapng/rte_pcapng.c-111-	struct timespec ts;
--
lib/pcapng/rte_pcapng.c-128-/* Convert from TSC (CPU cycles) to nanoseconds */
lib/pcapng/rte_pcapng.c-129-static uint64_t
lib/pcapng/rte_pcapng.c:130:pcapng_timestamp(const struct pcapng_time_conv *tc, uint64_t cycles)
lib/pcapng/rte_pcapng.c-131-{
lib/pcapng/rte_pcapng.c-132-	/* Compute TSC delta with mask to avoid wraparound */
--
lib/pcapng/rte_pcapng.c-275-	len = sizeof(*hdr);
lib/pcapng/rte_pcapng.c-276-
lib/pcapng/rte_pcapng.c:277:	len += pcapng_optlen(sizeof(tsresol));	/* timestamp */
lib/pcapng/rte_pcapng.c-278-	len += pcapng_optlen(strlen(ifname));	/* ifname */
lib/pcapng/rte_pcapng.c-279-
--
lib/pcapng/rte_pcapng.c-402-	hdr->interface_id = self->port_index[port_id];
lib/pcapng/rte_pcapng.c-403-
lib/pcapng/rte_pcapng.c:404:	sample_time = pcapng_timestamp(&self->tc, rte_get_tsc_cycles());
lib/pcapng/rte_pcapng.c-405-	hdr->timestamp_hi = sample_time >> 32;
lib/pcapng/rte_pcapng.c-406-	hdr->timestamp_lo = (uint32_t)sample_time;
--
lib/pcapng/rte_pcapng.c-668-		cycles = (uint64_t)epb->timestamp_hi << 32;
lib/pcapng/rte_pcapng.c-669-		cycles += epb->timestamp_lo;
lib/pcapng/rte_pcapng.c:670:		timestamp = pcapng_timestamp(&self->tc, cycles);
lib/pcapng/rte_pcapng.c-671-		epb->timestamp_hi = timestamp >> 32;
lib/pcapng/rte_pcapng.c-672-		epb->timestamp_lo = (uint32_t)timestamp;
--
lib/pcapng/rte_pcapng.c-724-	self->ports = 0;
lib/pcapng/rte_pcapng.c-725-
lib/pcapng/rte_pcapng.c:726:	pcapng_timestamp_init(&self->tc);
lib/pcapng/rte_pcapng.c-727-
lib/pcapng/rte_pcapng.c-728-	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
--
lib/log/log_timestamp.c-232-}
lib/log/log_timestamp.c-233-
lib/log/log_timestamp.c:234:RTE_INIT_PRIO(log_timestamp_init, LOG)
lib/log/log_timestamp.c-235-{
lib/log/log_timestamp.c-236-	struct timespec now;
--
drivers/net/intel/ice/base/ice_ptp_hw.h-636-#define BYTES_PER_IDX_ADDR_L		4
drivers/net/intel/ice/base/ice_ptp_hw.h-637-
drivers/net/intel/ice/base/ice_ptp_hw.h:638:/* Tx timestamp low latency read definitions */
drivers/net/intel/ice/base/ice_ptp_hw.h-639-#define TS_LL_MAX_TIME_READ_PER_PORT	80
drivers/net/intel/ice/base/ice_ptp_hw.h-640-#define TS_LL_MAX_PORT			8
--
app/test-pmd/txonly.c-63-static int32_t timestamp_off; /**< Timestamp dynamic field offset */
app/test-pmd/txonly.c-64-static bool timestamp_enable; /**< Timestamp enable */
app/test-pmd/txonly.c:65:static uint64_t timestamp_initial[RTE_MAX_ETHPORTS];
app/test-pmd/txonly.c-66-
app/test-pmd/txonly.c-67-static void
--
app/test-pmd/txonly.c-257-				TESTPMD_LOG(ERR,
app/test-pmd/txonly.c-258-					"Failed to get device info for port %d,"
app/test-pmd/txonly.c:259:					"could not finish timestamp init",
app/test-pmd/txonly.c-260-					fs->tx_port);
app/test-pmd/txonly.c-261-				return false;
--
app/test-pmd/txonly.c-268-			 * depending on queue index.
app/test-pmd/txonly.c-269-			 */
app/test-pmd/txonly.c:270:			skew = timestamp_initial[fs->tx_port] +
app/test-pmd/txonly.c-271-			       tx_pkt_times_inter + phase;
app/test-pmd/txonly.c-272-			fs->ts_skew = skew;
--
app/test-pmd/txonly.c-434-			   timestamp_mask &&
app/test-pmd/txonly.c-435-			   timestamp_off >= 0 &&
app/test-pmd/txonly.c:436:			   !rte_eth_read_clock(pi, &timestamp_initial[pi]);
app/test-pmd/txonly.c-437-
app/test-pmd/txonly.c-438-	if (timestamp_enable) {

=== Search for documentation ===
./doc/guides/tools/dumpcap.rst
./doc/guides/testpmd_app_ug/testpmd_funcs.rst
./doc/guides/tools/testeventdev.rst
./doc/guides/rel_notes/release_20_11.rst
./doc/guides/rel_notes/release_22_03.rst
./doc/guides/rel_notes/release_21_11.rst
./doc/guides/rel_notes/release_24_03.rst
./doc/guides/rel_notes/release_24_11.rst
./doc/guides/rel_notes/release_2_1.rst
./doc/guides/rel_notes/release_25_07.rst
./doc/guides/rel_notes/release_25_11.rst
./doc/guides/rel_notes/release_23_07.rst
./doc/guides/rel_notes/release_20_08.rst
./doc/guides/rel_notes/release_19_11.rst
./doc/guides/sample_app_ug/timer.rst
./doc/guides/rel_notes/release_17_11.rst
./doc/guides/rel_notes/release_17_05.rst
./doc/guides/sample_app_ug/rxtx_callbacks.rst
./doc/guides/platform/mlx5.rst
./doc/guides/prog_guide/bbdev.rst
./doc/guides/nics/nfb.rst
./doc/guides/nics/i40e.rst
./doc/guides/nics/ice.rst
./doc/guides/nics/mlx5.rst
./doc/guides/prog_guide/trace_lib.rst
./doc/guides/prog_guide/timer_lib.rst
./doc/guides/nics/hns3.rst
./doc/guides/nics/features.rst
./doc/guides/prog_guide/profile_app.rst
./doc/guides/nics/ena.rst
./doc/guides/prog_guide/ethdev/qos_framework.rst
./doc/guides/prog_guide/ethdev/flow_offload.rst
./doc/guides/prog_guide/multi_proc_support.rst
./doc/guides/nics/bnxt.rst
./doc/guides/prog_guide/mldev.rst
./doc/guides/prog_guide/metrics_lib.rst
./doc/guides/nics/ark.rst
./doc/guides/prog_guide/mbuf_lib.rst
./doc/guides/nics/af_packet.rst
./doc/guides/prog_guide/log_lib.rst
./doc/guides/prog_guide/glossary.rst
./doc/guides/prog_guide/env_abstraction_layer.rst
./doc/guides/linux_gsg/linux_eal_parameters.rst
./doc/guides/linux_gsg/enable_func.rst
./doc/guides/contributing/vulnerability.rst
./doc/guides/contributing/unit_test.rst

=== Search for shift=24 or mask patterns ===
lib/pcapng/rte_pcapng.c-121-	/* Set conversion factors for reasonabl prescision with no overflow */
lib/pcapng/rte_pcapng.c-122-	uint64_t tsc_hz = rte_get_tsc_hz();
lib/pcapng/rte_pcapng.c:123:	tc->shift = 24;
lib/pcapng/rte_pcapng.c-124-	tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
lib/pcapng/rte_pcapng.c:125:	tc->mask = RTE_BIT64(56) - 1;
lib/pcapng/rte_pcapng.c-126-}
lib/pcapng/rte_pcapng.c-127-
--
lib/ethdev/rte_ethdev.h-658- */
lib/ethdev/rte_ethdev.h-659-#define RTE_ETH_RSS_L3_PRE32           RTE_BIT64(57)
lib/ethdev/rte_ethdev.h:660:#define RTE_ETH_RSS_L3_PRE40           RTE_BIT64(56)
lib/ethdev/rte_ethdev.h-661-#define RTE_ETH_RSS_L3_PRE48           RTE_BIT64(55)
lib/ethdev/rte_ethdev.h-662-#define RTE_ETH_RSS_L3_PRE56           RTE_BIT64(54)
--
drivers/net/ntnic/nthw/flow_api/flow_api.c-964-	/* RTE_BIT64(55)  Not supported */
drivers/net/ntnic/nthw/flow_api/flow_api.c-965-	RSS_TO_STRING(RTE_ETH_RSS_L3_PRE48),
drivers/net/ntnic/nthw/flow_api/flow_api.c:966:	/* RTE_BIT64(56)  Not supported */
drivers/net/ntnic/nthw/flow_api/flow_api.c-967-	RSS_TO_STRING(RTE_ETH_RSS_L3_PRE40),
drivers/net/ntnic/nthw/flow_api/flow_api.c-968-	/* RTE_BIT64(57)  Not supported */
--
app/test/test_pmd_ring_perf.c-62-test_single_enqueue_dequeue(void)
app/test/test_pmd_ring_perf.c-63-{
app/test/test_pmd_ring_perf.c:64:	const unsigned iter_shift = 24;
app/test/test_pmd_ring_perf.c-65-	const unsigned iterations = 1 << iter_shift;
app/test/test_pmd_ring_perf.c-66-	unsigned i = 0;
--
app/test/test_ring_perf.c-405-	const unsigned int api_type)
app/test/test_ring_perf.c-406-{
app/test/test_ring_perf.c:407:	const unsigned int iter_shift = 24;
app/test/test_ring_perf.c-408-	const unsigned int iterations = 1 << iter_shift;
app/test/test_ring_perf.c-409-	unsigned int i = 0;
--
app/graph/utils.c-94-parser_ip4_read(uint32_t *value, char *p)
app/graph/utils.c-95-{
app/graph/utils.c:96:	uint8_t shift = 24;
app/graph/utils.c-97-	uint32_t ip = 0;
app/graph/utils.c-98-	char *token, *saveptr = NULL;

=== List test files related to pcapng ===
app/test/test.c
app/test/test.h
app/test/test_acl.c
app/test/test_acl.h
app/test/test_alarm.c
app/test/test_argparse.c
app/test/test_atomic.c
app/test/test_barrier.c
app/test/test_bitcount.c
app/test/test_bitmap.c
app/test/test_bitops.c
app/test/test_bitratestats.c
app/test/test_bitset.c
app/test/test_bpf.c
app/test/test_byteorder.c
app/test/test_cfgfile.c
app/test/test_cksum.c
app/test/test_cksum_perf.c
app/test/test_cmdline.c
app/test/test_cmdline.h
app/test/test_cmdline_cirbuf.c
app/test/test_cmdline_etheraddr.c
app/test/test_cmdline_ipaddr.c
app/test/test_cmdline_lib.c
app/test/test_cmdline_num.c
app/test/test_cmdline_portlist.c
app/test/test_cmdline_string.c
app/test/test_common.c
app/test/test_compressdev.c
app/test/test_compressdev_test_buffer.h
app/test/test_cpuflags.c
app/test/test_crc.c
app/test/test_cryptodev.c
app/test/test_cryptodev.h
app/test/test_cryptodev_aead_test_vectors.h
app/test/test_cryptodev_aes_test_vectors.h
app/test/test_cryptodev_asym.c
app/test/test_cryptodev_asym_util.h
app/test/test_cryptodev_blockcipher.c
app/test/test_cryptodev_blockcipher.h
app/test/test_cryptodev_crosscheck.c
app/test/test_cryptodev_des_test_vectors.h
app/test/test_cryptodev_dh_test_vectors.h
app/test/test_cryptodev_dsa_test_vectors.h
app/test/test_cryptodev_ecdh_test_vectors.h
app/test/test_cryptodev_ecdsa_test_vectors.h
app/test/test_cryptodev_ecpm_test_vectors.h
app/test/test_cryptodev_eddsa_test_vectors.h
app/test/test_cryptodev_hash_test_vectors.h
app/test/test_cryptodev_hmac_test_vectors.h
app/test/test_cryptodev_kasumi_hash_test_vectors.h
app/test/test_cryptodev_kasumi_test_vectors.h
app/test/test_cryptodev_mixed_test_vectors.h
app/test/test_cryptodev_ml_dsa_test_vectors.h
app/test/test_cryptodev_ml_kem_test_vectors.h
app/test/test_cryptodev_mod_test_vectors.h
app/test/test_cryptodev_rsa_test_vectors.h
app/test/test_cryptodev_security_docsis_test_vectors.h
app/test/test_cryptodev_security_ipsec.c
app/test/test_cryptodev_security_ipsec.h
app/test/test_cryptodev_security_ipsec_test_vectors.h
app/test/test_cryptodev_security_pdcp.c
app/test/test_cryptodev_security_pdcp_sdap_test_vectors.h
app/test/test_cryptodev_security_pdcp_test_func.h
app/test/test_cryptodev_security_pdcp_test_vectors.h
app/test/test_cryptodev_security_tls_record.c
app/test/test_cryptodev_security_tls_record.h
app/test/test_cryptodev_security_tls_record_test_vectors.h
app/test/test_cryptodev_sm2_test_vectors.h
app/test/test_cryptodev_sm4_test_vectors.h
app/test/test_cryptodev_snow3g_hash_test_vectors.h
app/test/test_cryptodev_snow3g_test_vectors.h
app/test/test_cryptodev_zuc_test_vectors.h
app/test/test_cycles.c
app/test/test_debug.c
app/test/test_devargs.c
app/test/test_dispatcher.c
app/test/test_distributor.c
app/test/test_distributor_perf.c
app/test/test_dmadev.c
app/test/test_dmadev_api.c
app/test/test_dmadev_api.h
app/test/test_eal_flags.c
app/test/test_eal_fs.c
app/test/test_efd.c
app/test/test_efd_perf.c
app/test/test_errno.c
app/test/test_ethdev_api.c
app/test/test_ethdev_link.c
app/test/test_event_crypto_adapter.c
app/test/test_event_dma_adapter.c
app/test/test_event_eth_rx_adapter.c
app/test/test_event_eth_tx_adapter.c
app/test/test_event_ring.c
app/test/test_event_timer_adapter.c
app/test/test_event_vector_adapter.c
app/test/test_eventdev.c
app/test/test_external_mem.c
app/test/test_fbarray.c
app/test/test_fib.c
app/test/test_fib6.c
app/test/test_fib6_perf.c
app/test/test_fib_perf.c
app/test/test_func_reentrancy.c
app/test/test_graph.c
app/test/test_graph_feature_arc.c
app/test/test_graph_perf.c
app/test/test_hash.c
app/test/test_hash_functions.c
app/test/test_hash_multiwriter.c
app/test/test_hash_perf.c
app/test/test_hash_readwrite.c
app/test/test_hash_readwrite_lf_perf.c
app/test/test_interrupts.c
app/test/test_ipfrag.c
app/test/test_ipsec.c
app/test/test_ipsec_perf.c
app/test/test_ipsec_sad.c
app/test/test_kvargs.c
app/test/test_latencystats.c
app/test/test_lcore_var.c
app/test/test_lcore_var_perf.c
app/test/test_lcores.c
app/test/test_link_bonding.c
app/test/test_link_bonding_mode4.c
app/test/test_link_bonding_rssconf.c
app/test/test_logs.c
app/test/test_lpm.c
app/test/test_lpm6.c
app/test/test_lpm6_data.h
app/test/test_lpm6_perf.c
app/test/test_lpm_perf.c
app/test/test_malloc.c
app/test/test_malloc_perf.c
app/test/test_mbuf.c
app/test/test_mcslock.c
app/test/test_member.c
app/test/test_member_perf.c
app/test/test_memcpy.c
app/test/test_memcpy_perf.c
app/test/test_memory.c
app/test/test_mempool.c
app/test/test_mempool_perf.c
app/test/test_memzone.c
app/test/test_meter.c
app/test/test_metrics.c
app/test/test_mp_secondary.c
app/test/test_net_ether.c
app/test/test_net_ip6.c
app/test/test_pcapng.c
app/test/test_pdcp.c
app/test/test_pdump.c
app/test/test_pdump.h
app/test/test_per_lcore.c
app/test/test_pflock.c
app/test/test_pie.c
app/test/test_pmd_perf.c
app/test/test_pmd_ring.c
app/test/test_pmd_ring_perf.c
app/test/test_pmu.c
app/test/test_power.c
app/test/test_power_cpufreq.c
app/test/test_power_intel_uncore.c
app/test/test_power_kvm_vm.c
app/test/test_prefetch.c
app/test/test_ptr_compress.c
app/test/test_rand_perf.c
app/test/test_rawdev.c
app/test/test_rcu_qsbr.c
app/test/test_rcu_qsbr_perf.c
app/test/test_reassembly_perf.c
app/test/test_reciprocal_division.c
app/test/test_reciprocal_division_perf.c
app/test/test_red.c
app/test/test_reorder.c
app/test/test_rib.c
app/test/test_rib6.c
app/test/test_ring.c
app/test/test_ring.h
app/test/test_ring_hts_stress.c
app/test/test_ring_mpmc_stress.c
app/test/test_ring_mt_peek_stress.c
app/test/test_ring_mt_peek_stress_zc.c
app/test/test_ring_perf.c
app/test/test_ring_rts_stress.c
app/test/test_ring_st_peek_stress.c
app/test/test_ring_st_peek_stress_zc.c
app/test/test_ring_stress.c
app/test/test_ring_stress.h
app/test/test_ring_stress_impl.h
app/test/test_rwlock.c
app/test/test_sched.c
app/test/test_security.c
app/test/test_security_inline_macsec.c
app/test/test_security_inline_macsec_vectors.h
app/test/test_security_inline_proto.c
app/test/test_security_inline_proto_vectors.h
app/test/test_security_proto.c
app/test/test_security_proto.h
app/test/test_seqlock.c
app/test/test_service_cores.c
app/test/test_soring.c
app/test/test_soring_mt_stress.c
app/test/test_soring_stress.c
app/test/test_soring_stress.h
app/test/test_soring_stress_impl.h
app/test/test_spinlock.c
app/test/test_stack.c
app/test/test_stack_perf.c
app/test/test_string_fns.c
app/test/test_table.c
app/test/test_table.h
app/test/test_table_acl.c
app/test/test_table_acl.h
app/test/test_table_combined.c
app/test/test_table_combined.h
app/test/test_table_pipeline.c
app/test/test_table_pipeline.h
app/test/test_table_ports.c
app/test/test_table_ports.h
app/test/test_table_tables.c
app/test/test_table_tables.h
app/test/test_tailq.c
app/test/test_telemetry_data.c
app/test/test_telemetry_json.c
app/test/test_thash.c
app/test/test_thash_perf.c
app/test/test_threads.c
app/test/test_ticketlock.c
app/test/test_timer.c
app/test/test_timer_perf.c
app/test/test_timer_racecond.c
app/test/test_timer_secondary.c
app/test/test_trace.c
app/test/test_trace.h
app/test/test_trace_perf.c
app/test/test_trace_register.c
app/test/test_vdev.c
app/test/test_version.c
app/test/test_xmmt_ops.h
app/test-bbdev/test_bbdev.c
app/test-bbdev/test_bbdev_perf.c
app/test-bbdev/test_bbdev_vector.c
app/test-bbdev/test_bbdev_vector.h
app/test-cmdline/cmdline_test.c
app/test-cmdline/cmdline_test.h
app/test-compress-perf/comp_perf_test_common.c
app/test-compress-perf/comp_perf_test_common.h
app/test-compress-perf/comp_perf_test_cyclecount.c
app/test-compress-perf/comp_perf_test_cyclecount.h
app/test-compress-perf/comp_perf_test_throughput.c
app/test-compress-perf/comp_perf_test_throughput.h
app/test-compress-perf/comp_perf_test_verify.c
app/test-compress-perf/comp_perf_test_verify.h
app/test-crypto-perf/cperf_test_common.c
app/test-crypto-perf/cperf_test_common.h
app/test-crypto-perf/cperf_test_latency.c
app/test-crypto-perf/cperf_test_latency.h
app/test-crypto-perf/cperf_test_pmd_cyclecount.c
app/test-crypto-perf/cperf_test_pmd_cyclecount.h
app/test-crypto-perf/cperf_test_throughput.c
app/test-crypto-perf/cperf_test_throughput.h
app/test-crypto-perf/cperf_test_vector_parsing.c
app/test-crypto-perf/cperf_test_vector_parsing.h
app/test-crypto-perf/cperf_test_vectors.c
app/test-crypto-perf/cperf_test_vectors.h
app/test-crypto-perf/cperf_test_verify.c
app/test-crypto-perf/cperf_test_verify.h
app/test-eventdev/evt_test.c
app/test-eventdev/evt_test.h
app/test-eventdev/test_atomic_atq.c
app/test-eventdev/test_atomic_common.c
app/test-eventdev/test_atomic_common.h
app/test-eventdev/test_atomic_queue.c
app/test-eventdev/test_order_atq.c
app/test-eventdev/test_order_common.c
app/test-eventdev/test_order_common.h
app/test-eventdev/test_order_queue.c
app/test-eventdev/test_perf_atq.c
app/test-eventdev/test_perf_common.c
app/test-eventdev/test_perf_common.h
app/test-eventdev/test_perf_queue.c
app/test-eventdev/test_pipeline_atq.c
app/test-eventdev/test_pipeline_common.c
app/test-eventdev/test_pipeline_common.h
app/test-eventdev/test_pipeline_queue.c
app/test-mldev/ml_test.c
app/test-mldev/ml_test.h
app/test-mldev/test_common.c
app/test-mldev/test_common.h
app/test-mldev/test_device_ops.c
app/test-mldev/test_device_ops.h
app/test-mldev/test_inference_common.c
app/test-mldev/test_inference_common.h
app/test-mldev/test_inference_interleave.c
app/test-mldev/test_inference_ordered.c
app/test-mldev/test_model_common.c
app/test-mldev/test_model_common.h
app/test-mldev/test_model_ops.c
app/test-mldev/test_model_ops.h
app/test-mldev/test_stats.c
app/test-mldev/test_stats.h
app/test-pmd/testpmd.c
app/test-pmd/testpmd.h
app/test-security-perf/test_security_perf.c
drivers/event/cnxk/cnxk_eventdev_selftest.c
drivers/event/dlb2/dlb2_selftest.c
drivers/event/dpaa2/dpaa2_eventdev_selftest.c
drivers/event/octeontx/ssovf_evdev_selftest.c
drivers/event/opdl/opdl_test.c
drivers/event/sw/sw_evdev_selftest.c
drivers/net/bonding/bonding_testpmd.c
drivers/net/intel/i40e/i40e_testpmd.c
drivers/net/intel/iavf/iavf_testpmd.c
drivers/net/intel/ice/ice_testpmd.c
drivers/net/intel/ixgbe/ixgbe_testpmd.c
drivers/net/mlx5/mlx5_testpmd.c
drivers/net/mlx5/mlx5_testpmd.h
drivers/raw/cnxk_bphy/cnxk_bphy_cgx_test.c
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
drivers/raw/cnxk_rvu_lf/cnxk_rvu_lf_selftest.c
drivers/raw/skeleton/skeleton_rawdev_test.c
examples/fips_validation/fips_dev_self_test.c
examples/fips_validation/fips_dev_self_test.h
lib/eal/include/rte_test.h

</shell_result>


Script executed:

#!/bin/bash
# Check the test file for pcapng timestamp validation
echo "=== Examining test_pcapng.c for timestamp tests ==="
wc -l app/test/test_pcapng.c

# Look for timestamp-related tests
rg -n "timestamp|shift|mask" app/test/test_pcapng.c -C 2

# Also check the header file to understand the time_conv structure
rg -n "pcapng_time_conv|struct.*time.*conv" --type=c -C 3

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

=== Examining test_pcapng.c for timestamp tests ===
467 app/test/test_pcapng.c
239-	ctx->count += 1;
240-
241:	/* The pcap library is misleading in reporting timestamp.
242:	 * packet header struct gives timestamp as a timeval (ie. usec);
243-	 * but the file is open in nanonsecond mode therefore
244:	 * the timestamp is really in timespec (ie. nanoseconds).
245-	 */
246-	ns = (uint64_t)h->ts.tv_sec * NS_PER_S + h->ts.tv_usec;
--
275-
276-static uint64_t
277:current_timestamp(void)
278-{
279-	struct timespec ts;
--
296-
297-	ctx.start_ns = started;
298:	ctx.end_ns = current_timestamp();
299-
300-	ctx.pcap = pcap_open_offline_with_tstamp_precision(file_name,
--
328-	static rte_pcapng_t *pcapng;
329-	int ret, tmp_fd;
330:	uint64_t now = current_timestamp();
331-
332-	tmp_fd = mkstemps(file_name, strlen(".pcapng"));
--
389-	static rte_pcapng_t *pcapng;
390-	int ret, tmp_fd, count;
391:	uint64_t now = current_timestamp();
392-
393-	tmp_fd = mkstemps(file_name, strlen(".pcapng"));
lib/pcapng/rte_pcapng.c-42-	int  outfd;		/* output file */
lib/pcapng/rte_pcapng.c-43-	unsigned int ports;	/* number of interfaces added */
lib/pcapng/rte_pcapng.c-44-
lib/pcapng/rte_pcapng.c:45:	struct pcapng_time_conv {
lib/pcapng/rte_pcapng.c-46-		uint64_t tsc_base; 	/* TSC when started */
lib/pcapng/rte_pcapng.c-47-		uint64_t ns_base;	/* ns since 1/1/1970 when initialized */
lib/pcapng/rte_pcapng.c-48-		uint64_t mult;		/* scaling factor relative to TSC hz */
--
lib/pcapng/rte_pcapng.c-106-
lib/pcapng/rte_pcapng.c-107-/* Initialize time conversion based on logic similar to rte_cyclecounter */
lib/pcapng/rte_pcapng.c-108-static void
lib/pcapng/rte_pcapng.c:109:pcapng_timestamp_init(struct pcapng_time_conv *tc)
lib/pcapng/rte_pcapng.c-110-{
lib/pcapng/rte_pcapng.c-111-	struct timespec ts;
lib/pcapng/rte_pcapng.c-112-	uint64_t cycles = rte_get_tsc_cycles();
--
lib/pcapng/rte_pcapng.c-127-
lib/pcapng/rte_pcapng.c-128-/* Convert from TSC (CPU cycles) to nanoseconds */
lib/pcapng/rte_pcapng.c-129-static uint64_t
lib/pcapng/rte_pcapng.c:130:pcapng_timestamp(const struct pcapng_time_conv *tc, uint64_t cycles)
lib/pcapng/rte_pcapng.c-131-{
lib/pcapng/rte_pcapng.c-132-	/* Compute TSC delta with mask to avoid wraparound */
lib/pcapng/rte_pcapng.c-133-	uint64_t delta = (cycles - tc->tsc_base) & tc->mask;
--
lib/member/rte_member.h-301-	/**
lib/member/rte_member.h-302-	 * Sampling rate means the internal sample rate of the rows of the count
lib/member/rte_member.h-303-	 * min sketches. Lower sampling rate can reduce CPU overhead, but the
lib/member/rte_member.h:304:	 * data structure will require more time to converge statistically.
lib/member/rte_member.h-305-	 */
lib/member/rte_member.h-306-	float sample_rate;
lib/member/rte_member.h-307-

</shell_result>


Script executed:

#!/bin/bash
# Get more context on the pcapng conversion functions and structure
echo "=== Full pcapng_timestamp_init and pcapng_timestamp functions ==="
sed -n '107,140p' lib/pcapng/rte_pcapng.c

# Check if there's any documentation in header files
echo -e "\n=== Check for header files with pcapng definitions ==="
find lib/pcapng -name "*.h" -exec cat {} \;

# Look for any comments or documentation about TSC or cyclecounter
echo -e "\n=== Search for related cyclecounter or TSC comments ==="
rg -n "cyclecounter|TSC.*hz|conversion.*factor" --type=c -C 2 | head -50

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

=== Full pcapng_timestamp_init and pcapng_timestamp functions ===
/* Initialize time conversion based on logic similar to rte_cyclecounter */
static void
pcapng_timestamp_init(struct pcapng_time_conv *tc)
{
	struct timespec ts;
	uint64_t cycles = rte_get_tsc_cycles();

	/* record start time in ns since 1/1/1970 */
	clock_gettime(CLOCK_REALTIME, &ts);

	/* Compute baseline TSC which occured during clock_gettime */
	tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
	tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;

	/* Set conversion factors for reasonabl prescision with no overflow */
	uint64_t tsc_hz = rte_get_tsc_hz();
	tc->shift = 24;
	tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
	tc->mask = RTE_BIT64(56) - 1;
}

/* Convert from TSC (CPU cycles) to nanoseconds */
static uint64_t
pcapng_timestamp(const struct pcapng_time_conv *tc, uint64_t cycles)
{
	/* Compute TSC delta with mask to avoid wraparound */
	uint64_t delta = (cycles - tc->tsc_base) & tc->mask;

	/* Convert TSC delta to nanoseconds (no division) */
	uint64_t ns_delta = (delta * tc->mult) >> tc->shift;

	return tc->ns_base + ns_delta;
}


=== Check for header files with pcapng definitions ===
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2019-2020 Microsoft Corporation
 *
 * PCAP Next Generation Capture File writer
 *
 * See: https://github.com/pcapng/pcapng/ for the file format.
 */

enum pcapng_block_types {
	PCAPNG_INTERFACE_BLOCK		= 1,
	PCAPNG_PACKET_BLOCK,		/* Obsolete */
	PCAPNG_SIMPLE_PACKET_BLOCK,
	PCAPNG_NAME_RESOLUTION_BLOCK,
	PCAPNG_INTERFACE_STATS_BLOCK,
	PCAPNG_ENHANCED_PACKET_BLOCK,

	PCAPNG_SECTION_BLOCK		= 0x0A0D0D0A,
};

struct pcapng_option {
	uint16_t code;
	uint16_t length;
	uint8_t data[];
};

#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D
#define PCAPNG_MAJOR_VERS 1
#define PCAPNG_MINOR_VERS 0

enum pcapng_opt {
	PCAPNG_OPT_END	= 0,
	PCAPNG_OPT_COMMENT = 1,
};

struct pcapng_section_header {
	uint32_t block_type;
	uint32_t block_length;
	uint32_t byte_order_magic;
	uint16_t major_version;
	uint16_t minor_version;
	uint64_t section_length;
};

enum pcapng_section_opt {
	PCAPNG_SHB_HARDWARE = 2,
	PCAPNG_SHB_OS	    = 3,
	PCAPNG_SHB_USERAPPL = 4,
};

struct pcapng_interface_block {
	uint32_t block_type;	/* 1 */
	uint32_t block_length;
	uint16_t link_type;
	uint16_t reserved;
	uint32_t snap_len;
};

enum pcapng_interface_options {
	PCAPNG_IFB_NAME	 = 2,
	PCAPNG_IFB_DESCRIPTION,
	PCAPNG_IFB_IPV4ADDR,
	PCAPNG_IFB_IPV6ADDR,
	PCAPNG_IFB_MACADDR,
	PCAPNG_IFB_EUIADDR,
	PCAPNG_IFB_SPEED,
	PCAPNG_IFB_TSRESOL,
	PCAPNG_IFB_TZONE,
	PCAPNG_IFB_FILTER,
	PCAPNG_IFB_OS,
	PCAPNG_IFB_FCSLEN,
	PCAPNG_IFB_TSOFFSET,
	PCAPNG_IFB_HARDWARE,
};

struct pcapng_enhance_packet_block {
	uint32_t block_type;	/* 6 */
	uint32_t block_length;
	uint32_t interface_id;
	uint32_t timestamp_hi;
	uint32_t timestamp_lo;
	uint32_t capture_length;
	uint32_t original_length;
};

/* Flags values */
#define PCAPNG_IFB_INBOUND   0b01
#define PCAPNG_IFB_OUTBOUND  0b10

enum pcapng_epb_options {
	PCAPNG_EPB_FLAGS = 2,
	PCAPNG_EPB_HASH,
	PCAPNG_EPB_DROPCOUNT,
	PCAPNG_EPB_PACKETID,
	PCAPNG_EPB_QUEUE,
	PCAPNG_EPB_VERDICT,
};

enum pcapng_epb_hash {
	PCAPNG_HASH_2COMP = 0,
	PCAPNG_HASH_XOR,
	PCAPNG_HASH_CRC32,
	PCAPNG_HASH_MD5,
	PCAPNG_HASH_SHA1,
	PCAPNG_HASH_TOEPLITZ,
};

struct pcapng_simple_packet {
	uint32_t block_type;	/* 3 */
	uint32_t block_length;
	uint32_t packet_length;
};

struct pcapng_statistics {
	uint32_t block_type;	/* 5 */
	uint32_t block_length;
	uint32_t interface_id;
	uint32_t timestamp_hi;
	uint32_t timestamp_lo;
};

enum pcapng_isb_options {
	PCAPNG_ISB_STARTTIME = 2,
	PCAPNG_ISB_ENDTIME,
	PCAPNG_ISB_IFRECV,
	PCAPNG_ISB_IFDROP,
	PCAPNG_ISB_FILTERACCEPT,
	PCAPNG_ISB_OSDROP,
	PCAPNG_ISB_USRDELIV,
};
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2019 Microsoft Corporation
 */

/**
 * @file
 * RTE pcapng
 *
 * Pcapng is an evolution from the pcap format, created to address some of
 * its deficiencies. Namely, the lack of extensibility and inability to store
 * additional information.
 *
 * For details about the file format see RFC:
 *   https://www.ietf.org/id/draft-tuexen-opsawg-pcapng-03.html
 *  and
 *    https://github.com/pcapng/pcapng/
 */

#ifndef _RTE_PCAPNG_H_
#define _RTE_PCAPNG_H_

#include <stdint.h>
#include <sys/types.h>

#include <rte_mempool.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Default link type for Ethernet traffic. */
#ifndef DLT_EN10MB
#define DLT_EN10MB 1
#endif

/* Opaque handle used for functions in this library. */
typedef struct rte_pcapng rte_pcapng_t;

/**
 * Write data to existing open file
 *
 * @param fd
 *   file descriptor
 * @param osname
 *   Optional description of the operating system.
 *   Examples: "Debian 11", "Windows Server 22"
 * @param hardware
 *   Optional description of the hardware used to create this file.
 *   Examples: "x86 Virtual Machine"
 * @param appname
 *   Optional: application name recorded in the pcapng file.
 *   Example: "dpdk-dumpcap 1.0 (DPDK 20.11)"
 * @param comment
 *   Optional comment to add to file header.
 * @return
 *   handle to library, or NULL in case of error (and rte_errno is set).
 */
rte_pcapng_t *
rte_pcapng_fdopen(int fd,
		  const char *osname, const char *hardware,
		  const char *appname, const char *comment);

/**
 * Close capture file
 *
 * @param self
 *  handle to library
 */
void
rte_pcapng_close(rte_pcapng_t *self);

/**
 * Add interface information to the capture file
 *
 * @param self
 *  The handle to the packet capture file
 * @param port
 *  The Ethernet port to report stats on.
 * @param link_type
 *  The link type (e.g., DLT_EN10MB).
 * @param ifname (optional)
 *  Interface name to record in the file.
 *  If not specified, name will be constructed from port
 * @param ifdescr (optional)
 *  Interface description to record in the file.
 * @param filter
 *  Capture filter to record in the file.
 *
 * Interfaces must be added to the output file after opening
 * and before any packet record. All ports used in packet capture
 * must be added.
 */
int
rte_pcapng_add_interface(rte_pcapng_t *self, uint16_t port, uint16_t link_type,
			 const char *ifname, const char *ifdescr,
			 const char *filter);

/**
 * Direction flag
 * These should match Enhanced Packet Block flag bits
 */
enum rte_pcapng_direction {
	RTE_PCAPNG_DIRECTION_UNKNOWN = 0,
	RTE_PCAPNG_DIRECTION_IN  = 1,
	RTE_PCAPNG_DIRECTION_OUT = 2,
};

/**
 * Format an mbuf for writing to file.
 *
 * @param port_id
 *   The Ethernet port on which packet was received
 *   or is going to be transmitted.
 * @param queue
 *   The queue on the Ethernet port where packet was received
 *   or is going to be transmitted.
 * @param mp
 *   The mempool from which the "clone" mbufs are allocated.
 * @param m
 *   The mbuf to copy
 * @param length
 *   The upper limit on bytes to copy.  Passing UINT32_MAX
 *   means all data (after offset).
 * @param direction
 *   The direction of the packer: receive, transmit or unknown.
 * @param comment
 *   Packet comment.
 *
 * @return
 *   - The pointer to the new mbuf formatted for pcapng_write
 *   - NULL if allocation fails.
 */
struct rte_mbuf *
rte_pcapng_copy(uint16_t port_id, uint32_t queue,
		const struct rte_mbuf *m, struct rte_mempool *mp,
		uint32_t length,
		enum rte_pcapng_direction direction, const char *comment);


/**
 * Determine optimum mbuf data size.
 *
 * @param length
 *   The largest packet that will be copied.
 * @return
 *   The minimum size of mbuf data to handle packet with length bytes.
 *   Accounting for required header and trailer fields
 */
uint32_t
rte_pcapng_mbuf_size(uint32_t length);

/**
 * Write packets to the capture file.
 *
 * Packets to be captured are copied by rte_pcapng_copy()
 * and then this function is called to write them to the file.
 *
 * @warning
 * Do not pass original mbufs from transmit or receive
 * or file will be invalid pcapng format.
 *
 * @param self
 *  The handle to the packet capture file
 * @param pkts
 *  The address of an array of *nb_pkts* pointers to *rte_mbuf* structures
 *  which contain the output packets
 * @param nb_pkts
 *  The number of packets to write to the file.
 * @return
 *  The number of bytes written to file, -1 on failure to write file.
 *  The mbuf's in *pkts* are always freed.
 */
ssize_t
rte_pcapng_write_packets(rte_pcapng_t *self,
			 struct rte_mbuf *pkts[], uint16_t nb_pkts);

/**
 * Write an Interface statistics block.
 * For statistics, use 0 if don't know or care to report it.
 * Should be called before closing capture to report results.
 *
 * @param self
 *  The handle to the packet capture file
 * @param port
 *  The Ethernet port to report stats on.
 * @param ifrecv
 *  The number of packets received by capture.
 *  Optional: use UINT64_MAX if not known.
 * @param ifdrop
 *  The number of packets missed by the capture process.
 *  Optional: use UINT64_MAX if not known.
 * @param comment
 *  Optional comment to add to statistics.
 * @return
 *  number of bytes written to file, -1 on failure to write file
 */
ssize_t
rte_pcapng_write_stats(rte_pcapng_t *self, uint16_t port,
		       uint64_t ifrecv, uint64_t ifdrop,
		       const char *comment);

#ifdef __cplusplus
}
#endif

#endif /* _RTE_PCAPNG_H_ */

=== Search for related cyclecounter or TSC comments ===
examples/vhost/main.c-210-struct vhost_bufftable *vhost_txbuff[RTE_MAX_LCORE * RTE_MAX_VHOST_DEVICE];
examples/vhost/main.c-211-
examples/vhost/main.c:212:#define MBUF_TABLE_DRAIN_TSC	((rte_get_tsc_hz() + US_PER_S - 1) \
examples/vhost/main.c-213-				 / US_PER_S * BURST_TX_DRAIN_US)
examples/vhost/main.c-214-
--
lib/pcapng/rte_pcapng.c-46-		uint64_t tsc_base; 	/* TSC when started */
lib/pcapng/rte_pcapng.c-47-		uint64_t ns_base;	/* ns since 1/1/1970 when initialized */
lib/pcapng/rte_pcapng.c:48:		uint64_t mult;		/* scaling factor relative to TSC hz */
lib/pcapng/rte_pcapng.c-49-		uint32_t shift;		/* shift for scaling (24) */
lib/pcapng/rte_pcapng.c-50-		uint64_t mask;		/* mask of bits used (56) */
--
lib/pcapng/rte_pcapng.c-105-#endif
lib/pcapng/rte_pcapng.c-106-
lib/pcapng/rte_pcapng.c:107:/* Initialize time conversion based on logic similar to rte_cyclecounter */
lib/pcapng/rte_pcapng.c-108-static void
lib/pcapng/rte_pcapng.c-109-pcapng_timestamp_init(struct pcapng_time_conv *tc)
--
lib/pcapng/rte_pcapng.c-119-	tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
lib/pcapng/rte_pcapng.c-120-
lib/pcapng/rte_pcapng.c:121:	/* Set conversion factors for reasonabl prescision with no overflow */
lib/pcapng/rte_pcapng.c-122-	uint64_t tsc_hz = rte_get_tsc_hz();
lib/pcapng/rte_pcapng.c-123-	tc->shift = 24;
--
lib/eal/include/rte_time.h-35-
lib/eal/include/rte_time.h-36-/**
lib/eal/include/rte_time.h:37: * Converts cyclecounter cycles to nanoseconds.
lib/eal/include/rte_time.h-38- */
lib/eal/include/rte_time.h-39-static inline uint64_t
lib/eal/include/rte_time.h:40:rte_cyclecounter_cycles_to_ns(struct rte_timecounter *tc, uint64_t cycles)
lib/eal/include/rte_time.h-41-{
lib/eal/include/rte_time.h-42-	uint64_t ns;
--
lib/eal/include/rte_time.h-66-
lib/eal/include/rte_time.h-67-	/* Convert to nanoseconds. */
lib/eal/include/rte_time.h:68:	ns_offset = rte_cyclecounter_cycles_to_ns(tc, cycle_delta);
lib/eal/include/rte_time.h-69-
lib/eal/include/rte_time.h-70-	/* Store current cycle counter for next call. */
--
drivers/net/intel/e1000/igb_ethdev.c-4834-
drivers/net/intel/e1000/igb_ethdev.c-4835-static uint64_t
drivers/net/intel/e1000/igb_ethdev.c:4836:igb_read_systime_cyclecounter(struct rte_eth_dev *dev)
drivers/net/intel/e1000/igb_ethdev.c-4837-{
drivers/net/intel/e1000/igb_ethdev.c-4838-	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
--
drivers/net/intel/e1000/igb_ethdev.c-4876-
drivers/net/intel/e1000/igb_ethdev.c-4877-static uint64_t
drivers/net/intel/e1000/igb_ethdev.c:4878:igb_read_rx_tstamp_cyclecounter(struct rte_eth_dev *dev)
drivers/net/intel/e1000/igb_ethdev.c-4879-{
drivers/net/intel/e1000/igb_ethdev.c-4880-	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);

</shell_result>


Script executed:

#!/bin/bash
# Check the cyclecounter implementation for comparison
echo "=== rte_cyclecounter implementation ==="
sed -n '35,75p' lib/eal/include/rte_time.h

# Search for any tests of cyclecounter or timestamp conversion
echo -e "\n=== Search for cyclecounter or timestamp conversion tests ==="
rg -n "rte_cyclecounter|cycles_to_ns" app/test --type=c -C 2

# Check if there are any comments about why 24 and 56 are chosen
echo -e "\n=== Full pcapng.c struct and conversion context ==="
sed -n '42,55p' lib/pcapng/rte_pcapng.c

Repository: ovsrobot/dpdk


<shell_result>
Repository: ovsrobot/dpdk
Exit code: 0

stdout:

=== rte_cyclecounter implementation ===

/**
 * Converts cyclecounter cycles to nanoseconds.
 */
static inline uint64_t
rte_cyclecounter_cycles_to_ns(struct rte_timecounter *tc, uint64_t cycles)
{
	uint64_t ns;

	/* Add fractional nanoseconds. */
	ns = cycles + tc->nsec_frac;
	tc->nsec_frac = ns & tc->nsec_mask;

	/* Shift to get only nanoseconds. */
	return ns >> tc->cc_shift;
}

/**
 * Update the internal nanosecond count in the structure.
 */
static inline uint64_t
rte_timecounter_update(struct rte_timecounter *tc, uint64_t cycle_now)
{
	uint64_t cycle_delta, ns_offset;

	/* Calculate the delta since the last call. */
	if (tc->cycle_last <= cycle_now)
		cycle_delta = (cycle_now - tc->cycle_last) & tc->cc_mask;
	else
		/* Handle cycle counts that have wrapped around . */
		cycle_delta = (~(tc->cycle_last - cycle_now) & tc->cc_mask) + 1;

	/* Convert to nanoseconds. */
	ns_offset = rte_cyclecounter_cycles_to_ns(tc, cycle_delta);

	/* Store current cycle counter for next call. */
	tc->cycle_last = cycle_now;

	/* Update the nanosecond count. */
	tc->nsec += ns_offset;


=== Search for cyclecounter or timestamp conversion tests ===

=== Full pcapng.c struct and conversion context ===
	int  outfd;		/* output file */
	unsigned int ports;	/* number of interfaces added */

	struct pcapng_time_conv {
		uint64_t tsc_base; 	/* TSC when started */
		uint64_t ns_base;	/* ns since 1/1/1970 when initialized */
		uint64_t mult;		/* scaling factor relative to TSC hz */
		uint32_t shift;		/* shift for scaling (24) */
		uint64_t mask;		/* mask of bits used (56) */
	} tc;

	/* DPDK port id to interface index in file */
	uint32_t port_index[RTE_MAX_ETHPORTS];
};

</shell_result>


Fix spelling errors in the comment on line 121.

The comment contains two typos: "reasonabl" should be "reasonable" and "prescision" should be "precision".

-	/* Set conversion factors for reasonabl prescision with no overflow */
+	/* Set conversion factors for reasonable precision with no overflow */

The shift value of 24 and mask of 56 bits are intentional design choices already documented in the struct definition and based on patterns similar to rte_cyclecounter. These provide adequate precision for typical TSC frequencies and reasonable wraparound handling. No test validation for edge cases with varying TSC frequencies was found in the codebase, though the parameters appear sound.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Initialize time conversion based on logic similar to rte_cyclecounter */
static void
pcapng_timestamp_init(struct pcapng_time_conv *tc)
{
struct timespec ts;
uint64_t cycles = rte_get_tsc_cycles();
/* record start time in ns since 1/1/1970 */
clock_gettime(CLOCK_REALTIME, &ts);
/* Compute baseline TSC which occured during clock_gettime */
tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
/* Set conversion factors for reasonabl prescision with no overflow */
uint64_t tsc_hz = rte_get_tsc_hz();
tc->shift = 24;
tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
tc->mask = RTE_BIT64(56) - 1;
}
/* Initialize time conversion based on logic similar to rte_cyclecounter */
static void
pcapng_timestamp_init(struct pcapng_time_conv *tc)
{
struct timespec ts;
uint64_t cycles = rte_get_tsc_cycles();
/* record start time in ns since 1/1/1970 */
clock_gettime(CLOCK_REALTIME, &ts);
/* Compute baseline TSC which occured during clock_gettime */
tc->tsc_base = (cycles + rte_get_tsc_cycles()) / 2;
tc->ns_base = (uint64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
/* Set conversion factors for reasonable precision with no overflow */
uint64_t tsc_hz = rte_get_tsc_hz();
tc->shift = 24;
tc->mult = ((uint64_t)1000000000ULL << tc->shift) / tsc_hz;
tc->mask = RTE_BIT64(56) - 1;
}
🤖 Prompt for AI Agents
In lib/pcapng/rte_pcapng.c around lines 107 to 126, the inline comment on line
121 contains two typos: change "reasonabl" to "reasonable" and "prescision" to
"precision"; update that comment text only to correct the spelling while leaving
the surrounding code (shift, mult, mask calculations and rationale) unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.