replayfilewithtimestampinject_example.c Source File

Reference Documentation

Platform
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.15
Napatech Software Suite: examples/net/replayfilewithtimestampinject/replayfilewithtimestampinject_example.c Source File
replayfilewithtimestampinject_example.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2025 Napatech A/S. All Rights Reserved.
4  *
5  * 1. Copying, modification, and distribution of this file, or executable
6  * versions of this file, is governed by the terms of the Napatech Software
7  * license agreement under which this file was made available. If you do not
8  * agree to the terms of the license do not install, copy, access or
9  * otherwise use this file.
10  *
11  * 2. Under the Napatech Software license agreement you are granted a
12  * limited, non-exclusive, non-assignable, copyright license to copy, modify
13  * and distribute this file in conjunction with Napatech SmartNIC's and
14  * similar hardware manufactured or supplied by Napatech A/S.
15  *
16  * 3. The full Napatech Software License Agreement is included in this
17  * distribution, please see "NA-0009 Software License Agreement.pdf"
18  *
19  * 4. Redistributions of source code must retain this copyright notice,
20  * list of conditions and the following disclaimer.
21  *
22  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
23  * IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
24  * IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
25  * FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
26  * APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
27  * OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
28  * INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
29  * LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
30  * BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
31  * OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
32  * SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
33  * THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
34  * OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
36  * THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
37  * INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
38  *
39  *
40 
41  */
42 
43 /**
44  *
45  * @example net/replayfilewithtimestampinject/replayfilewithtimestampinject_example.c
46  *
47  * @section replayfilewithtimestampinject_example_description Description
48  *
49  * This source file is an example of how to read a capture file using NTAPI
50  * and transmit the packet using a dynamic descriptor which makes it possible
51  * to inject the transmitted timestamp in the packet.
52  *
53  * This example make use of the following settings in ntservice.ini
54  *
55  * TimestampFormat = UNIX_NS
56  *
57  * TimestampInjectStaticOffset = 0
58  *
59  * TimestampInjectDynamicOffset = TSI_DYN_SOF
60  *
61  * PacketDescriptor = NT
62  *
63  *
64  * The NT_NetFile...() functions does not require NTservice to be running.
65  *
66  * The following NTAPI functions are used:
67  * - @ref NT_ExplainError()
68  * - @ref NT_Init()
69  * - @ref NT_NetFileClose()
70  * - @ref NT_NetFileGet()
71  * - @ref NT_NetFileOpen()
72  * - @ref NT_NetFileRelease()
73  * - @ref NT_NET_GET_PKT_DESCR_PTR_DYN3()
74  * - @ref NT_NET_GET_PKT_L2_PTR()
75  * - @ref NT_NET_GET_PKT_WIRE_LENGTH()
76  * - @ref NT_NetTxClose()
77  * - @ref NT_NETTX_DESCRIPTOR_MODE_DYN3
78  * - @ref NT_NetTxGet()
79  * - @ref NT_NETTX_NUMA_ADAPTER_HB
80  * - @ref NT_NetTxOpen_Attr
81  * - @ref NT_NetTxOpenAttrSetDescriptorPosChecksumCmd()
82  * - @ref NT_NetTxOpenAttrSetDescriptorPosFrameType()
83  * - @ref NT_NetTxOpenAttrSetMinHostbufferSize()
84  * - @ref NT_NetTxOpenAttrSetName()
85  * - @ref NT_NetTxOpenAttrSetPortMask()
86  * - @ref NT_NetTxOpenAttrSetTxtDescriptorPosFcs()
87  * - @ref NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInject()
88  * - @ref NT_NetTxOpen()
89  * - @ref NT_NetTxRelease()
90 
91 
92  *
93  * @section replayfilewithtimestampinject_example_prerequisites Prerequisites
94  *
95  * - Capture file, that has been captured with the @ref
96  * net/capture/capture_example.c "net/capture/capture_example.c" example.
97  *
98  * - The capture filename should be given as first argument to this example.
99  *
100  * @section replayfilewithtimestampinject_example_flow Program flow
101  * @{
102  * The following is required to perform replay of a captured file
103  *
104  * - \#include/nt.h - Applications/Tools only need to include @ref nt.h
105  * to obtain prototypes, macros etc. from NTAPI.
106  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
107  * library. @ref NTAPI_VERSION is a define that describes the version
108  * of the API described in the header files included by @ref
109  * nt.h. NT_Init() will ask the NTAPI library to convert return data
110  * to the @ref NTAPI_VERSION if possible. This will ensure that
111  * applications can run on NTAPI libraries of newer versions.
112  * - @ref NT_NetFileOpen() - Open the captured file and assign it to a stream.
113  * - @ref NT_NetFileGet() - Get a segment from the file. This call will
114  * return @ref NT_SUCCESS upon return of a segment and
115  * @ref NT_STATUS_END_OF_FILE when there is no more segments
116  * avaialble. The latter will cause the example to exit.
117  * - @ref NT_NetFileRelease() - Release the segment from the file stream.
118  * - @ref NT_NetFileClose() - Close the file stream when no more segments can be found.
119  *
120  *<hr>
121  *
122  * @section replayfilewithtimestampinject_example_code Code
123  * @}
124  *
125  */
126 
127 // Include this in order to access the Napatech API
128 #include <nt.h>
129 #include <argparse.h>
130 
131 #define PORT 0
132 
133 // The struct below represents the TX dynamic descriptor
134 // used by this application
135 //
136 // The struct is based on a copy of Dynamic descriptor 3
137 // It is modified with the location of the command bits
138 // time stamp inject handling and FCS handling.
139 //
140 // This example uses 3 bits of the color_hi field
141 // for these command bits. In other words - the
142 // normal color_hi:28 has been replaced by the
143 // 3 command bits and a color_hi_unused:25
144 //
146  uint64_t capLength:14;
147  uint64_t wireLength:14;
148  uint64_t color_lo:14;
149  uint64_t rxPort:6;
150  uint64_t descrFormat:8;
151  uint64_t descrLength:6;
152  uint64_t tsColor:1;
153  uint64_t ntDynDescr:1;
154  uint64_t timestamp;
155  uint64_t tsiCmd:1; // Timestamp inject command, 1 bit starting at bit offset 128
156  uint64_t fcsCmd:2; // FCS command, 2 bits starting at bit offset 129
157  uint64_t color_hi_unused:25; // The remaing 25 unused bits of color_hi
158  uint64_t offset0:10;
159  uint64_t offset1:10;
160 };
161 
162 // Time stamp inject command bit values
163 const uint64_t NO_TS_INJECT = 0;
164 const uint64_t TS_INJECT = 1;
165 
166 // FCS command bits values
167 const uint64_t FCS_GOOD = 0;
168 const uint64_t FCS_BAD = 1;
169 const uint64_t FCS_RESERVED = 2;
170 const uint64_t FCS_UNCHANGED = 3;
171 
172 static const char *usageText[] = {
173  "USAGE: replayfilewithtimestampinject_example <nt3gd_capture_filename>\n"
174  "Commands:\n",
175  NULL};
176 
177 
178 /**
179  * Table of valid options.
180  */
182  OPT_HELP(),
183  OPT_END(),
184 };
185 
186 
187 // printError is a simple convenience function for printing an NTAPI error
188 // message to stderr.
189 static void printError(const char *prefix, int errorCode) {
190  char errorBuffer[NT_ERRBUF_SIZE];
191  NT_ExplainError(errorCode, errorBuffer, sizeof errorBuffer);
192  fprintf(stderr, "%s: %s\n", prefix, errorBuffer);
193 }
194 
195 
196 int main(int argc, const char** argv) {
197  int status; // Status variable
198  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
199  int numPackets = 0; // The number of packets replayed
200  size_t numBytes = 0; // The number of bytes replayed
201  size_t pktLen = 0; // packet lenght
202  int option;
203  const char* ntcap_filename = NULL;
204  NtNetStreamFile_t hNetFile; // Handle to the File stream
205  NtNetBuf_t hNetBufFile; // Net buffer container. Used to return segments from the file stream
206  struct argparse argparse;
207 
208  int running = 1;
209 
210  argparse_init(&argparse, arg_options, usageText, 0);
211  option = argparse_parse(&argparse, argc, argv);
212 
213  if ((option >= 1) && (argv[0] != NULL)) {
214  ntcap_filename = argv[0];
215  } else {
216  argparse_usage(&argparse);
217  exit(0);
218  }
219 
220  // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
221  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
222  if ( status == NT_ERROR_NT_SERVICE_NOT_STARTED) {
223  printf("NOTE: NT service is not started.\n");
224  } else {
225  // Get the status code as text
226  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
227  fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
228  return -1;
229  }
230  }
231 
232  // Open the capture file to replay (captured with the capture example)
233  if ((status = NT_NetFileOpen(&hNetFile, "FileStream", NT_NET_INTERFACE_PACKET, ntcap_filename)) != NT_SUCCESS) {
234  // Get the status code as text
235  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
236  fprintf(stderr, "NT_NetFileOpen() failed: %s\n", errorBuffer);
237  return -1;
238  }
239 
240  // Open a TX stream
241  NtNetStreamTx_t hNetTx;
242 
243  status = NT_NetTxOpen(&hNetTx, "transmit_packet_example_txstream",
244  1ULL << PORT, NT_NETTX_NUMA_ADAPTER_HB, 0);
245  if (status != NT_SUCCESS) {
246  printError("NT_NetTxOpen() failed", status);
247  return -1;
248  }
249 
250  NtNetTxAttr_t txAttr;
251 
252  NT_NetTxOpenAttrInit(&txAttr);
253  NT_NetTxOpenAttrSetName(&txAttr, "Time stamp Inject and FCS example");
254  NT_NetTxOpenAttrSetPortMask(&txAttr, (uint64_t)(1U << PORT));
257 
258  // Set the position of the various descriptor command
259  // in accordance with struct Dyn3_tx_descriptor
260  status = NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInject(&txAttr, true, 128);
261  if (status != NT_SUCCESS) {
262  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
263  fprintf(stderr, "NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInjectCmd failed: %s\n", errorBuffer);
264  exit(1);
265  }
266 
267  status = NT_NetTxOpenAttrSetTxtDescriptorPosFcs(&txAttr, true, 129);
268  if (status != NT_SUCCESS) {
269  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
270  fprintf(stderr, "NT_NetTxOpenAttrSetTxtDescriptorPosFcs failed: %s\n", errorBuffer);
271  exit(1);
272  }
273 
274  // Open the TX network stream
275  status = NT_NetTxOpen_Attr(&hNetTx, &txAttr);
276  if (status != NT_SUCCESS) {
277  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
278  fprintf(stderr, "NT_NetTxOpen() failed: %s\n", errorBuffer);
279  exit(1);
280  }
281 
282  NtNetBuf_t hNetBufTx;
283  // Get packets from the file - update counters
284  while (running) {
285  // Get the packet
286  if ((status = NT_NetFileGet(hNetFile, &hNetBufFile)) != NT_SUCCESS) {
287  if (status == NT_STATUS_END_OF_FILE) {
288  // The file has no more data
289  break;
290  }
291  // Get the status code as text
292  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
293  fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
294  return -1;
295  }
296  pktLen = NT_NET_GET_PKT_WIRE_LENGTH((hNetBufFile));
297  printf("Fetched packet: #%d: packet length: %lu bytes - total capture length: %lu bytes\n", numPackets, pktLen, numBytes);
298 
299  // Get a packet TX buffer for this tx stream and port, without timeout
300  if ((status = NT_NetTxGet(hNetTx, &hNetBufTx, PORT, pktLen,
301  NT_NETTX_PACKET_OPTION_DYN, -1)) != NT_SUCCESS) {
302  printError("NT_NetTxGet() failed", status);
303  return -1;
304  }
305 
306  memcpy(NT_NET_GET_PKT_L2_PTR(hNetBufTx), NT_NET_GET_PKT_L2_PTR(hNetBufFile), pktLen);
307 
308  NtDyn3Descr_t* packet_ptr = NT_NET_GET_PKT_DESCR_PTR_DYN3(hNetBufTx);
309  struct Dyn3_tx_descriptor* overlay_ptr = (struct Dyn3_tx_descriptor*)(packet_ptr);
310 
311  overlay_ptr->tsiCmd = TS_INJECT & 0x01; // Set the time stamp inject command bits
312  overlay_ptr->fcsCmd = FCS_GOOD & 0x03; // Set the FCS command bits
313 
314  // Release the TX buffer and the packet will be transmitted
315  if ((status = NT_NetTxRelease(hNetTx, hNetBufTx)) != NT_SUCCESS) {
316  // Get the status code as text
317  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
318  fprintf(stderr, "NT_NetTxRelease() failed: %s\n", errorBuffer);
319  running = false;
320  }
321  numPackets++,
322  numBytes += pktLen;
323 
324  // Release the file packet
325  if ((status = NT_NetFileRelease(hNetFile, hNetBufFile)) != NT_SUCCESS) {
326  // Get the status code as text
327  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
328  fprintf(stderr, "NT_NetFileRelease() failed: %s\n", errorBuffer);
329  running = false;
330  }
331  }
332 
333  // Close the TX stream
334  NT_NetTxClose(hNetTx);
335 
336  // Close the file stream
337  NT_NetFileClose(hNetFile);
338 
339  printf("Done: %d packets %lu bytes has been read\n", numPackets, numBytes);
340  return 0;
341 }