replay_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/replay/replay_example.c Source File
replay_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  * @example net/replay/replay_example.c
45  * @section replay_example_description Description
46  *
47  * This source file is an example of how to replay a capture file onto
48  * a port using NTAPI.
49  *
50  * The following NTAPI functions are used:
51  * - @ref NT_Init()
52  * - @ref NT_InfoOpen
53  * - @ref NT_InfoRead
54  * - @ref NT_InfoClose
55  * - @ref NT_NetFileOpen()
56  * - @ref NT_NetTxOpen()
57  * - @ref NT_NTPL()
58  * - @ref NT_NetFileGet()
59  * - @ref NT_NetTxGet()
60  * - @ref NT_NET_GET_SEGMENT_PTR()
61  * - @ref NT_NET_GET_SEGMENT_LENGTH()
62  * - @ref NT_NetTxRelease()
63  * - @ref NT_NetFileRelease()
64  * - @ref NT_NetFileClose()
65  * - @ref NT_NetTxClose()
66  * - @ref NT_ExplainError()
67  *
68  * @section replay_example_prerequisites Prerequisites
69  * - Capture file, capfile.ntcap, that has been captured with the @ref
70  * net/capture/capture_example.c "net/capture/capture_example.c" example.
71  * - The ntservice.ini must have at least one HostBuffersTx
72  * defined. Below is an example of a minimum ini-file. It will
73  * create a 32MB TX hostbuffer from NUMA node 0.
74  * @code
75  * [System]
76  * TimestampFormat = NATIVE
77  *
78  * [Adapter0]
79  * AdapterType = NT20E2
80  * BusId = 00:0a:00.00
81  * HostBuffersTx = [1,32,0]
82  * @endcode
83  *
84  * @section replay_example_flow Program flow
85  * @{
86  * The following is required to perform replay of a captured file:
87  * - \#include/nt.h - Applications/Tools only need to include @ref
88  * nt.h to obtain prototypes, macros etc. from NTAPI.
89  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
90  * library. @ref NTAPI_VERSION is a define that describes the version
91  * of the API described in the header files included by @ref
92  * nt.h. NT_Init() will ask the NTAPI library to convert return data
93  * to the @ref NTAPI_VERSION if possible. This will ensure that
94  * applications can run on NTAPI libraries of newer versions.
95  * - @ref NT_InfoOpen() - Open the information stream.
96  * - @ref NT_InfoRead() - Read the adapter information to check whether or not
97  * we are using absolut TX timing. The @ref NtTxTimingMethod_e "txTiming"
98  * tells whether relative or absolut TX timing is enabled.
99  * - @ref NT_InfoClose() - Close the information stream.
100  * - @ref NT_NetFileOpen() - Open the captured file and assign it to a stream.
101  * - @ref NT_NetTxOpen() - Open a hostbuffer than can transmit packets to port 0.
102  * - @ref NT_NetFileGet() - Get a segment from the file. This call will
103  * return @ref NT_SUCCESS upon return of a segment and
104  * @ref NT_STATUS_END_OF_FILE when there is no more segments
105  * avaialble. The latter will cause the example to exit.
106  * - @ref NT_NetTxGet() - Get an empty tx buffer. This will get a segment of the
107  * requested length from the hostbuffer that will be sent
108  * onto port 0 when the buffer is released.
109  * - @ref NT_NET_GET_SEGMENT_PTR() and @ref NT_NET_GET_SEGMENT_LENGTH() are used
110  * to tell where the segment data is located and how much there is.
111  * _nt_net_build_pkt_netbuf() and _nt_net_get_next_packet() are used to traverse
112  * packets inside a segment. This is usefull if ie. the timing of the packet
113  * transmit rate needs to be changed.
114  * - @ref NT_NetTxRelease() - Release the segment buffer. Once a tx
115  * buffer is released it will be transmitted according to the
116  * timestamps of the packets in the segment.
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  * - @ref NT_NetTxClose() - Close the TX stream.
120  *
121  *<hr>
122  * @section replay_example_code Code
123  * @}
124  */
125 
126 // Include this in order to access the Napatech API
127 #include <nt.h>
128 
129 #if defined(__linux__) || defined(__FreeBSD__)
130  #include <string.h> // memcpy
131 #endif
132 
133 // default setup
134 #define PORT 0
135 
136 int main(void)
137 {
138  int numPackets=0; // The number of packets replayed
139  int numBytes=0; // The number of bytes replayed
140  int firstPacket=1; // First packet to transmit
141  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
142  int status; // Status variable
143  NtNetStreamFile_t hNetFile; // Handle to the File stream
144  NtNetBuf_t hNetBufFile; // Net buffer container. Used to return segments from the file stream
145  NtNetStreamTx_t hNetTx; // Handle to the TX stream
146  NtNetBuf_t hNetBufTx; // Net buffer container. Used when getting a transmit buffer
147  NtInfoStream_t hInfo; // Handle to a info stream
148  NtInfo_t infoRead; // Buffer to hold data from infostream
149  struct NtNetBuf_s pktNetBuf; // Packet netbuf structure.
150  enum NtTxTimingMethod_e txTiming; // TX mode - Do we use absolut or relative mode
151  uint8_t adapterNo; // Adapter no
152 
153  // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
154  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
155  // Get the status code as text
156  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
157  fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
158  return -1;
159  }
160 
161  // Open the infostream.
162  if ((status = NT_InfoOpen(&hInfo, "replay")) != NT_SUCCESS) {
163  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
164  fprintf(stderr, "NT_InfoOpen() failed: %s\n", errorBuffer);
165  return -1;
166  }
167 
168  // Check whether or not TX is supported on the defined port
169  infoRead.cmd = NT_INFO_CMD_READ_PORT_V10;
170  infoRead.u.port_v10.portNo=PORT; // TX port is hardcoded to defined PORT
171  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
172  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
173  fprintf(stderr, "NT_InfoRead() failed: %s\n", errorBuffer);
174  NT_InfoClose(hInfo);
175  return -1;
176  }
177 
179  fprintf(stderr, "Transmit is not possible on the selected port %d\n",PORT);
180  NT_InfoClose(hInfo);
181  return -1;
182  }
183 
184  // Check whether or not absolut TX timing is supported
185  adapterNo = infoRead.u.port_v10.data.adapterNo;
186  infoRead.cmd = NT_INFO_CMD_READ_ADAPTER_V7;
187  infoRead.u.adapter_v7.adapterNo=adapterNo; // Adapter is derived from PORT of adapter
188  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
189  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
190  fprintf(stderr, "NT_InfoRead() failed: %s\n", errorBuffer);
191  NT_InfoClose(hInfo);
192  return -1;
193  }
194 
195  // Get the TX mode
196  txTiming = infoRead.u.adapter_v7.data.txTiming;
197 
198  NT_InfoClose(hInfo);
199 
200  // Open the capture file to replay (captured with the capture example)
201  if ((status = NT_NetFileOpen(&hNetFile, "FileStream", NT_NET_INTERFACE_SEGMENT, "capfile.ntcap")) != NT_SUCCESS) {
202  // Get the status code as text
203  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
204  fprintf(stderr, "NT_NetFileOpen() failed: %s\n", errorBuffer);
205  return -1;
206  }
207 
208  // Open a TX hostbuffer from TX host buffer pool on the NUMA node of the adapter with the defined PORT
209  if ((status = NT_NetTxOpen(&hNetTx, "TxStreamPort", 1ULL << PORT, NT_NETTX_NUMA_ADAPTER_HB, 0)) != NT_SUCCESS) {
210  // Get the status code as text
211  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
212  fprintf(stderr, "NT_NetTxOpen() failed: %s\n", errorBuffer);
213  return -1;
214  }
215 
216  // Get segments from the file and transmit them to defined PORT
217  while (1) {
218  printf("Getting segment.\n");
219  // Get the packet
220  if ((status = NT_NetFileGet(hNetFile, &hNetBufFile)) != NT_SUCCESS) {
221  if (status == NT_STATUS_END_OF_FILE) {
222  // The file has no more data
223  break;
224  }
225  // Get the status code as text
226  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
227  fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
228  return -1;
229  }
230  // Get a TX buffer for this segment
231  if ((status = NT_NetTxGet(hNetTx, &hNetBufTx, PORT, NT_NET_GET_SEGMENT_LENGTH(hNetBufFile), NT_NETTX_SEGMENT_OPTION_RAW, -1 /* wait forever */)) != NT_SUCCESS) {
232  // Get the status code as text
233  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
234  fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
235  return -1;
236  }
237  // Copy the segment into the TX buffer
238  memcpy(NT_NET_GET_SEGMENT_PTR(hNetBufTx), NT_NET_GET_SEGMENT_PTR(hNetBufFile), NT_NET_GET_SEGMENT_LENGTH(hNetBufFile));
239 
240  // Build a packet netbuf structure
241  _nt_net_build_pkt_netbuf(hNetBufTx, &pktNetBuf);
242 
243  if (firstPacket == 1) {
244  if (txTiming == NT_TX_TIMING_ABSOLUTE) {
245  // Absolute TX mode is supported.
246  // If transmit tx relative is disabled i.e. we are using absolut transmit and
247  // the txclock must be synched to the timestamp in the first packet.
248  NT_NET_SET_PKT_TXNOW((&pktNetBuf), 0); // Wait for tx delay before the packet is sent
249  NT_NET_SET_PKT_TXSETCLOCK((&pktNetBuf), 1); // Synchronize tx clock to timestamp in first packet.
250  }
251  else {
252  // Legacy mode/Relative tx timing.
253  // First packet must be sent with txnow=1
254  NT_NET_SET_PKT_TXNOW((&pktNetBuf), 1); // Send the first packet now
255  }
256  firstPacket = 0;
257  }
258 
259  // Optional step. Here all packets are inspected before sent
260  if (NT_NET_GET_SEGMENT_LENGTH(hNetBufTx)) {
261  do {
262  // Just count the amount of packets and wire length
263  numPackets++;
264  numBytes+=NT_NET_GET_PKT_WIRE_LENGTH((&pktNetBuf));
265  } while (_nt_net_get_next_packet(hNetBufTx,
266  NT_NET_GET_SEGMENT_LENGTH(hNetBufTx),
267  &pktNetBuf)>0);
268  }
269  // Release the TX buffer and the packets within the segment will be transmitted
270  if ((status = NT_NetTxRelease(hNetTx, hNetBufTx)) != NT_SUCCESS) {
271  // Get the status code as text
272  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
273  fprintf(stderr, "NT_NetTxRelease() failed: %s\n", errorBuffer);
274  return -1;
275  }
276  // Release the file packet
277  if ((status = NT_NetFileRelease(hNetFile, hNetBufFile)) != NT_SUCCESS) {
278  // Get the status code as text
279  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
280  fprintf(stderr, "NT_NetFileRelease() failed: %s\n", errorBuffer);
281  return -1;
282  }
283  }
284 
285  // Close the file stream
286  NT_NetFileClose(hNetFile);
287 
288  // Close the TX stream
289  NT_NetTxClose(hNetTx);
290 
291  printf("Done: %d packets %d bytes has been replayed\n", numPackets, numBytes);
292  return 0;
293 }