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