Skip to content

Using libtcpreplay

Fred Klassen edited this page Jul 21, 2026 · 1 revision

Using libtcpreplay

Since 4.6, the suite installs libtcpreplay — a static library exposing the same replay engine the tcpreplay binary uses, via tcpreplay_api.h (implemented in #1027, closing #133). This lets an application replay pcap files and read live statistics programmatically, instead of forking the tcpreplay binary and scraping its stdout/stderr (which is what people previously had to do — see the long history on #133).

Companion to Using libtcpedit — that library rewrites packet headers, this one sends them.

Building against it

Headers install under $(includedir)/tcpreplay/, and a pkg-config file (libtcpreplay.pc) is generated by both build systems. Because the library is static-only (by design — see below), ask pkg-config for the private dependency closure too:

cc myapp.c $(pkg-config --cflags --libs --static libtcpreplay) -o myapp
sudo ./myapp

Or from CMake, using the _STATIC_ pkg-config variables so the full static dependency closure gets linked:

find_package(PkgConfig REQUIRED)
pkg_check_modules(TCPREPLAY REQUIRED libtcpreplay)

add_executable(myapp myapp.c)
target_include_directories(myapp PRIVATE ${TCPREPLAY_STATIC_INCLUDE_DIRS})
target_link_directories(myapp PRIVATE ${TCPREPLAY_STATIC_LIBRARY_DIRS})
target_link_libraries(myapp PRIVATE ${TCPREPLAY_STATIC_LIBRARIES})

A complete, always-current example — examples/replay_stats.c — is compiled as part of every build (in-tree, not installed): cmake --build build --target replay_stats. See examples/README.md for the full walkthrough this page summarizes.

The API flow

#include "tcpreplay_api.h"

tcpreplay_t *ctx = tcpreplay_init();

if (tcpreplay_set_interface(ctx, intf1, "eth0") < 0 ||
    tcpreplay_add_pcapfile(ctx, "file.pcap") < 0 ||
    tcpreplay_set_speed_mode(ctx, speed_topspeed) < 0 ||
    tcpreplay_set_loop(ctx, 1) < 0) {
    fprintf(stderr, "setup failed: %s\n", tcpreplay_geterr(ctx));
    tcpreplay_close(ctx);
    return 1;
}

/* validates the configuration and opens the interface(s) */
if (tcpreplay_prepare(ctx) < 0) {
    fprintf(stderr, "prepare failed: %s\n", tcpreplay_geterr(ctx));
    tcpreplay_close(ctx);
    return 1;
}

if (tcpreplay_replay(ctx) < 0) {
    fprintf(stderr, "replay failed: %s\n", tcpreplay_geterr(ctx));
    tcpreplay_close(ctx);
    return 1;
}

const tcpreplay_stats_t *stats = tcpreplay_get_stats(ctx);
printf("packets sent: " COUNTER_SPEC "\n", stats->pkts_sent);

tcpreplay_close(ctx);

tcpreplay_get_stats(ctx) can be called from another thread while tcpreplay_replay() is still running on the replay thread — that's the point: streaming live stats out of a running replay without the fork/exec + pipe-scraping race conditions described in #133. tcpreplay_stats_t (src/common/utils.h) carries pkts_sent, bytes_sent, failed, start_time/end_time/time_delta (struct timespec), and per-flow counters (flows, flows_unique, flow_packets, flows_expired, ...). There are also single-value getters if you don't want the whole struct: tcpreplay_get_pkts_sent(), tcpreplay_get_bytes_sent(), tcpreplay_get_start_time(), tcpreplay_get_end_time().

Configuration setters worth knowing about

Beyond tcpreplay_set_interface()/tcpreplay_add_pcapfile() above (all in src/tcpreplay_api.h, 4.6.0-beta1):

Setter Purpose
tcpreplay_set_interface(ctx, intf1|intf2, name) primary / secondary output interface — same intf1/intf2 split as the CLI's --intf1/--intf2
tcpreplay_set_speed_mode() / tcpreplay_set_speed_speed() / tcpreplay_set_speed_pps_multi() speed mode (speed_multiplier, speed_mbpsrate, speed_packetrate, speed_topspeed, speed_oneatatime) and its value
tcpreplay_set_loop() repeat count
tcpreplay_set_tcpprep_cache() attach a tcpprep cache file — see Usage Examples for the tcpprep/tcprewrite/tcpreplay workflow this fits into
tcpreplay_set_unique_ip() / _unique_ip_loops() rewrite IPs uniquely per loop iteration
tcpreplay_set_mtu(), _set_accurate(), _set_limit_send(), _set_dualfile(), _set_netmap(), _set_preload_pcap(), _set_use_pkthdr_len() remaining per-run tuning knobs
tcpreplay_set_flow_stats() / _set_flow_expiry() / _get_flow_expiry() flow tracking, same as tcpreplay -F
tcpreplay_abort() / _suspend() / _restart() control a replay from another thread while it runs
tcpreplay_set_manual_callback() step through sends one at a time under caller control, instead of running to completion
tcpreplay_post_args(ctx, argc) alternative to the setters above: after calling AutoOpts' own optionProcess() on argv yourself, tcpreplay_post_args() picks up its parsed state — same two-step sequence the tcpreplay binary's own main() uses

Every setter returns < 0 on error; call tcpreplay_geterr(ctx) for the reason, same pattern as libtcpedit.

Design note: why static-only

The library is deliberately static-only for now. Its current API exposes structs (like tcpreplay_stats_t) whose layout depends on build-time flags, so a shared library would need an ABI-hardening pass first — opaque types, a symbol export map, a soname policy — which was intentionally left out of scope for the initial #1027 implementation. Rebuild your application when you upgrade Tcpreplay.


New page — libtcpreplay didn't exist on the legacy Trac wiki (it shipped in 4.6, long after that site went stale). Written directly from src/tcpreplay_api.h, examples/replay_stats.c, and examples/README.md at the time #133 was closed.

Clone this wiki locally