transmit_packet_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/transmit_packet/transmit_packet_example.c Source File
transmit_packet_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/transmit_packet/transmit_packet_example.c
45  * @section transmit_packet_example_description Description
46  *
47  * This source file is an example of how to transmit packets using the packet
48  * interface in NTAPI. The example will transmit 2500000 packets with a size of
49  * 1024 bytes from port 0. The packet contains an incrementing 32bit pattern.
50  *
51  * The following NTAPI functions are used:
52  * - @ref NT_Init()
53  * - @ref NT_NetTxOpen()
54  * - @ref NT_NetTxGet()
55  * - @ref NT_NET_GET_PKT_L2_PTR()
56  * - @ref NT_NetTxRelease()
57  * - @ref NT_NetTxClose()
58  * - @ref NT_Done()
59  * - @ref NT_ExplainError()
60  *
61  * @section transmit_packet_example_prerequisites Prerequisites
62  * - The ntservice.ini must have at least one HostBuffersTx defined. Below is
63  * an example of a minimum ini-file. It will create a 4MB TX hostbuffer from
64  * NUMA node 0.
65  *
66  * @code
67  * [System]
68  * TimestampFormat = NATIVE
69  *
70  * [Adapter0]
71  * AdapterType = NT20E2
72  * BusId = 00:0a:00.00
73  * HostBuffersTx = [1,4,0]
74  * @endcode
75  *
76  * @section transmit_packet_example_flow Program flow
77  * @{
78  * The following is required to transmit packets:
79  * - \#include/nt.h - Applications/Tools only need to include @ref
80  * nt.h to obtain prototypes, macros etc. from NTAPI.
81  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
82  * library. @ref NTAPI_VERSION is a define that describes the version
83  * of the API described in the header files included by @ref
84  * nt.h. NT_Init() will ask the NTAPI library to convert return data
85  * to the @ref NTAPI_VERSION if possible. This will ensure that
86  * applications can run on NTAPI libraries of newer versions.
87  * - @ref NT_NetTxOpen() - Open a hostbuffer than can transmit packets to port 0.
88  * - @ref NT_NetTxGet() - Get an empty tx buffer. This will get a 296 byte
89  * wire length packet buffer that will be sent onto port 0 when
90  * released.
91  * - @ref NT_NET_GET_PKT_L2_PTR() is used to get the L2 pointer to the tx
92  * buffer, this is where the payload is placed.
93  * - @ref NT_NetTxRelease() - Release the tx packet buffer. Once a tx
94  * buffer is released it will be transmitted
95  * - @ref NT_NetTxClose() - Close the TX stream.
96  * - @ref NT_Done() - Close down the NTAPI library.
97  *
98  *<hr>
99  * @section transmit_packet_example_code Code
100  * @}
101  */
102 
103 // Include this in order to access the Napatech API
104 #include <nt.h>
105 
106 #ifdef WIN32
107  #include <windows.h>
108 #else
109  #include <unistd.h>
110 #endif
111 
112 // default TX packet test setup
113 #define PACKETS 2500000
114 #define PACKET_SIZE 1024 // Packet size to transmit (incl crc.)
115 #define PORT 0
116 
117 
118 static void msleep(unsigned ms)
119 {
120 #ifdef _WIN32
121  Sleep(ms);
122 #else
123  usleep(1000u * ms);
124 #endif
125 }
126 
127 // printError is a simple convenience function for printing an NTAPI error
128 // message to stderr.
129 static void printError(const char *prefix, int errorCode) {
130  char errorBuffer[NT_ERRBUF_SIZE];
131  NT_ExplainError(errorCode, errorBuffer, sizeof errorBuffer);
132  fprintf(stderr, "%s: %s\n", prefix, errorBuffer);
133 }
134 
135 int main(void)
136 {
137  //
138  // Initialize the API. This also checks if we are compatible with the
139  // installed library version.
140  //
141  int status;
142 
143  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
144  printError("NT_Init() failed", status);
145  return -1;
146  }
147 
148  //
149  // Open a TX stream
150  //
151  NtNetStreamTx_t hNetTx;
152 
153  status = NT_NetTxOpen(&hNetTx, "transmit_packet_example_txstream",
154  1ULL << PORT, NT_NETTX_NUMA_ANY_HB, 0);
155  if (status != NT_SUCCESS) {
156  printError("NT_NetTxOpen() failed", status);
157  return -1;
158  }
159 
160  //
161  // Retrieve a packet buffer, fill it, and repeat until we have transmitted
162  // the requested amount of packets.
163  //
164  printf("Commencing transmission\n");
165 
166  NtNetBuf_t hNetBufTx;
167  int numPackets;
168 
169  for (numPackets = 0; numPackets < PACKETS; numPackets++) {
170 
171  // Get a packet TX buffer for this tx stream and port, without timeout
172  if ((status = NT_NetTxGet(hNetTx, &hNetBufTx, PORT, PACKET_SIZE,
173  NT_NETTX_PACKET_OPTION_DEFAULT, -1)) != NT_SUCCESS) {
174  printError("NT_NetTxGet() failed", status);
175  return -1;
176  }
177 
178  // Fill the packet with an incrementing payload. Note that this will result
179  // in a garbage ethernet frame.
180  uint32_t *ptr = (uint32_t*)NT_NET_GET_PKT_L2_PTR(hNetBufTx);
181  for (uint32_t i = 0; i < PACKET_SIZE/4; i++) {
182  *(ptr+i) = i;
183  }
184 
185  // Release the TX buffer to transmit the packet.
186  if ((status = NT_NetTxRelease(hNetTx, hNetBufTx)) != NT_SUCCESS) {
187  printError("NT_NetTxRelease() failed", status);
188  return -1;
189  }
190  }
191 
192  //Wait until all packet have been delivered to the FPGA and this when all
193  //packets have left host memory
194  int timeOut = 0;
195 
196  while (true) {
197  if (timeOut >= 1000) { //Wait max 1 second
198  printError("Timeout waiting for data to be sent", NT_ERROR_OPERATION_TIMEOUT);
199  break;
200  }
201 
202  // Evaluate if hostbuffer contents have been delivered to FPGA
203  // This is used to detect when Tx data has left host memory
204  NtNetTx_t ntNetTx;
206  status = NT_NetTxRead(hNetTx, &ntNetTx);
207 
208  if (status != NT_SUCCESS) {
209  printError("NT_NetTxRead failed", status);
210  break;
211  }
212 
213  size_t nHbSizeTotal = ntNetTx.u.hbInfo.aHostBuffer[0].size;
214  size_t nHbSizeAvail = ntNetTx.u.hbInfo.aHostBuffer[0].available;
215  size_t nHbSizeRel = ntNetTx.u.hbInfo.aHostBuffer[0].released;
216  size_t nHbSizeDeq = ntNetTx.u.hbInfo.aHostBuffer[0].dequeued;
217 
218  if ((nHbSizeAvail == nHbSizeTotal) && (nHbSizeRel == 0) && (nHbSizeDeq == 0))
219  break;
220 
221  msleep(1); // Dont busy wait but sleep 1 ms
222  timeOut++;
223  };
224 
225  //printf("timeOut = %dms\n", timeOut); //Find timeout value
226  printf("Done: %d packets sent\n", numPackets);
227 
228  // Close the TX stream
229  NT_NetTxClose(hNetTx);
230 
231  // Close the API
232  NT_Done();
233 
234  return 0;
235 }