net/vlandemo/vlandemo_example.c

Reference Documentation

product_line_custom
Napatech SmartNIC
category
Reference Information

Description

INFO:
  • This is an 4GA inline example, which depends on the 4GA inline NTPL features.

  • The 3GA inline example can be found in examples/net/inline/.

This source file is an example of how to implement a simple vlan tagging, using the 4GA Napatech inline application capabilities. The example will add a vlan tag to every received packet before forwarding. The example demonstrates how to utilize following features:

RX:

  • a) set descriptor type = Dyn3

  • b) set descriptor length

TX:

  • c) set descriptor type = Dyn

  • d) set TxPorts = fixed or dynamic range

  • e) discard RxCRC

  • f) set TxPortPos for dynamic range (within same adapter)

Prerequisites

Any 4GA Napatech accelerator with 4GA FPGA inline support which was introduced with the HB2 release, FPGA-images: 200-95xx-08-xx, supporting minimum the NT_FEATURE_LEVEL_N_ANL9 feature set.

Below is an example of an ini-file with the default setting for NT40E3_4_PTP (adapter 0). The default setting supports the 4GA TX inline feature.

Establish optical cable loop from port 0 to port 1.

Use the following NT tools and sequence to demo this vlan example:
  • 1) start ntservice: /opt/napatech3/bin/ntstart.sh

  • 2) start monitoring: /opt/napatech3/bin/monitoring

  • 3) start pktgen: /opt/napatech3/bin/pktgen -p 1 -s 1024 -n 0

  • 4) check on monitoring:
    • 10G TX traffic on port 1

    • 10G RX traffic on port 0

  • 5) start vlandemo: /opt/napatech3/examples/net/vlandemo/vlandemo_example

  • 6) check on monitoring:
    • 10G TX traffic on port 1 and port 0 (inline)

    • 10G RX traffic on port 0 and port 1 (inline)

[System] HostBufferRefreshIntervalAll = default # LinkPropagationPortPairs = # [portA, portB], ... NumWorkerThreads = 3 # 1 .. 100 SDRAMFillLevelWarning = 0 # X1, X2, X3, X4 TimestampFormat = NATIVE_UNIX # NATIVE_UNIX* - PCAP - PCAP_NS TimestampMethod = EOF # UNKNOWN - EOF* TimeSyncOsTimeReference = None # None* - adapter-0 - adapter-1 - adapter-2 - adapter-3 - adapter-4 - adapter-5 - adapter-6 - adapter-7 [Logging] LogBufferWrap = wrap # wrap* - nowrap LogFileName = /tmp/Log3G_%s.log # String LogMask = 7 # See ini-file help for information about possible values LogToFile = false # true/false LogToSystem = true # true/false [Adapter0] AdapterType = NT40E3_4_PTP # ... BusId = 0000:08:00.0 # NNNN:NN:NN.N DiscardSize = 16 # 16 .. 63 HighFrequencySampling = DISABLE # DISABLE* - ENABLE HostBufferHandlerAffinity = -2 # -2 .. 39 HostBufferPollInterval = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000 HostBufferRefreshIntervalRx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500 HostBufferRefreshIntervalTx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500 HostBufferSegmentAlignmentRx = default # default* - none - 0 - 512 - 1024 - 2048 - 4096 HostBufferSegmentSizeRx = default # default* - dynamic - 0 - 1 - 2 - 4 HostBufferSegmentTimeOut = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000 HostBuffersRx = [4,16,-1] # [x1, x2, x3], ... HostBuffersTx = [4,16,-1] # [x1, x2, x3], ... IfgMode = NS # NS* - BYTE KmTcamConfig = [2,4,0],[4,1,0] # [cnt, len, dualLookup], ... MaxFrameSize = 9018 # 1518 .. 10000 NumaNode = -1 # -1 .. 16 OnBoardMemorySplit = Even # Dynamic - Even* - Proportional PacketDescriptor = NT # PCAP - NT* - Ext9 PortDisableMask = 0 # See ini-file help for information about possible values PortSpeedMultiRate = 10G, 10G, 10G, 10G # 1G - 10G* Profile = None # None* - Capture PtpDhcp = ENABLE # DISABLE - ENABLE* PtpMasterModeAllowed = DISABLE # DISABLE* - ENABLE PtpProfile = Default # Default* - Telecom - Power PtpUserDescription = Napatech adapter # String SofLinkSpeed = 10G # 100M - 1G - 10G TimeSyncConnectorExt1 = PpsIn # None - NttsIn* - PpsIn - NttsOut - PpsOut - RepeatInt1 - RepeatInt2 TimeSyncConnectorInt1 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt2 TimeSyncConnectorInt2 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt1 TimeSyncHardReset = ENABLE # DISABLE - ENABLE* TimeSyncNTTSInSyncLimit = 5000 # 1 .. 4294967295 TimeSyncOSInSyncLimit = 50000 # 1 .. 4294967295 TimeSyncPPSInSyncLimit = 5000 # 1 .. 4294967295 TimeSyncPTPInSyncLimit = 5000 # 1 .. 4294967295 TimeSyncReferencePriority = Ext1, FreeRun # FreeRun* - PTP - Int1 - Int2 - Ext1 - OSTime TimeSyncTimeOffset = 0 # 0 .. 1000000 TxTiming = RELATIVE # ABSOLUTE - RELATIVE* VXLANAltDestinationPorts = 4789,4789 # X1, X2

