Since 4.6, the suite installs libtcpreplay — a static library exposing the
same replay engine the tcpreplay binary uses, via tcpreplay_api.h. This lets an
application replay pcap files and read live statistics programmatically, instead of
forking the tcpreplay binary and scraping its stdout/stderr.
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 in the source tree 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 fork/exec + pipe-scraping race
conditions. tcpreplay_stats_t 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):
| 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. Rebuild your application when you upgrade Tcpreplay.
Adapted from the Tcpreplay developer wiki.