replay_example.c Source File

Reference Documentation

Platform
Intel® PAC
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.10
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 2023 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 "NP-0405 Napatech Software license
18  * agreement.pdf"
19  *
20  * 4. Redistributions of source code must retain this copyright notice,
21  * list of conditions and the following disclaimer.
22  *
23  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
24  * IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
25  * IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
26  * FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
27  * APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
28  * OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
29  * INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
30  * LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
31  * BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
32  * OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
33  * SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
34  * THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
35  * OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
37  * THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
38  * INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
39  *
40  *
41 
42  */
43 
44 /**
45  * @example net/replay/replay_example.c
46  * @section replay_example_description Description
47  *
48  * This source file is an example of how to replay a capture file onto
49  * a port using NTAPI.
50  *
51  * The following NTAPI functions are used:
52  * - @ref NT_Init()
53  * - @ref NT_InfoOpen
54  * - @ref NT_InfoRead
55  * - @ref NT_InfoClose
56  * - @ref NT_NetFileOpen()
57  * - @ref NT_NetTxOpen()
58  * - @ref NT_NTPL()
59  * - @ref NT_NetFileGet()
60  * - @ref NT_NetTxGet()
61  * - @ref NT_NET_GET_SEGMENT_PTR()
62  * - @ref NT_NET_GET_SEGMENT_LENGTH()
63  * - @ref NT_NetTxRelease()
64  * - @ref NT_NetFileRelease()
65  * - @ref NT_NetFileClose()
66  * - @ref NT_NetTxClose()
67  * - @ref NT_ExplainError()
68  *
69  * @section replay_example_prerequisites Prerequisites
70  * - Capture file, capfile.ntcap, that has been captured with the @ref
71  * net/capture/capture_example.c "net/capture/capture_example.c" example.
72  * - The ntservice.ini must have at least one HostBuffersTx
73  * defined. Below is an example of a minimum ini-file. It will
74  * create a 32MB TX hostbuffer from NUMA node 0.
75  * @code
76  * [System]
77  * TimestampFormat = NATIVE
78  *
79  * [Adapter0]
80  * AdapterType = NT20E2
81  * BusId = 00:0a:00.00
82  * HostBuffersTx = [1,32,0]
83  * @endcode
84  *
85  * @section replay_example_flow Program flow
86  * @{
87  * The following is required to perform replay of a captured file:
88  * - \#include/nt.h - Applications/Tools only need to include @ref
89  * nt.h to obtain prototypes, macros etc. from NTAPI.
90  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
91  * library. @ref NTAPI_VERSION is a define that describes the version
92  * of the API described in the header files included by @ref
93  * nt.h. NT_Init() will ask the NTAPI library to convert return data
94  * to the @ref NTAPI_VERSION if possible. This will ensure that
95  * applications can run on NTAPI libraries of newer versions.
96  * - @ref NT_InfoOpen() - Open the information stream.
97  * - @ref NT_InfoRead() - Read the adapter information to check whether or not
98  * we are using absolut TX timing. The @ref NtTxTimingMethod_e "txTiming"
99  * tells whether relative or absolut TX timing is enabled.
100  * - @ref NT_InfoClose() - Close the information stream.
101  * - @ref NT_NetFileOpen() - Open the captured file and assign it to a stream.
102  * - @ref NT_NetTxOpen() - Open a hostbuffer than can transmit packets to port 0.
103  * - @ref NT_NetFileGet() - Get a segment from the file. This call will
104  * return @ref NT_SUCCESS upon return of a segment and
105  * @ref NT_STATUS_END_OF_FILE when there is no more segments
106  * avaialble. The latter will cause the example to exit.
107  * - @ref NT_NetTxGet() - Get an empty tx buffer. This will get a segment of the
108  * requested length from the hostbuffer that will be sent
109  * onto port 0 when the buffer is released.
110  * - @ref NT_NET_GET_SEGMENT_PTR() and @ref NT_NET_GET_SEGMENT_LENGTH() are used
111  * to tell where the segment data is located and how much there is.
112  * _nt_net_build_pkt_netbuf() and _nt_net_get_next_packet() are used to traverse
113  * packets inside a segment. This is usefull if ie. the timing of the packet
114  * transmit rate needs to be changed.
115  * - @ref NT_NetTxRelease() - Release the segment buffer. Once a tx
116  * buffer is released it will be transmitted according to the
117  * timestamps of the packets in the segment.
118  * - @ref NT_NetFileRelease() - Release the segment from the file stream.
119  * - @ref NT_NetFileClose() - Close the file stream when no more segments can be found.
120  * - @ref NT_NetTxClose() - Close the TX stream.
121  *
122  *<hr>
123  * @section replay_example_code Code
124  * @}
125  */
126 
127 // Include this in order to access the Napatech API
128 #include <nt.h>
129 
130 #if defined(__linux__) || defined(__FreeBSD__)
131  #include <string.h> // memcpy
132 #endif
133 
134 // default setup
135 #define PORT 0
136 
137 int main(void)
138 {
139  int numPackets=0; // The number of packets replayed
140  int numBytes=0; // The number of bytes replayed
141  int firstPacket=1; // First packet to transmit
142  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
143  int status; // Status variable
144  NtNetStreamFile_t hNetFile; // Handle to the File stream
145  NtNetBuf_t hNetBufFile; // Net buffer container. Used to return segments from the file stream
146  NtNetStreamTx_t hNetTx; // Handle to the TX stream
147  NtNetBuf_t hNetBufTx; // Net buffer container. Used when getting a transmit buffer
148  NtInfoStream_t hInfo; // Handle to a info stream
149  NtInfo_t infoRead; // Buffer to hold data from infostream
150  struct NtNetBuf_s pktNetBuf; // Packet netbuf structure.
151  enum NtTxTimingMethod_e txTiming; // TX mode - Do we use absolut or relative mode
152  uint8_t adapterNo; // Adapter no
153 
154  // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
155  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
156  // Get the status code as text
157  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
158  fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
159  return -1;
160  }
161 
162  // Open the infostream.
163  if ((status = NT_InfoOpen(&hInfo, "replay")) != NT_SUCCESS) {
164  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
165  fprintf(stderr, "NT_InfoOpen() failed: %s\n", errorBuffer);
166  return -1;
167  }
168 
169  // Check whether or not TX is supported on the defined port
170  infoRead.cmd = NT_INFO_CMD_READ_PORT_V9;
171  infoRead.u.port_v9.portNo=PORT; // TX port is hardcoded to defined PORT
172  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
173  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
174  fprintf(stderr, "NT_InfoRead() failed: %s\n", errorBuffer);
175  NT_InfoClose(hInfo);
176  return -1;
177  }
178 
180  fprintf(stderr, "Transmit is not possible on the selected port %d\n",PORT);
181  NT_InfoClose(hInfo);
182  return -1;
183  }
184 
185  // Check whether or not absolut TX timing is supported
186  adapterNo = infoRead.u.port_v9.data.adapterNo;
187  infoRead.cmd = NT_INFO_CMD_READ_ADAPTER_V6;
188  infoRead.u.adapter_v6.adapterNo=adapterNo; // Adapter is derived from PORT of adapter
189  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
190  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
191  fprintf(stderr, "NT_InfoRead() failed: %s\n", errorBuffer);
192  NT_InfoClose(hInfo);
193  return -1;
194  }
195 
196  // Get the TX mode
197  txTiming = infoRead.u.adapter_v6.data.txTiming;
198 
199  NT_InfoClose(hInfo);
200 
201  // Open the capture file to replay (captured with the capture example)
202  if ((status = NT_NetFileOpen(&hNetFile, "FileStream", NT_NET_INTERFACE_SEGMENT, "capfile.ntcap")) != NT_SUCCESS) {
203  // Get the status code as text
204  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
205  fprintf(stderr, "NT_NetFileOpen() failed: %s\n", errorBuffer);
206  return -1;
207  }
208 
209  // Open a TX hostbuffer from TX host buffer pool on the NUMA node of the adapter with the defined PORT
210  if ((status = NT_NetTxOpen(&hNetTx, "TxStreamPort", 1ULL << PORT, NT_NETTX_NUMA_ADAPTER_HB, 0)) != NT_SUCCESS) {
211  // Get the status code as text
212  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
213  fprintf(stderr, "NT_NetTxOpen() failed: %s\n", errorBuffer);
214  return -1;
215  }
216 
217  // Get segments from the file and transmit them to defined PORT
218  while (1) {
219  printf("Getting segment.\n");
220  // Get the packet
221  if ((status = NT_NetFileGet(hNetFile, &hNetBufFile)) != NT_SUCCESS) {
222  if (status == NT_STATUS_END_OF_FILE) {
223  // The file has no more data
224  break;
225  }
226  // Get the status code as text
227  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
228  fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
229  return -1;
230  }
231  // Get a TX buffer for this segment
232  if ((status = NT_NetTxGet(hNetTx, &hNetBufTx, PORT, NT_NET_GET_SEGMENT_LENGTH(hNetBufFile), NT_NETTX_SEGMENT_OPTION_RAW, -1 /* wait forever */)) != NT_SUCCESS) {
233  // Get the status code as text
234  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
235  fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
236  return -1;
237  }
238  // Copy the segment into the TX buffer
239  memcpy(NT_NET_GET_SEGMENT_PTR(hNetBufTx), NT_NET_GET_SEGMENT_PTR(hNetBufFile), NT_NET_GET_SEGMENT_LENGTH(hNetBufFile));
240 
241  // Build a packet netbuf structure
242  _nt_net_build_pkt_netbuf(hNetBufTx, &pktNetBuf);
243 
244  if (firstPacket == 1) {
245  if (txTiming == NT_TX_TIMING_ABSOLUTE) {
246  // Absolute TX mode is supported.
247  // If transmit tx relative is disabled i.e. we are using absolut transmit and
248  // the txclock must be synched to the timestamp in the first packet.
249  NT_NET_SET_PKT_TXNOW((&pktNetBuf), 0); // Wait for tx delay before the packet is sent
250  NT_NET_SET_PKT_TXSETCLOCK((&pktNetBuf), 1); // Synchronize tx clock to timestamp in first packet.
251  }
252  else {
253  // Legacy mode/Relative tx timing.
254  // First packet must be sent with txnow=1
255  NT_NET_SET_PKT_TXNOW((&pktNetBuf), 1); // Send the first packet now
256  }
257  firstPacket = 0;
258  }
259 
260  // Optional step. Here all packets are inspected before sent
261  if (NT_NET_GET_SEGMENT_LENGTH(hNetBufTx)) {
262  do {
263  // Just count the amount of packets and wire length
264  numPackets++;
265  numBytes+=NT_NET_GET_PKT_WIRE_LENGTH((&pktNetBuf));
266  } while (_nt_net_get_next_packet(hNetBufTx,
267  NT_NET_GET_SEGMENT_LENGTH(hNetBufTx),
268  &pktNetBuf)>0);
269  }
270  // Release the TX buffer and the packets within the segment will be transmitted
271  if ((status = NT_NetTxRelease(hNetTx, hNetBufTx)) != NT_SUCCESS) {
272  // Get the status code as text
273  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
274  fprintf(stderr, "NT_NetTxRelease() failed: %s\n", errorBuffer);
275  return -1;
276  }
277  // Release the file packet
278  if ((status = NT_NetFileRelease(hNetFile, hNetBufFile)) != NT_SUCCESS) {
279  // Get the status code as text
280  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
281  fprintf(stderr, "NT_NetFileRelease() failed: %s\n", errorBuffer);
282  return -1;
283  }
284  }
285 
286  // Close the file stream
287  NT_NetFileClose(hNetFile);
288 
289  // Close the TX stream
290  NT_NetTxClose(hNetTx);
291 
292  printf("Done: %d packets %d bytes has been replayed\n", numPackets, numBytes);
293  return 0;
294 }