vlandemo_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/vlandemo/vlandemo_example.c Source File
vlandemo_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/vlandemo/vlandemo_example.c
45  * @section vlandemo_example_description Description
46  *
47  * INFO:
48  * - This is an 4GA inline example, which depends on the 4GA inline NTPL features.
49  * - The 3GA inline example can be found in examples/net/inline/.
50  *
51  * This source file is an example of how to implement a simple vlan tagging,
52  * using the 4GA Napatech inline application capabilities.
53  * The example will add a vlan tag to every received packet before forwarding.
54  * The example demonstrates how to utilize following features:
55  *
56  * RX:
57  *
58  * - a) set descriptor type = Dyn3
59  * - b) set descriptor length
60  *
61  * TX:
62  *
63  * - c) set descriptor type = Dyn
64  * - d) set TxPorts = fixed or dynamic range
65  * - e) discard RxCRC
66  * - f) set TxPortPos for dynamic range (within same adapter)
67  *
68  * The following NTAPI functions are used:
69  * - @ref NT_Init()
70  * - @ref NT_ConfigOpen()
71  * - @ref NT_InfoOpen()
72  * - @ref NT_NetRxOpen()
73  * - @ref NT_InfoRead()
74  * - @ref NT_NTPL()
75  * - @ref NT_NetRxGet()
76  * - @ref NT_NET_GET_PKT_CAP_LENGTH()
77  * - @ref NT_NET_GET_PKT_DESCR_LENGTH()
78  * - @ref NT_NET_GET_PKT_WIRE_LENGTH()
79  * - @ref NT_NET_GET_PKT_TIMESTAMP()
80  * - @ref NT_NET_GET_PKT_DESCR_PTR()
81  * - @ref NT_NET_SET_PKT_TXPORT()
82  * - @ref NT_NetRxRelease()
83  * - @ref NT_NetRxClose()
84  * - @ref NT_ConfigClose()
85  * - @ref NT_InfoClose()
86  * - @ref NT_ExplainError()
87  *
88  * @section vlandemo_example_prerequisites Prerequisites
89  * Any 4GA Napatech accelerator with 4GA FPGA inline support which was
90  * introduced with the HB2 release, FPGA-images: 200-95xx-08-xx,
91  * supporting minimum the NT_FEATURE_LEVEL_N_ANL9 feature set.
92  *
93  * Below is an example of an ini-file with the default setting for
94  * NT40E3_4_PTP (adapter 0).
95  * The default setting supports the 4GA TX inline feature.
96  *
97  * Establish optical cable loop from port 0 to port 1.
98  *
99  * Use the following NT tools and sequence to demo this vlan example:
100  * - 1) start ntservice: /opt/napatech3/bin/ntstart.sh
101  * - 2) start monitoring: /opt/napatech3/bin/monitoring
102  * - 3) start pktgen: /opt/napatech3/bin/pktgen -p 1 -s 1024 -n 0
103  * - 4) check on monitoring:
104  * - 10G TX traffic on port 1
105  * - 10G RX traffic on port 0
106  * - 5) start vlandemo: /opt/napatech3/examples/net/vlandemo/vlandemo_example
107  * - 6) check on monitoring:
108  * - 10G TX traffic on port 1 and port 0 (inline)
109  * - 10G RX traffic on port 0 and port 1 (inline)
110  *
111  * @code
112  * [System]
113  * HostBufferRefreshIntervalAll = default #
114  * LinkPropagationPortPairs = # [portA, portB], ...
115  * NumWorkerThreads = 3 # 1 .. 100
116  * SDRAMFillLevelWarning = 0 # X1, X2, X3, X4
117  * TimestampFormat = NATIVE_UNIX # NATIVE_UNIX* - PCAP - PCAP_NS
118  * TimestampMethod = EOF # UNKNOWN - EOF*
119  * TimeSyncOsTimeReference = None # None* - adapter-0 - adapter-1 - adapter-2 - adapter-3 - adapter-4 - adapter-5 - adapter-6 - adapter-7
120  *
121  * [Logging]
122  * LogBufferWrap = wrap # wrap* - nowrap
123  * LogFileName = /tmp/Log3G_%s.log # String
124  * LogMask = 7 # See ini-file help for information about possible values
125  * LogToFile = false # true/false
126  * LogToSystem = true # true/false
127  *
128  * [Adapter0]
129  * AdapterType = NT40E3_4_PTP # ...
130  * BusId = 0000:08:00.0 # NNNN:NN:NN.N
131  * DiscardSize = 16 # 16 .. 63
132  * HighFrequencySampling = DISABLE # DISABLE* - ENABLE
133  * HostBufferHandlerAffinity = -2 # -2 .. 39
134  * HostBufferPollInterval = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000
135  * HostBufferRefreshIntervalRx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500
136  * HostBufferRefreshIntervalTx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500
137  * HostBufferSegmentAlignmentRx = default # default* - none - 0 - 512 - 1024 - 2048 - 4096
138  * HostBufferSegmentSizeRx = default # default* - dynamic - 0 - 1 - 2 - 4
139  * HostBufferSegmentTimeOut = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000
140  * HostBuffersRx = [4,16,-1] # [x1, x2, x3], ...
141  * HostBuffersTx = [4,16,-1] # [x1, x2, x3], ...
142  * IfgMode = NS # NS* - BYTE
143  * KmTcamConfig = [2,4,0],[4,1,0] # [cnt, len, dualLookup], ...
144  * MaxFrameSize = 9018 # 1518 .. 10000
145  * NumaNode = -1 # -1 .. 16
146  * OnBoardMemorySplit = Even # Dynamic - Even* - Proportional
147  * PacketDescriptor = NT # PCAP - NT* - Ext9
148  * PortDisableMask = 0 # See ini-file help for information about possible values
149  * PortSpeedMultiRate = 10G, 10G, 10G, 10G # 1G - 10G*
150  * Profile = None # None* - Capture
151  * PtpDhcp = ENABLE # DISABLE - ENABLE*
152  * PtpMasterModeAllowed = DISABLE # DISABLE* - ENABLE
153  * PtpProfile = Default # Default* - Telecom - Power
154  * PtpUserDescription = Napatech adapter # String
155  * SofLinkSpeed = 10G # 100M - 1G - 10G
156  * TimeSyncConnectorExt1 = PpsIn # None - NttsIn* - PpsIn - NttsOut - PpsOut - RepeatInt1 - RepeatInt2
157  * TimeSyncConnectorInt1 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt2
158  * TimeSyncConnectorInt2 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt1
159  * TimeSyncHardReset = ENABLE # DISABLE - ENABLE*
160  * TimeSyncNTTSInSyncLimit = 5000 # 1 .. 4294967295
161  * TimeSyncOSInSyncLimit = 50000 # 1 .. 4294967295
162  * TimeSyncPPSInSyncLimit = 5000 # 1 .. 4294967295
163  * TimeSyncPTPInSyncLimit = 5000 # 1 .. 4294967295
164  * TimeSyncReferencePriority = Ext1, FreeRun # FreeRun* - PTP - Int1 - Int2 - Ext1 - OSTime
165  * TimeSyncTimeOffset = 0 # 0 .. 1000000
166  * TxTiming = RELATIVE # ABSOLUTE - RELATIVE*
167  * VXLANAltDestinationPorts = 4789,4789 # X1, X2
168  *
169  * @endcode
170  *
171  * @section vlandemo_example_flow Program flow
172  * @{
173  * The following is required to run in an inline scenario:
174  * - \#include/nt.h - Applications/Tools only need to include @ref
175  * nt.h to obtain prototypes, macros etc. from NTAPI.
176  * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI
177  * library. @ref NTAPI_VERSION is a define that describes the version
178  * of the API described in the header files included by @ref
179  * nt.h. NT_Init() will ask the NTAPI library to convert return data
180  * to the @ref NTAPI_VERSION if possible. This will ensure that
181  * applications can run on NTAPI libraries of newer versions.
182  * - To verify that the 4GA inline feature is supported, the
183  * Is4GATxSupported() local function open a info stream with
184  * @ref NT_InfoOpen() - to inquire the actual feature level with
185  * @ref NT_InfoRead() and check if we have minimum the ANL9. Next,
186  * - @ref NT_ConfigOpen() - Open a config stream in order to setup
187  * filter using the @ref NT_NTPL() command. Some conditional
188  * compile flags control various options:
189  * - ENABLE_DYNAMIC_TX_PORT - setup NTPL "TxPortPos=112" Dyn-desc
190  * - ENABLE_VLAN_TAGGING - enable VLAN tagging or packet forward
191  * - DISCARD_EVERY_SECOND_PACKET - discard every second packet
192  * - DISCARD_BY_WIRELEN - discard setting wirelen=0 or TXIGNORE=1
193  * - ENABLE_DYN_USER_DATA - extend Dyn3 descriptor for user data
194  * - @ref NT_NetRxOpen() - Open a stream. The stream ID(=1) must match
195  * the one used when creating the filter using the @ref NT_NTPL()
196  * command.
197  * - Having setup the TX inline NTPL configuration for stream ID(=1)
198  * and opened the RX stream ID(=1), the packet processing and
199  * forwarding loop is entered.
200  * Wait until we receive packets with @ref NT_NetRxGet(), which is
201  * called with a timeout of 1000ms and will return NT_STATUS_TIMEOUT
202  * in case nothing is received within 1000ms and will return
203  * NT_SUCCESS if something is returned. Return values different from
204  * that is an indication of an error.
205  * Packets are received with the Dyn3-descriptor as configured with NTPL.
206  * If ENABLE_VLAN_TAGGING is true, the required VLAN-tag space(=4 bytes)
207  * is allocated from the Dyn3-descriptor by subtracting 4 bytes from
208  * from the descriptor-length and adding 4-bytes to the wire-length along
209  * with the MAC-header move and VLAN-tag payload prepending.
210  * If DISCARD_EVERY_SECOND_PACKET is enabled, every second packet is discarded
211  * either by setting wirelen = 0 if DISCARD_BY_WIRELEN is enabled or
212  * by setting the TX IGNORE-bit to 1 with TxIgnorePos=42 . Next, the actual
213  * packet is forwarded with the @ref NT_NetRxRelease().
214  * - At program termination, the config stream is opened to clear the
215  * NTPL filter serup witth the "Delete=All" before the RX stream(=1)
216  * is closed the @ref NT_NetRxClose().
217  *
218  *<hr>
219  * @section vlandemo_example_code Code
220  * @}
221  *
222  */
223 
224 // Include this in order to access the Napatech API
225 #include <nt.h>
226 
227 #if defined(WIN32) || defined (WIN64)
228 #include <winsock2.h> /* htonl, htons */
229 #else
230 #include <arpa/inet.h> /* htonl, htons */
231 #include <signal.h>
232 #include <stdatomic.h>
233 #endif
234 
235 #include <stdlib.h>
236 
237 #if defined(WIN32) || defined(WIN64)
238  #define snprintf(dst, ...) _snprintf_s((dst), _countof(dst), __VA_ARGS__)
239  static volatile int appRunning = 1; // The application will run as long as appRunning == 1
240 #else
241  static atomic_int appRunning = 1; // The application will run as long as appRunning == 1
242 #endif
243 
244 //#define ENABLE_DYNAMIC_TX_PORT 1 // enable dynamic TX port
245 #define ENABLE_VLAN_TAGGING 1 // enable VLAN tagging of packets
246 //#define DISCARD_EVERY_SECOND_PACKET 1 // enable this to discard every second packet
247 #define DISCARD_BY_WIRELEN 1 // enable this to use wirelen=0 discard option (recommended)
248 //#define ENABLE_DYN_USER_DATA 1 // enable user data field along with Dyn3
249 
250 
251 /**
252  * The function called when user is pressing CTRL-C
253  */
254 #if defined(WIN32) || defined (WIN64)
255 static BOOL WINAPI StopApplication(int sig)
256 {
257  (void) sig;
258  appRunning = 0;
259  return TRUE;
260 }
261 #else
262 static void StopApplication(int sig)
263 {
264  if (sig == SIGINT)
265  appRunning = 0;
266 }
267 #endif
268 
269 
270 static int Is4GATxSupported(uint8_t portNo)
271 {
272  int status; // Status variable
273  uint8_t adapterNo;
274  NtInfoStream_t hInfo; // Handle to a info stream
275  NtInfo_t infoRead;
276  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
277 
278  if ((status = NT_InfoOpen(&hInfo, "Info")) != NT_SUCCESS) {
279  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
280  fprintf(stderr, "NT_InfoOpen failed: %s", errorBuffer);
281  return 0;
282  }
283 
284  // Get adapterNo of this TX port
285  (void)memset(&infoRead, 0, sizeof(NtInfo_t));
286  infoRead.cmd = NT_INFO_CMD_READ_PORT_V10;
287  infoRead.u.port_v10.portNo=portNo;
288  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
289  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
290  fprintf(stderr, "NT_InfoRead failed: %s", errorBuffer);
291  return 0;
292  }
293 
294  // Save adapter number of the TX port
295  adapterNo = infoRead.u.port_v10.data.adapterNo;
296 
297  // Get feature level of this adapter
298  (void)memset(&infoRead, 0, sizeof(NtInfo_t));
300  infoRead.u.adapter_v7.adapterNo = adapterNo;
301  if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) {
302  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
303  fprintf(stderr, "NT_InfoRead failed: %s", errorBuffer);
304  return 0;
305  }
306 
307  NT_InfoClose(hInfo);
308 
312  // 4GA adapters with ANL9 feature level support native TX with inline capabilities
313  // NOTE: 4GA adapters with ANL9 feature level doesn't support
314  // NT_NET_SET_PKT_DESCR_TYPE_EXT7 descriptor type
315  return 1;
316  }
317  printf("Adapter=%d, Port=%d, FeatureLevel=0x%x\n", adapterNo, portNo, infoRead.u.adapter_v7.data.featureLevel );
318  return 0;
319 }
320 
321 int main(void)
322 {
323  int status; // Status variable
324  char tmpBuffer[20]; // Buffer to build filter string
325  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
326  NtNetStreamRx_t hNetRx; // Handle to the RX stream
327  NtConfigStream_t hCfgStream; // Handle to a config stream
328  NtNtplInfo_t ntplInfo; // Return data structure from the NT_NTPL() call.
329  NtNetBuf_t hNetBuf; // Net buffer container. Packet data is returned in this when calling NT_NetRxGet().
330 #if ENABLE_VLAN_TAGGING
331  NtDyn3Descr_t *pDyn3; // dyn3 descriptor ref
332  uint8_t* pb;
333  struct {
334  uint16_t tpid;
335  uint16_t tci;
336  } vlan_tag = {htons(0x8100),htons(0x0001)}; // VLAN tag to prepend
337 #endif
338 #if DISCARD_EVERY_SECOND_PACKET
339  int discard = 0;
340 #endif
341 
342 #if ENABLE_DYNAMIC_TX_PORT
343  int dynamicTxPort = 0;
344 #endif
345 
346  // Register ctrl+c handler so we are able to stop again
347 #if defined(WIN32) || defined (WIN64)
348  SetConsoleCtrlHandler((PHANDLER_ROUTINE)StopApplication, TRUE);
349 #else
350  struct sigaction newaction; // Ctrl+c signal handler container
351  memset(&newaction, 0, sizeof(newaction));
352  newaction.sa_handler = StopApplication;
353  if (sigaction(SIGINT, &newaction, NULL) < 0) {
354  fprintf(stderr, "Failed to register SIGINT sigaction.\n");
355  exit(EXIT_FAILURE);
356  }
357 #endif
358 
359  // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
360  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
361  // Get the status code as text
362  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
363  fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
364  return -1;
365  }
366 
367  // Check if 4GA TX including inline capability is supported
368  if (!Is4GATxSupported(0)) {
369  printf("ERROR: 4GA TX inline is NOT supported !\n");
370  return -1;
371  }
372 
373  // Open a config stream to assign a filter to a stream ID.
374  if ((status = NT_ConfigOpen(&hCfgStream, "TestStream")) != NT_SUCCESS) {
375  // Get the status code as text
376  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
377  fprintf(stderr, "NT_ConfigOpen() failed: %s\n", errorBuffer);
378  return -1;
379  }
380 
381 #if DISCARD_EVERY_SECOND_PACKET
382 #if DISCARD_BY_WIRELEN
383  // Setup traffic to stream ID(=1) and Tx port = 0
384  if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
385 #else
386  // Setup traffic to stream ID(=1) and Tx port = 0, TX Ignore bit position = 42 (located in the rxPort field, which is not used by TX)
387  if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;TxIgnorePos=42;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
388 #endif
389 #else
390 #if ENABLE_DYNAMIC_TX_PORT
391  // Setup traffic to stream ID(=1), Tx port = 0..1 (within same adapter), RxCRC = false, TxPortPos=112 (to utilize macro)
392  if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=(0..1);RxCRC=False;TxPortPos=112;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
393 #else
394  // Setup traffic to stream ID(=1) and Tx port = 0
395  if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
396 #endif
397 #endif
398  // Get the status code as text
399  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
400  fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer);
401  fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode);
402  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]);
403  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]);
404  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]);
405  return -1;
406  }
407 
408  // Assign all traffic from port 0 to stream ID(=1)
409 #if ENABLE_DYN_USER_DATA
410  // Set descriptor length = 62 bytes to add user data field of 40 bytes
411  if ((status = NT_NTPL(hCfgStream, "Assign[StreamId=1;Descriptor=Dyn3,length=62] = Port == 0", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
412 #else
413  // Keep default Dyn3 descriptor length = 22 bytes
414  if ((status = NT_NTPL(hCfgStream, "Assign[StreamId=1;Descriptor=Dyn3] = Port == 0", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
415 #endif
416  // Get the status code as text
417  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
418  fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer);
419  fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode);
420  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]);
421  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]);
422  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]);
423  return -1;
424  }
425 
426  // Close the config stream
427  if ((status = NT_ConfigClose(hCfgStream)) != NT_SUCCESS) {
428  // Get the status code as text
429  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
430  fprintf(stderr, "NT_ConfigClose() failed: %s\n", errorBuffer);
431  return -1;
432  }
433 
434  // Open stat stream
435  NtStatStream_t hStat = NULL;
436  if ((status = NT_StatOpen(&hStat, "hStat")) != 0) {
437  fprintf(stderr, "Failed to create statistics stream: 0x%08X\n", status);
438  return -1;
439  }
440 
441  // Reset stats
442  static NtStatistics_t statSet;
444  statSet.u.query_v4.poll = 1;
445  statSet.u.query_v4.clear = 1;
446  if ((status = NT_StatRead(hStat, &statSet))) {
447  fprintf(stderr, "Failed resetting statistics: 0x%08X\n", status);
448  return -1;
449  }
450 
451  // Get a stream handle with the stream ID(=1). NT_NET_INTERFACE_PACKET specify that we will receive data in a packet based matter.
452  if ((status = NT_NetRxOpen(&hNetRx, "TestStream", NT_NET_INTERFACE_PACKET, 1, -1)) != NT_SUCCESS) {
453  // Get the status code as text
454  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
455  fprintf(stderr, "NT_NetRxOpen() failed: %s\n", errorBuffer);
456  return -1;
457  }
458 
459  // Optional step. Wait for the first packet that hit the NTPL assign command
460  while (appRunning == 1) {
461  if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) {
462  if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) {
463  // Timeouts are ok, we just need to wait a little longer for a packet
464  continue;
465  }
466  // Get the status code as text
467  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
468  fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer);
469  return -1;
470  }
471 
472  // We got a packet. Check if the timestamp is newer than when the NTPL assign command was applied
473  if (NT_NET_GET_PKT_TIMESTAMP(hNetBuf) > ntplInfo.ts) {
474  printf("First packet received: Capture length=%d, Descriptor length=%d, Wire length=%d\n", NT_NET_GET_PKT_CAP_LENGTH(hNetBuf), NT_NET_GET_PKT_DESCR_LENGTH(hNetBuf), NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf) );
475  break; // Break out, we have received a packet that is received after the NTPL assign command was applied
476  }
477 
478  // Release the packet, it is too "old".
479  if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) {
480  // Get the status code as text
481  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
482  fprintf(stderr, "NT_NetRxRelease() failed: %s\n", errorBuffer);
483  return -1;
484  }
485  }
486 
487  // Add VLAN tag and forward packet
488  uint64_t totPkts = 0;
489  uint64_t totBytes = 0;
490  while (appRunning == 1) { // start of packet processing loop
491  if (hNetBuf != NULL) {
492 
493 #if ENABLE_VLAN_TAGGING
494  // 1: Add VLAN tag
495  pDyn3 = (NtDyn3Descr_t*)NT_NET_GET_PKT_DESCR_PTR(hNetBuf);
496  pb = (uint8_t*)pDyn3;
497  const size_t descrLen = pDyn3->descrLength - 4U;
498  pDyn3->descrLength = descrLen & 0x3fU; // create space in actual packet to prepend 4-byte VLAN-tag,
499  memmove(pb + descrLen, pb + descrLen + 4U, 12U); // move actual MAC-header to new start of packet payload
500  memcpy(pb + descrLen + 12U, &vlan_tag, 4U); // insert VLAN tag after MAC-header
501  pDyn3->wireLength = (pDyn3->wireLength + 4U) & 0x3fffU; // set new wire length to inlude the 4-byte VLAN-tag
502 #endif
503 
504 #if ENABLE_DYNAMIC_TX_PORT
505  NT_NET_SET_PKT_TXPORT(hNetBuf, dynamicTxPort);
506  if (dynamicTxPort == 0) {
507  dynamicTxPort = 1;
508  }
509  else {
510  dynamicTxPort = 0;
511  }
512 #endif
513 
514 #if DISCARD_EVERY_SECOND_PACKET
515  if (discard) {
516  // discard packet
517 #if DISCARD_BY_WIRELEN
518  // force wirelength = 0
519  pDyn3->wireLength = 0;
520 #else
521  pDyn3->rxPort = 1; // INFO: Ensure ignore-bit is TRUE. Requires NTPL-Setup: TxIgnorePos=42
522 #endif
523  discard = 0;
524  }
525  else {
526  // don't discard
527 #if DISCARD_BY_WIRELEN
528  // keep wirelength untouched
529 #else
530  pDyn3->rxPort = 0; // INFO: Ensure ignore-bit is FALSE. Requires NTPL-Setup: TxIgnorePos=42
531 #endif
532  discard = 1;
533  }
534 #endif
535 
536  // 2: Forward the VLAN-tagged packet
537  if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) {
538  // Get the status code as text
539  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
540  fprintf(stderr, "NT_NetRxRelease() failed: %s\n", errorBuffer);
541  return -1;
542  }
543  }
544 
545  // 3: Get the next packet
546  while (appRunning == 1) {
547  if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) {
548  if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) {
549  // Timeouts are ok, we just need to wait a little longer for a packet
550  continue;
551  }
552  // Get the status code as text
553  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
554  fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer);
555  return -1;
556  }
557  totPkts++;
558  totBytes += NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf);
559  break; // We got a packet
560  }
561  } // end of packet processing loop
562 
563  // Close the stream and release the hostbuffer
564  NT_NetRxClose(hNetRx);
565 
566  // Request stats
568  statSet.u.query_v4.poll = 1;
569  statSet.u.query_v4.clear = 0;
570  if ((status = NT_StatRead(hStat, &statSet)) != NT_SUCCESS) {
571  fprintf(stderr, "Failed reading statistics: 0x%08X\n", status);
572  return -1;
573  }
574 
575  // Read drop counters for streamid 1
576  uint64_t totDropsPkts = statSet.u.query_v4.data.stream.streamid[1].drop.pkts;
577  uint64_t totDropsBytes = statSet.u.query_v4.data.stream.streamid[1].drop.octets;
578 
579  // Close stat stream
580  NT_StatClose(hStat);
581 
582  // Open a config stream to delete a filter.
583  if ((status = NT_ConfigOpen(&hCfgStream, "TestStream")) != NT_SUCCESS) {
584  // Get the status code as text
585  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
586  fprintf(stderr, "NT_ConfigOpen() failed: %s\n", errorBuffer);
587  return -1;
588  }
589 
590  // Clear filter setup
591  snprintf(tmpBuffer, sizeof(tmpBuffer), "Delete=All");
592  if ((status = NT_NTPL(hCfgStream, tmpBuffer, &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
593  // Get the status code as text
594  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
595  fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer);
596  fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode);
597  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]);
598  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]);
599  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]);
600  return -1;
601  }
602 
603  // Close the config stream
604  if ((status = NT_ConfigClose(hCfgStream)) != NT_SUCCESS) {
605  // Get the status code as text
606  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
607  fprintf(stderr, "NT_ConfigClose() failed: %s\n", errorBuffer);
608  return -1;
609  }
610 
611  // Output totals
612  printf("Drop: %lu packets, %lu bytes\n", totDropsPkts, totDropsBytes);
613  printf("Done: %lu packets, %lu bytes\n", totPkts, totBytes);
614 
615  // Close down the NTAPI library
616  NT_Done();
617 
618  return 0;
619 }
620 
621 //
622 // EOF
623 //