Program flow

The following is required to run in an inline scenario:
  • #include/nt.h - Applications/Tools only need to include nt.h to obtain prototypes, macros etc. from NTAPI.

  • NT_Init(NTAPI_VERSION) - Initialize the NTAPI library. NTAPI_VERSION is a define that describes the version of the API described in the header files included by nt.h. NT_Init() will ask the NTAPI library to convert return data to the NTAPI_VERSION if possible. This will ensure that applications can run on NTAPI libraries of newer versions.

  • To verify that the 4GA inline feature is supported, the Is4GATxSupported() local function open a info stream with NT_InfoOpen() - to inquire the actual feature level with NT_InfoRead() and check if we have minimum the ANL9. Next,

  • NT_ConfigOpen() - Open a config stream in order to setup filter using the NT_NTPL() command. Some conditional compile flags control various options:
    • ENABLE_DYNAMIC_TX_PORT - setup NTPL "TxPortPos=112" Dyn-desc

    • ENABLE_VLAN_TAGGING - enable VLAN tagging or packet forward

    • DISCARD_EVERY_SECOND_PACKET - discard every second packet

    • DISCARD_BY_WIRELEN - discard setting wirelen=0 or TXIGNORE=1

    • ENABLE_DYN_USER_DATA - extend Dyn3 descriptor for user data

  • NT_NetRxOpen() - Open a stream. The stream ID(=1) must match the one used when creating the filter using the NT_NTPL() command.

  • Having setup the TX inline NTPL configuration for stream ID(=1) and opened the RX stream ID(=1), the packet processing and forwarding loop is entered. Wait until we receive packets with NT_NetRxGet(), which is called with a timeout of 1000ms and will return NT_STATUS_TIMEOUT in case nothing is received within 1000ms and will return NT_SUCCESS if something is returned. Return values different from that is an indication of an error. Packets are received with the Dyn3-descriptor as configured with NTPL. If ENABLE_VLAN_TAGGING is true, the required VLAN-tag space(=4 bytes) is allocated from the Dyn3-descriptor by subtracting 4 bytes from from the descriptor-length and adding 4-bytes to the wire-length along with the MAC-header move and VLAN-tag payload prepending. If DISCARD_EVERY_SECOND_PACKET is enabled, every second packet is discarded either by setting wirelen = 0 if DISCARD_BY_WIRELEN is enabled or by setting the TX IGNORE-bit to 1 with TxIgnorePos=42 . Next, the actual packet is forwarded with the NT_NetRxRelease().

  • At program termination, the config stream is opened to clear the NTPL filter serup witth the "Delete=All" before the RX stream(=1) is closed the NT_NetRxClose().

Code

