1
0

tcpreplay_api.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2024 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "tcpreplay_api.h"
  20. #include "defines.h"
  21. #include "config.h"
  22. #include "common.h"
  23. #include "replay.h"
  24. #include "send_packets.h"
  25. #include "sleep.h"
  26. #include <ctype.h>
  27. #include <errno.h>
  28. #include <fcntl.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <sys/types.h>
  34. #include <time.h>
  35. #include <unistd.h>
  36. #ifdef TCPREPLAY_EDIT
  37. #include "tcpreplay_edit_opts.h"
  38. #else
  39. #include "tcpreplay_opts.h"
  40. #endif
  41. /**
  42. * \brief Returns a string describing the last error.
  43. *
  44. * Value when the last call does not result in an error is undefined
  45. * (may be NULL, may be garbage)
  46. */
  47. char *
  48. tcpreplay_geterr(tcpreplay_t *ctx)
  49. {
  50. assert(ctx);
  51. return(ctx->errstr);
  52. }
  53. /**
  54. * \brief Returns a string describing the last warning.
  55. *
  56. * Value when the last call does not result in an warning is undefined
  57. * (may be NULL, may be garbage)
  58. */
  59. char *
  60. tcpreplay_getwarn(tcpreplay_t *ctx)
  61. {
  62. assert(ctx);
  63. return(ctx->warnstr);
  64. }
  65. /**
  66. * \brief Initialize a new tcpreplay context
  67. *
  68. * Allocates memory and stuff like that. Always returns a buffer or completely
  69. * fails by calling exit() on malloc failure.
  70. */
  71. tcpreplay_t *
  72. tcpreplay_init()
  73. {
  74. tcpreplay_t *ctx;
  75. /* allocations will reset everything to zeros */
  76. ctx = safe_malloc(sizeof(tcpreplay_t));
  77. ctx->options = safe_malloc(sizeof(tcpreplay_opt_t));
  78. /* replay packets only once */
  79. ctx->options->loop = 1;
  80. /* Default mode is to replay pcap once in real-time */
  81. ctx->options->speed.mode = speed_multiplier;
  82. ctx->options->speed.multiplier = 1.0;
  83. /* Set the default timing method */
  84. ctx->options->accurate = accurate_gtod;
  85. /* set the default MTU size */
  86. ctx->options->mtu = DEFAULT_MTU;
  87. /* disable periodic statistics */
  88. ctx->options->stats = -1;
  89. /* disable limit send */
  90. ctx->options->limit_send = -1;
  91. /* default unique-loops */
  92. ctx->options->unique_loops = 1.0;
  93. #ifdef ENABLE_VERBOSE
  94. /* clear out tcpdump struct */
  95. ctx->options->tcpdump = (tcpdump_t *)safe_malloc(sizeof(tcpdump_t));
  96. #endif
  97. if (fcntl(STDERR_FILENO, F_SETFL, O_NONBLOCK) < 0)
  98. tcpreplay_setwarn(ctx, "Unable to set STDERR to non-blocking: %s", strerror(errno));
  99. #ifdef ENABLE_PCAP_FINDALLDEVS
  100. ctx->intlist = get_interface_list();
  101. #else
  102. ctx->intlist = NULL;
  103. #endif
  104. /* set up flows - on by default*/
  105. ctx->options->flow_stats = 1;
  106. ctx->flow_hash_table = flow_hash_table_init(DEFAULT_FLOW_HASH_BUCKET_SIZE);
  107. ctx->sp_type = SP_TYPE_NONE;
  108. ctx->intf1dlt = -1;
  109. ctx->intf2dlt = -1;
  110. ctx->abort = false;
  111. ctx->first_time = true;
  112. return ctx;
  113. }
  114. /**
  115. * \brief Parses the GNU AutoOpts options for tcpreplay
  116. *
  117. * If you're using AutoOpts with tcpreplay_api, then just call this after
  118. * optionProcess() and it will parse all the options for you. As always,
  119. * returns 0 on success, and -1 on error & -2 on warning.
  120. */
  121. int
  122. tcpreplay_post_args(tcpreplay_t *ctx, int argc)
  123. {
  124. char *temp, *intname;
  125. char *ebuf;
  126. tcpreplay_opt_t *options;
  127. int warn = 0;
  128. float n;
  129. int ret = 0;
  130. options = ctx->options;
  131. dbg(2, "tcpreplay_post_args: parsing command arguments");
  132. ebuf = safe_malloc(SENDPACKET_ERRBUF_SIZE);
  133. #ifdef DEBUG
  134. if (HAVE_OPT(DBUG))
  135. debug = OPT_VALUE_DBUG;
  136. #else
  137. if (HAVE_OPT(DBUG)) {
  138. warn ++;
  139. tcpreplay_setwarn(ctx, "%s", "not configured with --enable-debug. Debugging disabled.");
  140. }
  141. #endif
  142. options->loop = OPT_VALUE_LOOP;
  143. options->loopdelay_ms = OPT_VALUE_LOOPDELAY_MS;
  144. options->loopdelay_ns = OPT_VALUE_LOOPDELAY_NS;
  145. if (HAVE_OPT(LIMIT))
  146. options->limit_send = OPT_VALUE_LIMIT;
  147. if (HAVE_OPT(DURATION))
  148. options->limit_time = OPT_VALUE_DURATION;
  149. if (HAVE_OPT(TOPSPEED)) {
  150. options->speed.mode = speed_topspeed;
  151. options->speed.speed = 0;
  152. } else if (HAVE_OPT(PPS)) {
  153. n = atof(OPT_ARG(PPS));
  154. if (!n) {
  155. tcpreplay_seterr(ctx, "invalid pps value '%s'", OPT_ARG(PPS));
  156. ret = -1;
  157. goto out;
  158. }
  159. options->speed.speed = (COUNTER)(n * 60.0 * 60.0); /* convert to packets per hour */
  160. options->speed.mode = speed_packetrate;
  161. options->speed.pps_multi = OPT_VALUE_PPS_MULTI;
  162. } else if (HAVE_OPT(ONEATATIME)) {
  163. options->speed.mode = speed_oneatatime;
  164. options->speed.speed = 0;
  165. } else if (HAVE_OPT(MBPS)) {
  166. n = atof(OPT_ARG(MBPS));
  167. if (n) {
  168. options->speed.mode = speed_mbpsrate;
  169. options->speed.speed = (COUNTER)(n * 1000000.0); /* convert to bps */
  170. } else {
  171. options->speed.mode = speed_topspeed;
  172. options->speed.speed = 0;
  173. }
  174. } else if (HAVE_OPT(MULTIPLIER)) {
  175. options->speed.mode = speed_multiplier;
  176. options->speed.multiplier = atof(OPT_ARG(MULTIPLIER));
  177. }
  178. if (HAVE_OPT(MAXSLEEP)) {
  179. options->maxsleep.tv_sec = OPT_VALUE_MAXSLEEP / 1000;
  180. options->maxsleep.tv_nsec = (OPT_VALUE_MAXSLEEP % 1000) * 1000 * 1000;
  181. }
  182. if (HAVE_OPT(SUPPRESS_WARNINGS))
  183. print_warnings = 0;
  184. #ifdef ENABLE_VERBOSE
  185. if (HAVE_OPT(VERBOSE))
  186. options->verbose = 1;
  187. if (HAVE_OPT(DECODE))
  188. options->tcpdump->args = safe_strdup(OPT_ARG(DECODE));
  189. #endif
  190. if (HAVE_OPT(STATS))
  191. options->stats = OPT_VALUE_STATS;
  192. /*
  193. * preloading the pcap before the first run
  194. */
  195. if (HAVE_OPT(PRELOAD_PCAP)) {
  196. options->preload_pcap = true;
  197. }
  198. #ifdef TCPREPLAY_EDIT
  199. if (HAVE_OPT(PRELOAD_PCAP) && OPT_VALUE_LOOP > 1) {
  200. tcpreplay_seterr(ctx,
  201. "%s",
  202. "tcpreplay_edit --loop (-l) and --preload_pcap (-K) options are mutually exclusive");
  203. ret = -1;
  204. goto out;
  205. }
  206. #endif
  207. /* Dual file mode */
  208. if (HAVE_OPT(DUALFILE)) {
  209. options->dualfile = true;
  210. if (argc < 2) {
  211. tcpreplay_seterr(ctx, "%s", "--dualfile mode requires at least two pcap files");
  212. ret = -1;
  213. goto out;
  214. }
  215. if (argc % 2 != 0) {
  216. tcpreplay_seterr(ctx, "%s", "--dualfile mode requires an even number of pcap files");
  217. ret = -1;
  218. goto out;
  219. }
  220. }
  221. #ifdef HAVE_NETMAP
  222. options->netmap_delay = OPT_VALUE_NM_DELAY;
  223. #endif
  224. if (HAVE_OPT(NETMAP)) {
  225. #ifdef HAVE_NETMAP
  226. options->netmap = 1;
  227. ctx->sp_type = SP_TYPE_NETMAP;
  228. #else
  229. err(-1, "--netmap feature was not compiled in. See INSTALL.");
  230. #endif
  231. }
  232. if (HAVE_OPT(XDP)) {
  233. #ifdef HAVE_LIBXDP
  234. options->xdp = 1;
  235. ctx->sp_type = SP_TYPE_LIBXDP;
  236. #else
  237. err(-1, "--xdp feature was not compiled in. See INSTALL.");
  238. #endif
  239. }
  240. if (HAVE_OPT(UNIQUE_IP))
  241. options->unique_ip = 1;
  242. if (HAVE_OPT(UNIQUE_IP_LOOPS)) {
  243. options->unique_loops = atof(OPT_ARG(UNIQUE_IP_LOOPS));
  244. if (options->unique_loops < 1.0) {
  245. tcpreplay_seterr(ctx, "%s", "--unique-ip-loops requires loop count >= 1.0");
  246. ret = -1;
  247. goto out;
  248. }
  249. }
  250. /* flow statistics */
  251. if (HAVE_OPT(NO_FLOW_STATS))
  252. options->flow_stats = 0;
  253. if (HAVE_OPT(FLOW_EXPIRY)) {
  254. options->flow_expiry = OPT_VALUE_FLOW_EXPIRY;
  255. }
  256. if (HAVE_OPT(TIMER)) {
  257. if (strcmp(OPT_ARG(TIMER), "select") == 0) {
  258. #ifdef HAVE_SELECT
  259. options->accurate = accurate_select;
  260. #else
  261. tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with select support");
  262. ret = -1;
  263. goto out;
  264. #endif
  265. } else if (strcmp(OPT_ARG(TIMER), "ioport") == 0) {
  266. #if defined HAVE_IOPORT_SLEEP__
  267. options.accurate = ACCURATE_IOPORT;
  268. ioport_sleep_init();
  269. #else
  270. err(-1, "tcpreplay not compiled with IO Port 0x80 support");
  271. #endif
  272. } else if (strcmp(OPT_ARG(TIMER), "gtod") == 0) {
  273. options->accurate = accurate_gtod;
  274. } else if (strcmp(OPT_ARG(TIMER), "nano") == 0) {
  275. options->accurate = accurate_nanosleep;
  276. } else if (strcmp(OPT_ARG(TIMER), "abstime") == 0) {
  277. tcpreplay_seterr(ctx, "%s", "abstime is deprecated");
  278. ret = -1;
  279. goto out;
  280. } else {
  281. tcpreplay_seterr(ctx, "Unsupported timer mode: %s", OPT_ARG(TIMER));
  282. ret = -1;
  283. goto out;
  284. }
  285. }
  286. #ifdef HAVE_RDTSC
  287. if (HAVE_OPT(RDTSC_CLICKS)) {
  288. rdtsc_calibrate(OPT_VALUE_RDTSC_CLICKS);
  289. }
  290. #endif
  291. if (HAVE_OPT(PKTLEN)) {
  292. options->use_pkthdr_len = true;
  293. warn ++;
  294. tcpreplay_setwarn(ctx, "%s", "--pktlen may cause problems. Use with caution.");
  295. }
  296. switch (WHICH_IDX_INTF1) {
  297. case INDEX_OPT_WRITE:
  298. options->intf1_name = safe_strdup(OPT_ARG(INTF1));
  299. ctx->sp_type = SP_TYPE_LIBPCAP_DUMP;
  300. /* open interfaces for writing */
  301. if ((ctx->intf1 = sendpacket_open(options->intf1_name, ebuf, TCPR_DIR_C2S, ctx->sp_type, ctx)) == NULL) {
  302. tcpreplay_seterr(ctx, "Can't open %s: %s", options->intf1_name, ebuf);
  303. ret = -1;
  304. goto out;
  305. }
  306. break;
  307. case INDEX_OPT_INTF1:
  308. if ((intname = get_interface(ctx->intlist, OPT_ARG(INTF1))) == NULL) {
  309. if (!strncmp(OPT_ARG(INTF1), "netmap:", 7) || !strncmp(OPT_ARG(INTF1), "vale", 4)) {
  310. tcpreplay_seterr(
  311. ctx,
  312. "Unable to connect to netmap interface %s. Ensure netmap module is installed (see INSTALL).",
  313. OPT_ARG(INTF1));
  314. } else {
  315. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF1));
  316. }
  317. ret = -1;
  318. goto out;
  319. }
  320. if (!strncmp(intname, "netmap:", 7) || !strncmp(intname, "vale:", 5)) {
  321. #ifdef HAVE_NETMAP
  322. options->netmap = 1;
  323. ctx->sp_type = SP_TYPE_NETMAP;
  324. #else
  325. tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with netmap support");
  326. ret = -1;
  327. goto out;
  328. #endif
  329. }
  330. options->intf1_name = safe_strdup(intname);
  331. /* open interfaces for writing */
  332. if ((ctx->intf1 = sendpacket_open(options->intf1_name, ebuf, TCPR_DIR_C2S, ctx->sp_type, ctx)) == NULL) {
  333. tcpreplay_seterr(ctx, "Can't open %s: %s", options->intf1_name, ebuf);
  334. ret = -1;
  335. goto out;
  336. }
  337. #ifdef HAVE_LIBXDP
  338. ctx->intf1->batch_size = OPT_VALUE_XDP_BATCH_SIZE;
  339. #endif
  340. #if defined HAVE_NETMAP
  341. ctx->intf1->netmap_delay = ctx->options->netmap_delay;
  342. #endif
  343. ctx->intf1dlt = sendpacket_get_dlt(ctx->intf1);
  344. if (HAVE_OPT(INTF2)) {
  345. if (!HAVE_OPT(CACHEFILE) && !HAVE_OPT(DUALFILE)) {
  346. tcpreplay_seterr(ctx, "--intf2=%s requires either --cachefile or --dualfile", OPT_ARG(INTF2));
  347. ret = -1;
  348. goto out;
  349. }
  350. if ((intname = get_interface(ctx->intlist, OPT_ARG(INTF2))) == NULL) {
  351. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF2));
  352. ret = -1;
  353. goto out;
  354. }
  355. options->intf2_name = safe_strdup(intname);
  356. /* open interface for writing */
  357. if ((ctx->intf2 = sendpacket_open(options->intf2_name, ebuf, TCPR_DIR_S2C, ctx->sp_type, ctx)) == NULL) {
  358. tcpreplay_seterr(ctx, "Can't open %s: %s", options->intf2_name, ebuf);
  359. }
  360. #if defined HAVE_NETMAP
  361. ctx->intf2->netmap_delay = ctx->options->netmap_delay;
  362. #endif
  363. ctx->intf2dlt = sendpacket_get_dlt(ctx->intf2);
  364. if (ctx->intf2dlt != ctx->intf1dlt) {
  365. tcpreplay_seterr(ctx,
  366. "DLT type mismatch for %s (%s) and %s (%s)",
  367. options->intf1_name,
  368. pcap_datalink_val_to_name(ctx->intf1dlt),
  369. options->intf2_name,
  370. pcap_datalink_val_to_name(ctx->intf2dlt));
  371. ret = -1;
  372. goto out;
  373. }
  374. }
  375. break;
  376. default:
  377. assert(false); // shouldn't happen!
  378. }
  379. if (HAVE_OPT(CACHEFILE)) {
  380. temp = safe_strdup(OPT_ARG(CACHEFILE));
  381. options->cache_packets = read_cache(&options->cachedata, temp,
  382. &options->comment);
  383. safe_free(temp);
  384. }
  385. /* return -2 on warnings */
  386. if (warn > 0)
  387. ret = -2;
  388. out:
  389. safe_free(ebuf);
  390. return ret;
  391. }
  392. /**
  393. * Closes & free's all memory related to a tcpreplay context
  394. */
  395. void
  396. tcpreplay_close(tcpreplay_t *ctx)
  397. {
  398. tcpreplay_opt_t *options;
  399. interface_list_t *intlist, *intlistnext;
  400. packet_cache_t *packet_cache, *next;
  401. assert(ctx);
  402. assert(ctx->options);
  403. options = ctx->options;
  404. #ifdef HAVE_LIBXDP
  405. if (ctx->intf1->handle_type == SP_TYPE_LIBXDP) {
  406. free_umem_and_xsk(ctx->intf1);
  407. if (ctx->intf2) {
  408. free_umem_and_xsk(ctx->intf2);
  409. }
  410. }
  411. #endif
  412. safe_free(options->intf1_name);
  413. safe_free(options->intf2_name);
  414. sendpacket_close(ctx->intf1);
  415. if (ctx->intf2 != NULL)
  416. sendpacket_close(ctx->intf2);
  417. safe_free(options->cachedata);
  418. safe_free(options->comment);
  419. #ifdef ENABLE_VERBOSE
  420. safe_free(options->tcpdump_args);
  421. tcpdump_close(options->tcpdump);
  422. #endif
  423. /* free the flow hash table */
  424. flow_hash_table_release(ctx->flow_hash_table);
  425. /* free the file cache */
  426. packet_cache = options->file_cache->packet_cache;
  427. while (packet_cache != NULL) {
  428. next = packet_cache->next;
  429. safe_free(packet_cache->pktdata);
  430. safe_free(packet_cache);
  431. packet_cache = next;
  432. }
  433. /* free our interface list */
  434. if (ctx->intlist != NULL) {
  435. intlist = ctx->intlist;
  436. while (intlist != NULL) {
  437. intlistnext = intlist->next;
  438. safe_free(intlist);
  439. intlist = intlistnext;
  440. }
  441. }
  442. /* free --include / --exclude list */
  443. free_list(options->list);
  444. }
  445. /**
  446. * \brief Specifies an interface to use for sending.
  447. *
  448. * You may call this up to two (2) times with different interfaces
  449. * when using a tcpprep cache file or dualfile mode. Note, both interfaces
  450. * must use the same DLT type
  451. */
  452. int
  453. tcpreplay_set_interface(tcpreplay_t *ctx, tcpreplay_intf intf, char *value)
  454. {
  455. static int int1dlt = -1, int2dlt = -1;
  456. char *intname;
  457. char *ebuf;
  458. int ret = 0;
  459. assert(ctx);
  460. assert(value);
  461. ebuf = safe_malloc(SENDPACKET_ERRBUF_SIZE);
  462. if (intf == intf1) {
  463. if ((intname = get_interface(ctx->intlist, value)) == NULL) {
  464. if (!strncmp(OPT_ARG(INTF1), "netmap:", 7) || !strncmp(OPT_ARG(INTF1), "vale", 4))
  465. tcpreplay_seterr(ctx, "Unable to connect to netmap interface %s. Ensure netmap module is installed (see INSTALL).",
  466. value);
  467. else
  468. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", value);
  469. ret = -1;
  470. goto out;
  471. }
  472. ctx->options->intf1_name = safe_strdup(intname);
  473. /* open interfaces for writing */
  474. if ((ctx->intf1 = sendpacket_open(ctx->options->intf1_name, ebuf, TCPR_DIR_C2S, ctx->sp_type, ctx)) == NULL) {
  475. tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf1_name, ebuf);
  476. ret = -1;
  477. goto out;
  478. }
  479. int1dlt = sendpacket_get_dlt(ctx->intf1);
  480. } else if (intf == intf2) {
  481. if ((intname = get_interface(ctx->intlist, value)) == NULL) {
  482. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", ctx->options->intf2_name);
  483. ret = -1;
  484. goto out;
  485. }
  486. ctx->options->intf2_name = safe_strdup(intname);
  487. /* open interface for writing */
  488. if ((ctx->intf2 = sendpacket_open(ctx->options->intf2_name, ebuf, TCPR_DIR_S2C, ctx->sp_type, ctx)) == NULL) {
  489. tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf2_name, ebuf);
  490. ret = -1;
  491. goto out;
  492. }
  493. int2dlt = sendpacket_get_dlt(ctx->intf2);
  494. }
  495. /*
  496. * If both interfaces are selected, then make sure both interfaces use
  497. * the same DLT type
  498. */
  499. if (int1dlt != -1 && int2dlt != -1) {
  500. if (int1dlt != int2dlt) {
  501. tcpreplay_seterr(ctx, "DLT type mismatch for %s (%s) and %s (%s)",
  502. ctx->options->intf1_name, pcap_datalink_val_to_name(int1dlt),
  503. ctx->options->intf2_name, pcap_datalink_val_to_name(int2dlt));
  504. ret = -1;
  505. goto out;
  506. }
  507. }
  508. out:
  509. safe_free(ebuf);
  510. return ret;
  511. }
  512. /**
  513. * Set the replay speed mode.
  514. */
  515. int
  516. tcpreplay_set_speed_mode(tcpreplay_t *ctx, tcpreplay_speed_mode value)
  517. {
  518. assert(ctx);
  519. ctx->options->speed.mode = value;
  520. return 0;
  521. }
  522. /**
  523. * Set the approprate speed value. Value is interpreted based on
  524. * how tcpreplay_set_speed_mode() value
  525. */
  526. int
  527. tcpreplay_set_speed_speed(tcpreplay_t *ctx, COUNTER value)
  528. {
  529. assert(ctx);
  530. ctx->options->speed.speed = value;
  531. return 0;
  532. }
  533. /**
  534. * Sending under packets/sec requires an integer value, not float.
  535. * you must first call tcpreplay_set_speed_mode(ctx, speed_packetrate)
  536. */
  537. int
  538. tcpreplay_set_speed_pps_multi(tcpreplay_t *ctx, int value)
  539. {
  540. assert(ctx);
  541. ctx->options->speed.pps_multi = value;
  542. return 0;
  543. }
  544. /**
  545. * How many times should we loop through all the pcap files?
  546. */
  547. int
  548. tcpreplay_set_loop(tcpreplay_t *ctx, u_int32_t value)
  549. {
  550. assert(ctx);
  551. ctx->options->loop = value;
  552. return 0;
  553. }
  554. /**
  555. * Set the unique IP address flag
  556. */
  557. int
  558. tcpreplay_set_unique_ip(tcpreplay_t *ctx, bool value)
  559. {
  560. assert(ctx);
  561. ctx->options->unique_ip = value;
  562. return 0;
  563. }
  564. int
  565. tcpreplay_set_unique_ip_loops(tcpreplay_t *ctx, int value)
  566. {
  567. assert(ctx);
  568. ctx->options->unique_loops = value;
  569. return 0;
  570. }
  571. /**
  572. * Set netmap mode
  573. */
  574. int
  575. tcpreplay_set_netmap(_U_ tcpreplay_t *ctx, _U_ bool value)
  576. {
  577. assert(ctx);
  578. #ifdef HAVE_NETMAP
  579. ctx->options->netmap = value;
  580. return 0;
  581. #else
  582. warn("netmap not compiled in");
  583. return -1;
  584. #endif
  585. }
  586. /**
  587. * Tell tcpreplay to ignore the snaplen (default) and use the "actual"
  588. * packet len instead
  589. */
  590. int
  591. tcpreplay_set_use_pkthdr_len(tcpreplay_t *ctx, bool value)
  592. {
  593. assert(ctx);
  594. ctx->options->use_pkthdr_len = value;
  595. return 0;
  596. }
  597. /**
  598. * Override the outbound MTU
  599. */
  600. int
  601. tcpreplay_set_mtu(tcpreplay_t *ctx, int value)
  602. {
  603. assert(ctx);
  604. ctx->options->mtu = value;
  605. return 0;
  606. }
  607. /**
  608. * Sets the accurate timing mode
  609. */
  610. int
  611. tcpreplay_set_accurate(tcpreplay_t *ctx, tcpreplay_accurate value)
  612. {
  613. assert(ctx);
  614. ctx->options->accurate = value;
  615. return 0;
  616. }
  617. /**
  618. * Sets the number of seconds between printing stats
  619. */
  620. int
  621. tcpreplay_set_stats(tcpreplay_t *ctx, int value)
  622. {
  623. assert(ctx);
  624. ctx->options->stats = value;
  625. return 0;
  626. }
  627. /**
  628. * \brief Enable or disable dual file mode
  629. *
  630. * In dual file mode, we read two files at the same time and use
  631. * one file for each interface.
  632. */
  633. int
  634. tcpreplay_set_dualfile(tcpreplay_t *ctx, bool value)
  635. {
  636. assert(ctx);
  637. ctx->options->dualfile = value;
  638. return 0;
  639. }
  640. /**
  641. * \brief Enable or disable preloading the file cache
  642. *
  643. * Note: This is a global option and forces all pcaps
  644. * to be preloaded for this context. If you turn this
  645. * on, then it forces set_file_cache(true)
  646. */
  647. int
  648. tcpreplay_set_preload_pcap(tcpreplay_t *ctx, bool value)
  649. {
  650. assert(ctx);
  651. ctx->options->preload_pcap = value;
  652. return 0;
  653. }
  654. /**
  655. * \brief Add a pcap file to be sent via tcpreplay
  656. *
  657. * One or more pcap files can be added. Each file will be replayed
  658. * in order
  659. */
  660. int
  661. tcpreplay_add_pcapfile(tcpreplay_t *ctx, char *pcap_file)
  662. {
  663. assert(ctx);
  664. assert(pcap_file);
  665. if (ctx->options->source_cnt < MAX_FILES) {
  666. ctx->options->sources[ctx->options->source_cnt].filename = safe_strdup(pcap_file);
  667. ctx->options->sources[ctx->options->source_cnt].type = source_filename;
  668. /*
  669. * prepare the cache info data struct. This doesn't actually enable
  670. * file caching for this pcap (that is controlled globally via
  671. * tcpreplay_set_file_cache())
  672. */
  673. ctx->options->file_cache[ctx->options->source_cnt].index = ctx->options->source_cnt;
  674. ctx->options->file_cache[ctx->options->source_cnt].cached = false;
  675. ctx->options->file_cache[ctx->options->source_cnt].packet_cache = NULL;
  676. ctx->options->source_cnt += 1;
  677. } else {
  678. tcpreplay_seterr(ctx, "Unable to add more then %u files", MAX_FILES);
  679. return -1;
  680. }
  681. return 0;
  682. }
  683. /**
  684. * Limit the total number of packets to send
  685. */
  686. int
  687. tcpreplay_set_limit_send(tcpreplay_t *ctx, COUNTER value)
  688. {
  689. assert(ctx);
  690. ctx->options->limit_send = value;
  691. return 0;
  692. }
  693. /**
  694. * \brief Specify the tcpprep cache file to use for replaying with two NICs
  695. *
  696. * Note: this only works if you have a single pcap file
  697. * returns -1 on error
  698. */
  699. int
  700. tcpreplay_set_tcpprep_cache(tcpreplay_t *ctx, char *file)
  701. {
  702. assert(ctx);
  703. char *tcpprep_file;
  704. if (ctx->options->source_cnt > 1) {
  705. tcpreplay_seterr(ctx, "%s", "Unable to use tcpprep cache file with a single pcap file");
  706. return -1;
  707. }
  708. tcpprep_file = safe_strdup(file);
  709. ctx->options->cache_packets = read_cache(&ctx->options->cachedata,
  710. tcpprep_file, &ctx->options->comment);
  711. free(tcpprep_file);
  712. return 0;
  713. }
  714. /*
  715. * Verbose mode requires fork() and tcpdump binary, hence won't work
  716. * under Win32 without Cygwin
  717. */
  718. /**
  719. * Enable verbose mode
  720. */
  721. int
  722. tcpreplay_set_verbose(tcpreplay_t *ctx, bool value _U_)
  723. {
  724. assert(ctx);
  725. #ifdef ENABLE_VERBOSE
  726. ctx->options->verbose = value;
  727. return 0;
  728. #else
  729. tcpreplay_seterr(ctx, "%s", "verbose mode not supported");
  730. return -1;
  731. #endif
  732. }
  733. /**
  734. * \brief Set the arguments to be passed to tcpdump
  735. *
  736. * Specify the additional argument to be passed to tcpdump when enabling
  737. * verbose mode. See TCPDUMP_ARGS in tcpdump.h for the default options
  738. */
  739. int
  740. tcpreplay_set_tcpdump_args(tcpreplay_t *ctx, char *value _U_)
  741. {
  742. assert(ctx);
  743. #ifdef ENABLE_VERBOSE
  744. assert(value);
  745. ctx->options->tcpdump_args = safe_strdup(value);
  746. return 0;
  747. #else
  748. tcpreplay_seterr(ctx, "%s", "verbose mode not supported");
  749. return -1;
  750. #endif
  751. }
  752. /**
  753. * \brief Set the path to the tcpdump binary
  754. *
  755. * In order to support the verbose feature, tcpreplay needs to know where
  756. * tcpdump lives
  757. */
  758. int
  759. tcpreplay_set_tcpdump(tcpreplay_t *ctx, tcpdump_t *value _U_)
  760. {
  761. assert(ctx);
  762. #ifdef ENABLE_VERBOSE
  763. assert(value);
  764. ctx->options->verbose = true;
  765. ctx->options->tcpdump = value;
  766. return 0;
  767. #else
  768. tcpreplay_seterr(ctx, "%s", "verbose mode not supported");
  769. return -1;
  770. #endif
  771. }
  772. /**
  773. * \brief Set the callback function for handing manual iteration
  774. *
  775. * Obviously for this to work, you need to first set speed_mode = speed_oneatatime
  776. * returns 0 on success, < 0 on error
  777. */
  778. int
  779. tcpreplay_set_manual_callback(tcpreplay_t *ctx, tcpreplay_manual_callback callback)
  780. {
  781. assert(ctx);
  782. assert(callback);
  783. if (ctx->options->speed.mode != speed_oneatatime) {
  784. tcpreplay_seterr(ctx, "%s",
  785. "Unable to set manual callback because speed mode is not 'speed_oneatatime'");
  786. return -1;
  787. }
  788. ctx->options->speed.manual_callback = callback;
  789. return 0;
  790. }
  791. /**
  792. * \brief return the number of packets sent so far
  793. */
  794. COUNTER
  795. tcpreplay_get_pkts_sent(tcpreplay_t *ctx)
  796. {
  797. assert(ctx);
  798. ctx->static_stats.pkts_sent = ctx->stats.pkts_sent;
  799. return ctx->static_stats.pkts_sent;
  800. }
  801. /**
  802. * \brief return the number of bytes sent so far
  803. */
  804. COUNTER
  805. tcpreplay_get_bytes_sent(tcpreplay_t *ctx)
  806. {
  807. assert(ctx);
  808. ctx->static_stats.bytes_sent = ctx->stats.bytes_sent;
  809. return ctx->static_stats.bytes_sent;
  810. }
  811. /**
  812. * \brief return the number of failed attempts to send a packet
  813. */
  814. COUNTER
  815. tcpreplay_get_failed(tcpreplay_t *ctx)
  816. {
  817. assert(ctx);
  818. ctx->static_stats.failed = ctx->stats.failed;
  819. return ctx->static_stats.failed;
  820. }
  821. /**
  822. * \brief returns a pointer to the timespec structure of when replay first started
  823. */
  824. const struct timespec *
  825. tcpreplay_get_start_time(tcpreplay_t *ctx)
  826. {
  827. assert(ctx);
  828. TIMESPEC_SET(&ctx->static_stats.start_time, &ctx->stats.start_time);
  829. return &ctx->static_stats.start_time;
  830. }
  831. /**
  832. * \brief returns a pointer to the timespec structure of when replay finished
  833. */
  834. const struct timespec *
  835. tcpreplay_get_end_time(tcpreplay_t *ctx)
  836. {
  837. assert(ctx);
  838. TIMESPEC_SET(&ctx->static_stats.end_time, &ctx->stats.end_time);
  839. return &ctx->static_stats.end_time;
  840. }
  841. /**
  842. * \brief Internal function to set the tcpreplay error string
  843. *
  844. * Used to set the error string when there is an error, result is retrieved
  845. * using tcpedit_geterr(). You shouldn't ever actually call this, but use
  846. * tcpreplay_seterr() which is a macro wrapping this instead.
  847. */
  848. void
  849. __tcpreplay_seterr(tcpreplay_t *ctx, const char *func,
  850. const int line, const char *file, const char *fmt, ...)
  851. {
  852. va_list ap;
  853. char errormsg[TCPREPLAY_ERRSTR_LEN - 32];
  854. assert(ctx);
  855. assert(file);
  856. assert(func);
  857. assert(line);
  858. va_start(ap, fmt);
  859. if (fmt != NULL)
  860. (void)vsnprintf(errormsg, sizeof(errormsg), fmt, ap);
  861. va_end(ap);
  862. #ifdef DEBUG
  863. snprintf(ctx->errstr, sizeof(ctx->errstr), "From %s:%s() line %d:\n%s",
  864. file, func, line, errormsg);
  865. #else
  866. snprintf(ctx->errstr, sizeof(ctx->errstr), "%s", errormsg);
  867. #endif
  868. }
  869. /**
  870. * \brief Internal function to set the tcpedit warning string
  871. *
  872. * Used to set the warning string when there is an non-fatal issue, result is retrieved
  873. * using tcpedit_getwarn().
  874. */
  875. void
  876. tcpreplay_setwarn(tcpreplay_t *ctx, const char *fmt, ...)
  877. {
  878. va_list ap;
  879. assert(ctx);
  880. va_start(ap, fmt);
  881. if (fmt != NULL)
  882. (void)vsnprintf(ctx->warnstr, sizeof(ctx->warnstr), fmt, ap);
  883. va_end(ap);
  884. }
  885. /**
  886. * \brief Does all the prep work before calling tcpreplay_replay()
  887. *
  888. * Technically this validates our config options, preloads the tcpprep
  889. * cache file, loads the packet cache and anything else which might
  890. * cause a delay for starting to send packets with tcpreplay_replay()
  891. */
  892. int
  893. tcpreplay_prepare(tcpreplay_t *ctx)
  894. {
  895. char *intname, *ebuf;
  896. int int1dlt, int2dlt, i;
  897. int ret = 0;
  898. assert(ctx);
  899. ebuf = safe_malloc(SENDPACKET_ERRBUF_SIZE);
  900. /*
  901. * First, process the validations, basically the same we do in
  902. * tcpreplay_post_args() and AutoOpts
  903. */
  904. if (ctx->options->intf1_name == NULL) {
  905. tcpreplay_seterr(ctx, "%s", "You must specify at least one network interface");
  906. ret = -1;
  907. goto out;
  908. }
  909. if (ctx->options->source_cnt == 0) {
  910. tcpreplay_seterr(ctx, "%s", "You must specify at least one source pcap");
  911. ret = -1;
  912. goto out;
  913. }
  914. if (ctx->options->dualfile) {
  915. if (!(ctx->options->source_cnt >= 2)) {
  916. tcpreplay_seterr(ctx, "%s", "Dual file mode requires 2 or more pcap files");
  917. ret = -1;
  918. goto out;
  919. }
  920. if (ctx->options->source_cnt % 2 != 0) {
  921. tcpreplay_seterr(ctx, "%s", "Dual file mode requires an even number of pcap files");
  922. ret = -1;
  923. goto out;
  924. }
  925. }
  926. if (ctx->options->dualfile && ctx->options->cachedata != NULL) {
  927. tcpreplay_seterr(ctx, "%s", "Can't use dual file mode and tcpprep cache file together");
  928. ret = -1;
  929. goto out;
  930. }
  931. if ((ctx->options->dualfile || ctx->options->cachedata != NULL) &&
  932. ctx->options->intf2_name == NULL) {
  933. tcpreplay_seterr(ctx, "%s", "dual file mode and tcpprep cache files require two interfaces");
  934. }
  935. #ifndef HAVE_SELECT
  936. if (ctx->options->accurate == accurate_select) {
  937. tcpreplay_seterr(ctx, "%s", "tcpreplay_api not compiled with select support");
  938. ret = -1;
  939. goto out;
  940. }
  941. #endif
  942. if ((intname = get_interface(ctx->intlist, ctx->options->intf1_name)) == NULL) {
  943. if (!strncmp(OPT_ARG(INTF1), "netmap:", 7) || !strncmp(OPT_ARG(INTF1), "vale", 4))
  944. tcpreplay_seterr(ctx, "Unable to connect to netmap interface %s. Ensure netmap module is installed (see INSTALL).",
  945. OPT_ARG(INTF1));
  946. else
  947. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF1));
  948. ret = -1;
  949. goto out;
  950. }
  951. /* open interfaces for writing */
  952. if ((ctx->intf1 = sendpacket_open(ctx->options->intf1_name, ebuf, TCPR_DIR_C2S, ctx->sp_type, ctx)) == NULL) {
  953. tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf1_name, ebuf);
  954. ret = -1;
  955. goto out;
  956. }
  957. int1dlt = sendpacket_get_dlt(ctx->intf1);
  958. if (ctx->options->intf2_name != NULL) {
  959. if ((intname = get_interface(ctx->intlist, ctx->options->intf2_name)) == NULL) {
  960. tcpreplay_seterr(ctx, "Invalid interface name/alias: %s", OPT_ARG(INTF2));
  961. ret = -1;
  962. goto out;
  963. }
  964. /* open interfaces for writing */
  965. if ((ctx->intf2 = sendpacket_open(ctx->options->intf2_name, ebuf, TCPR_DIR_C2S, ctx->sp_type, ctx)) == NULL) {
  966. tcpreplay_seterr(ctx, "Can't open %s: %s", ctx->options->intf2_name, ebuf);
  967. ret = -1;
  968. goto out;
  969. }
  970. int2dlt = sendpacket_get_dlt(ctx->intf2);
  971. if (int2dlt != int1dlt) {
  972. tcpreplay_seterr(ctx, "DLT type mismatch for %s (%s) and %s (%s)",
  973. ctx->options->intf1_name, pcap_datalink_val_to_name(int1dlt),
  974. ctx->options->intf2_name, pcap_datalink_val_to_name(int2dlt));
  975. ret = -1;
  976. goto out;
  977. }
  978. }
  979. /*
  980. * Setup up the file cache, if required
  981. */
  982. if (ctx->options->preload_pcap) {
  983. /* Initialise each of the file cache structures */
  984. for (i = 0; i < ctx->options->source_cnt; i++) {
  985. ctx->options->file_cache[i].index = i;
  986. ctx->options->file_cache[i].cached = FALSE;
  987. ctx->options->file_cache[i].packet_cache = NULL;
  988. }
  989. }
  990. out:
  991. safe_free(ebuf);
  992. return ret;
  993. }
  994. static bool apply_loop_delay(tcpreplay_t *ctx);
  995. /**
  996. * \brief sends the traffic out the interfaces
  997. *
  998. * Designed to be called in a separate thread if you need to. Blocks until
  999. * the replay is complete or you call tcpreplay_abort() in another thread.
  1000. */
  1001. int
  1002. tcpreplay_replay(tcpreplay_t *ctx)
  1003. {
  1004. int rcode;
  1005. COUNTER loop, total_loops;
  1006. assert(ctx);
  1007. if (!ctx->options->source_cnt) {
  1008. tcpreplay_seterr(ctx, "invalid source count: %d", ctx->options->source_cnt);
  1009. return -1;
  1010. }
  1011. if (ctx->options->dualfile && ctx->options->source_cnt < 2) {
  1012. tcpreplay_seterr(ctx, "invalid dualfile source count: %d", ctx->options->source_cnt);
  1013. return -1;
  1014. }
  1015. init_timestamp(&ctx->stats.start_time);
  1016. init_timestamp(&ctx->stats.time_delta);
  1017. init_timestamp(&ctx->stats.end_time);
  1018. init_timestamp(&ctx->stats.pkt_ts_delta);
  1019. init_timestamp(&ctx->stats.last_print);
  1020. ctx->running = true;
  1021. total_loops = ctx->options->loop;
  1022. loop = 0;
  1023. /* main loop, when not looping forever (or until abort) */
  1024. if (ctx->options->loop > 0) {
  1025. while (ctx->options->loop-- && !ctx->abort) { /* limited loop */
  1026. ++loop;
  1027. if (ctx->options->stats == 0) {
  1028. if (!ctx->unique_iteration || loop == ctx->unique_iteration)
  1029. printf("Loop " COUNTER_SPEC " of " COUNTER_SPEC "...\n",
  1030. loop, total_loops);
  1031. else
  1032. printf("Loop " COUNTER_SPEC " of " COUNTER_SPEC " (" COUNTER_SPEC " unique)...\n",
  1033. loop, total_loops,
  1034. ctx->unique_iteration);
  1035. }
  1036. if ((rcode = tcpr_replay_index(ctx)) < 0)
  1037. return rcode;
  1038. if (ctx->options->loop > 0) {
  1039. if (apply_loop_delay(ctx))
  1040. get_current_time(&ctx->stats.end_time);
  1041. if (ctx->options->stats == 0) {
  1042. packet_stats(&ctx->stats);
  1043. }
  1044. }
  1045. #ifdef HAVE_LIBXDP
  1046. sendpacket_t *sp = ctx->intf1;
  1047. if (sp->handle_type == SP_TYPE_LIBXDP) {
  1048. sp->xsk_info->tx.cached_prod = 0;
  1049. sp->xsk_info->tx.cached_cons = sp->tx_size;
  1050. }
  1051. #endif
  1052. }
  1053. } else {
  1054. while (!ctx->abort) { /* loop forever unless user aborts */
  1055. ++loop;
  1056. if (ctx->options->stats == 0) {
  1057. if (!ctx->unique_iteration || loop == ctx->unique_iteration)
  1058. printf("Loop " COUNTER_SPEC "...\n", loop);
  1059. else
  1060. printf("Loop " COUNTER_SPEC " (" COUNTER_SPEC " unique)...\n", loop,
  1061. ctx->unique_iteration);
  1062. }
  1063. if ((rcode = tcpr_replay_index(ctx)) < 0)
  1064. return rcode;
  1065. if (apply_loop_delay(ctx))
  1066. get_current_time(&ctx->stats.end_time);
  1067. if (ctx->options->stats == 0 && !ctx->abort)
  1068. packet_stats(&ctx->stats);
  1069. }
  1070. }
  1071. ctx->running = false;
  1072. if (ctx->options->stats >= 0) {
  1073. char buf[64];
  1074. if (format_date_time(&ctx->stats.end_time, buf, sizeof(buf)) > 0)
  1075. printf("Test complete: %s\n", buf);
  1076. }
  1077. return 0;
  1078. }
  1079. /**
  1080. * \brief Abort the tcpreplay_replay execution.
  1081. *
  1082. * This might take a little while since tcpreplay_replay() only checks this
  1083. * once per packet (sleeping between packets can cause delays), however,
  1084. * this function returns once the signal has been sent and does not block
  1085. */
  1086. int
  1087. tcpreplay_abort(tcpreplay_t *ctx)
  1088. {
  1089. assert(ctx);
  1090. ctx->abort = true;
  1091. printf("sendpacket_abort\n");
  1092. if (ctx->intf1 != NULL)
  1093. sendpacket_abort(ctx->intf1);
  1094. if (ctx->intf2 != NULL)
  1095. sendpacket_abort(ctx->intf2);
  1096. return 0;
  1097. }
  1098. /**
  1099. * \brief Temporarily suspend tcpreplay_replay()
  1100. *
  1101. * This might take a little while since tcpreplay_replay() only checks this
  1102. * once per packet (sleeping between packets can cause delays), however,
  1103. * this function returns once the signal has been sent and does not block
  1104. *
  1105. * Note that suspending a running context can create odd timing
  1106. */
  1107. int
  1108. tcpreplay_suspend(tcpreplay_t *ctx)
  1109. {
  1110. assert(ctx);
  1111. ctx->suspend = true;
  1112. return 0;
  1113. }
  1114. /**
  1115. * \brief Restart tcpreplay_replay() after suspend
  1116. *
  1117. * Causes the worker thread to restart sending packets
  1118. */
  1119. int
  1120. tcpreplay_restart(tcpreplay_t *ctx)
  1121. {
  1122. assert(ctx);
  1123. ctx->suspend = false;
  1124. return 0;
  1125. }
  1126. /**
  1127. * \brief Tells you if the given tcpreplay context is currently suspended
  1128. *
  1129. * Suspended == running, but not sending packets
  1130. */
  1131. bool
  1132. tcpreplay_is_suspended(tcpreplay_t *ctx)
  1133. {
  1134. assert(ctx);
  1135. return ctx->suspend;
  1136. }
  1137. /**
  1138. * \brief Tells you if the tcpreplay context is running (not yet finished)
  1139. *
  1140. * Returns true even if it is suspended
  1141. */
  1142. bool
  1143. tcpreplay_is_running(tcpreplay_t *ctx)
  1144. {
  1145. assert(ctx);
  1146. return ctx->running;
  1147. }
  1148. /**
  1149. * \brief returns the current statistics during or after a replay
  1150. *
  1151. * For performance reasons, I don't bother to put a mutex around this and you
  1152. * don't need to either. Just realize that your values may be off by one until
  1153. * tcreplay_replay() returns.
  1154. */
  1155. const tcpreplay_stats_t *
  1156. tcpreplay_get_stats(tcpreplay_t *ctx)
  1157. {
  1158. const tcpreplay_stats_t *ptr;
  1159. assert(ctx);
  1160. /* copy stats over so they don't change while caller is using the buffer */
  1161. memcpy(&ctx->static_stats, &ctx->stats, sizeof(tcpreplay_stats_t));
  1162. ptr = &ctx->static_stats;
  1163. return ptr;
  1164. }
  1165. /**
  1166. * \brief returns the current number of sources/files to be sent
  1167. */
  1168. int
  1169. tcpreplay_get_source_count(tcpreplay_t *ctx)
  1170. {
  1171. assert(ctx);
  1172. return ctx->options->source_cnt;
  1173. }
  1174. /**
  1175. * \brief Returns the current source id being replayed
  1176. */
  1177. int
  1178. tcpreplay_get_current_source(tcpreplay_t *ctx)
  1179. {
  1180. assert(ctx);
  1181. return ctx->current_source;
  1182. }
  1183. /* vim: set tabstop=8 expandtab shiftwidth=4 softtabstop=4: */
  1184. /**
  1185. * \brief Sets printing of flow statistics
  1186. */
  1187. int tcpreplay_set_flow_stats(tcpreplay_t *ctx, bool value)
  1188. {
  1189. assert(ctx);
  1190. ctx->options->flow_stats = value;
  1191. return 0;
  1192. }
  1193. /**
  1194. * \brief Sets the flow expiry in seconds
  1195. */
  1196. int tcpreplay_set_flow_expiry(tcpreplay_t *ctx, int value)
  1197. {
  1198. assert(ctx);
  1199. ctx->options->flow_expiry = value;
  1200. return 0;
  1201. }
  1202. /**
  1203. * \brief Get whether to printof flow statistics
  1204. */
  1205. bool tcpreplay_get_flow_stats(tcpreplay_t *ctx)
  1206. {
  1207. assert(ctx);
  1208. return ctx->options->flow_stats;
  1209. }
  1210. /**
  1211. * \brief Gets the flow expiry in seconds
  1212. */
  1213. int tcpreplay_get_flow_expiry(tcpreplay_t *ctx)
  1214. {
  1215. assert(ctx);
  1216. return ctx->options->flow_expiry;
  1217. }
  1218. bool
  1219. apply_loop_delay(tcpreplay_t *ctx) {
  1220. if (!ctx->abort && ctx->options->loopdelay_ms > 0) {
  1221. usleep(ctx->options->loopdelay_ms * 1000);
  1222. return true;
  1223. }
  1224. if (!ctx->abort && ctx->options->loopdelay_ns > 0) {
  1225. struct timespec nap;
  1226. nap.tv_sec = 0;
  1227. nap.tv_nsec = ctx->options->loopdelay_ns;
  1228. nanosleep_sleep(NULL, &nap, &ctx->stats.end_time, NULL);
  1229. return true;
  1230. }
  1231. return false;
  1232. }
  1233. #ifdef HAVE_LIBXDP
  1234. void
  1235. delete_xsk_socket(struct xsk_socket *xsk)
  1236. {
  1237. size_t desc_sz = sizeof(struct xdp_desc);
  1238. struct xdp_mmap_offsets off;
  1239. socklen_t optlen;
  1240. int err;
  1241. if (!xsk) {
  1242. return;
  1243. }
  1244. optlen = sizeof(off);
  1245. err = getsockopt(xsk->fd, SOL_XDP, XDP_MMAP_OFFSETS, &off, &optlen);
  1246. if (!err) {
  1247. if (xsk->rx) {
  1248. munmap(xsk->rx->ring - off.rx.desc, off.rx.desc + xsk->config.rx_size * desc_sz);
  1249. }
  1250. if (xsk->tx) {
  1251. munmap(xsk->tx->ring - off.tx.desc, off.tx.desc + xsk->config.tx_size * desc_sz);
  1252. }
  1253. }
  1254. close(xsk->fd);
  1255. }
  1256. void
  1257. free_umem_and_xsk(sendpacket_t *sp)
  1258. {
  1259. xsk_umem__delete(sp->xsk_info->umem->umem);
  1260. delete_xsk_socket(sp->xsk_info->xsk);
  1261. }
  1262. #endif /*HAVE_LIBXDP*/