/* * %NT_SOFTWARE_LICENSE% */ /** * @example net/vlandemo/vlandemo_example.c * @section vlandemo_example_description Description * * INFO: * - This is an 4GA inline example, which depends on the 4GA inline NTPL features. * - The 3GA inline example can be found in examples/net/inline/. * * This source file is an example of how to implement a simple vlan tagging, * using the 4GA Napatech inline application capabilities. * The example will add a vlan tag to every received packet before forwarding. * The example demonstrates how to utilize following features: * * RX: * * - a) set descriptor type = Dyn3 * - b) set descriptor length * * TX: * * - c) set descriptor type = Dyn * - d) set TxPorts = fixed or dynamic range * - e) discard RxCRC * - f) set TxPortPos for dynamic range (within same adapter) * * The following NTAPI functions are used: * - @ref NT_Init() * - @ref NT_ConfigOpen() * - @ref NT_InfoOpen() * - @ref NT_NetRxOpen() * - @ref NT_InfoRead() * - @ref NT_NTPL() * - @ref NT_NetRxGet() * - @ref NT_NET_GET_PKT_CAP_LENGTH() * - @ref NT_NET_GET_PKT_DESCR_LENGTH() * - @ref NT_NET_GET_PKT_WIRE_LENGTH() * - @ref NT_NET_GET_PKT_TIMESTAMP() * - @ref NT_NET_GET_PKT_DESCR_PTR() * - @ref NT_NET_SET_PKT_TXPORT() * - @ref NT_NetRxRelease() * - @ref NT_NetRxClose() * - @ref NT_ConfigClose() * - @ref NT_InfoClose() * - @ref NT_ExplainError() * * @section vlandemo_example_prerequisites Prerequisites * Any 4GA Napatech accelerator with 4GA FPGA inline support which was * introduced with the HB2 release, FPGA-images: 200-95xx-08-xx, * supporting minimum the NT_FEATURE_LEVEL_N_ANL9 feature set. * * Below is an example of an ini-file with the default setting for * NT40E3_4_PTP (adapter 0). * The default setting supports the 4GA TX inline feature. * * Establish optical cable loop from port 0 to port 1. * * Use the following NT tools and sequence to demo this vlan example: * - 1) start ntservice: /opt/napatech3/bin/ntstart.sh * - 2) start monitoring: /opt/napatech3/bin/monitoring * - 3) start pktgen: /opt/napatech3/bin/pktgen -p 1 -s 1024 -n 0 * - 4) check on monitoring: * - 10G TX traffic on port 1 * - 10G RX traffic on port 0 * - 5) start vlandemo: /opt/napatech3/examples/net/vlandemo/vlandemo_example * - 6) check on monitoring: * - 10G TX traffic on port 1 and port 0 (inline) * - 10G RX traffic on port 0 and port 1 (inline) * * @code * [System] * HostBufferRefreshIntervalAll = default # * LinkPropagationPortPairs = # [portA, portB], ... * NumWorkerThreads = 3 # 1 .. 100 * SDRAMFillLevelWarning = 0 # X1, X2, X3, X4 * TimestampFormat = NATIVE_UNIX # NATIVE_UNIX* - PCAP - PCAP_NS * TimestampMethod = EOF # UNKNOWN - EOF* * TimeSyncOsTimeReference = None # None* - adapter-0 - adapter-1 - adapter-2 - adapter-3 - adapter-4 - adapter-5 - adapter-6 - adapter-7 * * [Logging] * LogBufferWrap = wrap # wrap* - nowrap * LogFileName = /tmp/Log3G_%s.log # String * LogMask = 7 # See ini-file help for information about possible values * LogToFile = false # true/false * LogToSystem = true # true/false * * [Adapter0] * AdapterType = NT40E3_4_PTP # ... * BusId = 0000:08:00.0 # NNNN:NN:NN.N * DiscardSize = 16 # 16 .. 63 * HighFrequencySampling = DISABLE # DISABLE* - ENABLE * HostBufferHandlerAffinity = -2 # -2 .. 39 * HostBufferPollInterval = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000 * HostBufferRefreshIntervalRx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500 * HostBufferRefreshIntervalTx = default # default* - 1 - 5 - 10 - 50 - 100 - 250 - 500 * HostBufferSegmentAlignmentRx = default # default* - none - 0 - 512 - 1024 - 2048 - 4096 * HostBufferSegmentSizeRx = default # default* - dynamic - 0 - 1 - 2 - 4 * HostBufferSegmentTimeOut = default # default* - 100 - 250 - 500 - 1000 - 10000 - 25000 - 50000 - 100000 * HostBuffersRx = [4,16,-1] # [x1, x2, x3], ... * HostBuffersTx = [4,16,-1] # [x1, x2, x3], ... * IfgMode = NS # NS* - BYTE * KmTcamConfig = [2,4,0],[4,1,0] # [cnt, len, dualLookup], ... * MaxFrameSize = 9018 # 1518 .. 10000 * NumaNode = -1 # -1 .. 16 * OnBoardMemorySplit = Even # Dynamic - Even* - Proportional * PacketDescriptor = NT # PCAP - NT* - Ext9 * PortDisableMask = 0 # See ini-file help for information about possible values * PortSpeedMultiRate = 10G, 10G, 10G, 10G # 1G - 10G* * Profile = None # None* - Capture * PtpDhcp = ENABLE # DISABLE - ENABLE* * PtpMasterModeAllowed = DISABLE # DISABLE* - ENABLE * PtpProfile = Default # Default* - Telecom - Power * PtpUserDescription = Napatech adapter # String * SofLinkSpeed = 10G # 100M - 1G - 10G * TimeSyncConnectorExt1 = PpsIn # None - NttsIn* - PpsIn - NttsOut - PpsOut - RepeatInt1 - RepeatInt2 * TimeSyncConnectorInt1 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt2 * TimeSyncConnectorInt2 = None # None* - NttsIn - PpsIn - NttsOut - PpsOut - RepeatExt1 - RepeatInt1 * TimeSyncHardReset = ENABLE # DISABLE - ENABLE* * TimeSyncNTTSInSyncLimit = 5000 # 1 .. 4294967295 * TimeSyncOSInSyncLimit = 50000 # 1 .. 4294967295 * TimeSyncPPSInSyncLimit = 5000 # 1 .. 4294967295 * TimeSyncPTPInSyncLimit = 5000 # 1 .. 4294967295 * TimeSyncReferencePriority = Ext1, FreeRun # FreeRun* - PTP - Int1 - Int2 - Ext1 - OSTime * TimeSyncTimeOffset = 0 # 0 .. 1000000 * TxTiming = RELATIVE # ABSOLUTE - RELATIVE* * VXLANAltDestinationPorts = 4789,4789 # X1, X2 * * @endcode * * @section vlandemo_example_flow Program flow * @{ * The following is required to run in an inline scenario: * - \#include/nt.h - Applications/Tools only need to include @ref * nt.h to obtain prototypes, macros etc. from NTAPI. * - @ref NT_Init(@ref NTAPI_VERSION) - Initialize the NTAPI * library. @ref NTAPI_VERSION is a define that describes the version * of the API described in the header files included by @ref * nt.h. NT_Init() will ask the NTAPI library to convert return data * to the @ref NTAPI_VERSION if possible. This will ensure that * applications can run on NTAPI libraries of newer versions. * - To verify that the 4GA inline feature is supported, the * Is4GATxSupported() local function open a info stream with * @ref NT_InfoOpen() - to inquire the actual feature level with * @ref NT_InfoRead() and check if we have minimum the ANL9. Next, * - @ref NT_ConfigOpen() - Open a config stream in order to setup * filter using the @ref NT_NTPL() command. Some conditional * compile flags control various options: * - ENABLE_DYNAMIC_TX_PORT - setup NTPL "TxPortPos=112" Dyn-desc * - ENABLE_VLAN_TAGGING - enable VLAN tagging or packet forward * - DISCARD_EVERY_SECOND_PACKET - discard every second packet * - DISCARD_BY_WIRELEN - discard setting wirelen=0 or TXIGNORE=1 * - ENABLE_DYN_USER_DATA - extend Dyn3 descriptor for user data * - @ref NT_NetRxOpen() - Open a stream. The stream ID(=1) must match * the one used when creating the filter using the @ref NT_NTPL() * command. * - Having setup the TX inline NTPL configuration for stream ID(=1) * and opened the RX stream ID(=1), the packet processing and * forwarding loop is entered. * Wait until we receive packets with @ref NT_NetRxGet(), which is * called with a timeout of 1000ms and will return NT_STATUS_TIMEOUT * in case nothing is received within 1000ms and will return * NT_SUCCESS if something is returned. Return values different from * that is an indication of an error. * Packets are received with the Dyn3-descriptor as configured with NTPL. * If ENABLE_VLAN_TAGGING is true, the required VLAN-tag space(=4 bytes) * is allocated from the Dyn3-descriptor by subtracting 4 bytes from * from the descriptor-length and adding 4-bytes to the wire-length along * with the MAC-header move and VLAN-tag payload prepending. * If DISCARD_EVERY_SECOND_PACKET is enabled, every second packet is discarded * either by setting wirelen = 0 if DISCARD_BY_WIRELEN is enabled or * by setting the TX IGNORE-bit to 1 with TxIgnorePos=42 . Next, the actual * packet is forwarded with the @ref NT_NetRxRelease(). * - At program termination, the config stream is opened to clear the * NTPL filter serup witth the "Delete=All" before the RX stream(=1) * is closed the @ref NT_NetRxClose(). * *<hr> * @section vlandemo_example_code Code * @} * */ #include <nt.h> #if defined(__linux__) #include <signal.h> #endif #ifdef _WIN32 #include <winsock2.h> /* htonl, htons */ #else #include <arpa/inet.h> /* htonl, htons */ #endif #if defined(WIN32) || defined (WIN64) //#define snprintf _snprintf #define snprintf(a, b, c, d) _snprintf_s((a), _countof(a), (b), (c), (d)) #endif //#define ENABLE_DYNAMIC_TX_PORT 1 // enable dynamic TX port #define ENABLE_VLAN_TAGGING 1 // enable VLAN tagging of packets //#define DISCARD_EVERY_SECOND_PACKET 1 // enable this to discard every second packet #define DISCARD_BY_WIRELEN 1 // enable this to use wirelen=0 discard option (recommended) //#define ENABLE_DYN_USER_DATA 1 // enable user data field along with Dyn3 static int running = 1 ; #if defined(__linux__) static void catch_signal(int sig) { (void)sig; running = 0 ; } #endif static int Is4GATxSupported(uint8_t portNo) { int status; // Status variable uint8_t adapterNo; NtInfoStream_t hInfo; // Handle to a info stream NtInfo_t infoRead; char errorBuffer[80]; // Error buffer if ((status = NT_InfoOpen(&hInfo, "Info")) != NT_SUCCESS) { NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)-1); fprintf(stderr, "NT_InfoOpen failed: %s", errorBuffer); return(0); } // Get adapterNo of this TX port (void)memset(&infoRead, 0, sizeof(NtInfo_t)); infoRead.cmd = NT_INFO_CMD_READ_PORT_V9; infoRead.u.port_v9.portNo=portNo; if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) { NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)-1); fprintf(stderr, "NT_InfoRead failed: %s", errorBuffer); return(0); } // Save adapter number of the TX port adapterNo = infoRead.u.port_v9.data.adapterNo ; // Get feature level of this adapter (void)memset(&infoRead, 0, sizeof(NtInfo_t)); infoRead.cmd=NT_INFO_CMD_READ_ADAPTER_V6; infoRead.u.adapter_v6.adapterNo = adapterNo; if ((status = NT_InfoRead(hInfo, &infoRead)) != NT_SUCCESS) { NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)-1); fprintf(stderr, "NT_InfoRead failed: %s", errorBuffer); return(0); } NT_InfoClose(hInfo); if (infoRead.u.adapter_v6.data.featureLevel == NT_FEATURE_LEVEL_N_ANL9 || infoRead.u.adapter_v6.data.featureLevel == NT_FEATURE_LEVEL_N_ANL10 || infoRead.u.adapter_v6.data.featureLevel == NT_FEATURE_LEVEL_N_ANL11) { // 4GA adapters with ANL9 feature level support native TX with inline capabilities // NOTE: 4GA adapters with ANL9 feature level doesn't support // NT_NET_SET_PKT_DESCR_TYPE_EXT7 descriptor type return(1); } printf("Adapter=%d, Port=%d, FeatureLevel=0x%x\n", adapterNo, portNo, infoRead.u.adapter_v6.data.featureLevel ); return(0); } int main(void) { int status; // Status variable char tmpBuffer[20]; // Buffer to build filter string char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer NtNetStreamRx_t hNetRx; // Handle to the RX stream NtConfigStream_t hCfgStream; // Handle to a config stream NtNtplInfo_t ntplInfo; // Return data structure from the NT_NTPL() call. NtNetBuf_t hNetBuf; // Net buffer container. Packet data is returned in this when calling NT_NetRxGet(). #if ENABLE_VLAN_TAGGING NtDyn3Descr_t *pDyn3; // dyn3 descriptor ref uint8_t* pb; struct __vlan_tag { uint16_t tpid; uint16_t tci; } vlan_tag = {htons(0x8100),htons(0x0001)}; // VLAN tag to prepend #endif #if DISCARD_EVERY_SECOND_PACKET int discard = 0 ; #endif #if ENABLE_DYNAMIC_TX_PORT int dynamicTxPort = 0 ; #endif #if defined(__linux__) signal(SIGINT, catch_signal); //<-- Catch keyboard QUIT (CTRL-\) #endif // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer); return -1; } // Check if 4GA TX including inline capability is supported if (!Is4GATxSupported(0)) { printf("ERROR: 4GA TX inline is NOT supported !\n"); return -1; } // Open a config stream to assign a filter to a stream ID. if ((status = NT_ConfigOpen(&hCfgStream, "TestStream")) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_ConfigOpen() failed: %s\n", errorBuffer); return -1; } #if DISCARD_EVERY_SECOND_PACKET #if DISCARD_BY_WIRELEN // Setup traffic to stream ID(=1) and Tx port = 0 if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { #else // 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) if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;TxIgnorePos=42;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { #endif #else #if ENABLE_DYNAMIC_TX_PORT // Setup traffic to stream ID(=1), Tx port = 0..1 (within same adapter), RxCRC = false, TxPortPos=112 (to utilize macro) 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) { #else // Setup traffic to stream ID(=1) and Tx port = 0 if ((status = NT_NTPL(hCfgStream, "Setup[TxDescriptor=Dyn;TxPorts=0;UseWL=True] = StreamId == 1", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { #endif #endif // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer); fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]); return -1; } // Assign all traffic from port 0 to stream ID(=1) #if ENABLE_DYN_USER_DATA // Set descriptor length = 62 bytes to add user data field of 40 bytes if ((status = NT_NTPL(hCfgStream, "Assign[StreamId=1;Descriptor=Dyn3,length=62] = Port == 0", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { #else // Keep default Dyn3 descriptor length = 22 bytes if ((status = NT_NTPL(hCfgStream, "Assign[StreamId=1;Descriptor=Dyn3] = Port == 0", &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { #endif // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer); fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]); return -1; } // Close the config stream if ((status = NT_ConfigClose(hCfgStream)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_ConfigClose() failed: %s\n", errorBuffer); return -1; } // Open stat stream NtStatStream_t hStat = NULL; if ((status = NT_StatOpen(&hStat, "hStat")) != 0) { fprintf(stderr, "Failed to create statistics stream: 0x%08X\n", status); return -1; } // Reset stats static NtStatistics_t statSet; statSet.cmd = NT_STATISTICS_READ_CMD_QUERY_V2; statSet.u.query_v2.poll = 1; statSet.u.query_v2.clear = 1; if ((status = NT_StatRead(hStat, &statSet))) { fprintf(stderr, "Failed resetting statistics: 0x%08X\n", status); return -1; } // Get a stream handle with the stream ID(=1). NT_NET_INTERFACE_PACKET specify that we will receive data in a packet based matter. if ((status = NT_NetRxOpen(&hNetRx, "TestStream", NT_NET_INTERFACE_PACKET, 1, -1)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NetRxOpen() failed: %s\n", errorBuffer); return -1; } // Optional step. Wait for the first packet that hit the NTPL assign command while (running) { if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) { if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) { // Timeouts are ok, we just need to wait a little longer for a packet continue; } // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer); return -1; } // We got a packet. Check if the timestamp is newer than when the NTPL assign command was applied if (NT_NET_GET_PKT_TIMESTAMP(hNetBuf) > ntplInfo.ts) { 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) ); break; // Break out, we have received a packet that is received after the NTPL assign command was applied } // Release the packet, it is too "old". if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NetRxRelease() failed: %s\n", errorBuffer); return -1; } } // Add VLAN tag and forward packet uint64_t totPkts = 0; uint64_t totBytes = 0; while (running) { // start of packet processing loop #if ENABLE_VLAN_TAGGING // 1: Add VLAN tag pDyn3 = (NtDyn3Descr_t*)NT_NET_GET_PKT_DESCR_PTR(hNetBuf) ; pb = (uint8_t*)pDyn3; pDyn3->descrLength = (uint64_t)((pDyn3->descrLength - 4)&0x3f); // create space in actual packet to prepend 4-byte VLAN-tag, memcpy( (pb+pDyn3->descrLength), (pb+pDyn3->descrLength+4), 12); // move actual MAC-header to new start of packet payload memcpy( (pb+pDyn3->descrLength+12), &vlan_tag, 4) ; // insert VLAN tag after MAC-header pDyn3->wireLength = (uint64_t)((pDyn3->wireLength + 4)&0x3fff); // set new wirelength to inlude the 4-byte VLAN-tag #endif #if ENABLE_DYNAMIC_TX_PORT NT_NET_SET_PKT_TXPORT(hNetBuf, dynamicTxPort); if (dynamicTxPort == 0) { dynamicTxPort = 1 ; } else { dynamicTxPort = 0 ; } #endif #if DISCARD_EVERY_SECOND_PACKET if (discard) { // discard packet #if DISCARD_BY_WIRELEN // force wirelength = 0 pDyn3->wireLength = 0; #else pDyn3->rxPort = 1; // INFO: Ensure ignore-bit is TRUE. Requires NTPL-Setup: TxIgnorePos=42 #endif discard = 0; } else { // don't discard #if DISCARD_BY_WIRELEN // keep wirelength untouched #else pDyn3->rxPort = 0; // INFO: Ensure ignore-bit is FALSE. Requires NTPL-Setup: TxIgnorePos=42 #endif discard = 1; } #endif // 2: Forward the VLAN-tagged packet if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NetRxRelease() failed: %s\n", errorBuffer); return -1; } // 3: Get the next packet while (running) { if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) { if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) { // Timeouts are ok, we just need to wait a little longer for a packet continue; } // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer); return -1; } totPkts++; totBytes += NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf); break; // We got a packet } } // end of packet processing loop // Close the stream and release the hostbuffer NT_NetRxClose(hNetRx); // Request stats statSet.cmd = NT_STATISTICS_READ_CMD_QUERY_V2; statSet.u.query_v2.poll = 1; statSet.u.query_v2.clear = 0; if ((status = NT_StatRead(hStat, &statSet)) != NT_SUCCESS) { fprintf(stderr, "Failed reading statistics: 0x%08X\n", status); return -1; } // Read drop counters for streamid 1 uint64_t totDropsPkts = statSet.u.query_v2.data.stream.streamid[1].drop.pkts; uint64_t totDropsBytes = statSet.u.query_v2.data.stream.streamid[1].drop.octets; // Close stat stream NT_StatClose(hStat); // Open a config stream to delete a filter. if ((status = NT_ConfigOpen(&hCfgStream, "TestStream")) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_ConfigOpen() failed: %s\n", errorBuffer); return -1; } // Clear filter setup snprintf(tmpBuffer, sizeof(tmpBuffer), "Delete=All"); if ((status = NT_NTPL(hCfgStream, tmpBuffer, &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer); fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]); fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]); return -1; } // Close the config stream if ((status = NT_ConfigClose(hCfgStream)) != NT_SUCCESS) { // Get the status code as text NT_ExplainError(status, errorBuffer, sizeof(errorBuffer)); fprintf(stderr, "NT_ConfigClose() failed: %s\n", errorBuffer); return -1; } // Output totals printf("Drop: %lu packets, %lu bytes\n", totDropsPkts, totDropsBytes); printf("Done: %lu packets, %lu bytes\n", totPkts, totBytes); // Close down the NTAPI library NT_Done(); return 0; } // // EOF //