net/replayfilewithtimestampinject/replayfilewithtimestampinject_example.c
Description
This source file is an example of how to read a capture file using NTAPI and transmit the packet using a dynamic descriptor which makes it possible to inject the transmitted timestamp in the packet.
This example make use of the following settings in ntservice.ini
TimestampFormat = UNIX_NS
TimestampInjectStaticOffset = 0
TimestampInjectDynamicOffset = TSI_DYN_SOF
PacketDescriptor = NT
The NT_NetFile...() functions does not require NTservice to be running.
The following NTAPI functions are used:
- NT_ExplainError()
- NT_Init()
- NT_NetFileClose()
- NT_NetFileGet()
- NT_NetFileOpen()
- NT_NetFileRelease()
- NT_NET_GET_PKT_DESCR_PTR_DYN3()
- NT_NET_GET_PKT_L2_PTR()
- NT_NET_GET_PKT_WIRE_LENGTH()
- NT_NetTxClose()
- NT_NETTX_DESCRIPTOR_MODE_DYN3
- NT_NetTxGet()
- NT_NETTX_NUMA_ADAPTER_HB
- NT_NetTxOpen_Attr
- NT_NetTxOpenAttrSetDescriptorPosChecksumCmd()
- NT_NetTxOpenAttrSetDescriptorPosFrameType()
- NT_NetTxOpenAttrSetMinHostbufferSize()
- NT_NetTxOpenAttrSetName()
- NT_NetTxOpenAttrSetPortMask()
- NT_NetTxOpenAttrSetTxtDescriptorPosFcs()
- NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInject()
- NT_NetTxOpen()
- NT_NetTxRelease()
Prerequisites
- Capture file, that has been captured with the net/capture/capture_example.c example.
- The capture filename should be given as first argument to this example.
Program flow
The following is required to perform replay of a captured file
- #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.
- NT_NetFileOpen() - Open the captured file and assign it to a stream.
- NT_NetFileGet() - Get a segment from the file. This call will return NT_SUCCESS upon return of a segment and NT_STATUS_END_OF_FILE when there is no more segments avaialble. The latter will cause the example to exit.
- NT_NetFileRelease() - Release the segment from the file stream.
- NT_NetFileClose() - Close the file stream when no more segments can be found.
Code
/*
*
* Copyright 2025 Napatech A/S. All Rights Reserved.
*
* 1. Copying, modification, and distribution of this file, or executable
* versions of this file, is governed by the terms of the Napatech Software
* license agreement under which this file was made available. If you do not
* agree to the terms of the license do not install, copy, access or
* otherwise use this file.
*
* 2. Under the Napatech Software license agreement you are granted a
* limited, non-exclusive, non-assignable, copyright license to copy, modify
* and distribute this file in conjunction with Napatech SmartNIC's and
* similar hardware manufactured or supplied by Napatech A/S.
*
* 3. The full Napatech Software License Agreement is included in this
* distribution, please see "NA-0009 Software License Agreement.pdf"
*
* 4. Redistributions of source code must retain this copyright notice,
* list of conditions and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
* IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
* IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
* FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
* APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
* OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
* INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
* LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
* BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
* OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
* SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
* THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
* OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
* THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
* INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
*
*
*/
/**
*
* @example net/replayfilewithtimestampinject/replayfilewithtimestampinject_example.c
*
* @section replayfilewithtimestampinject_example_description Description
*
* This source file is an example of how to read a capture file using NTAPI
* and transmit the packet using a dynamic descriptor which makes it possible
* to inject the transmitted timestamp in the packet.
*
* This example make use of the following settings in ntservice.ini
*
* TimestampFormat = UNIX_NS
*
* TimestampInjectStaticOffset = 0
*
* TimestampInjectDynamicOffset = TSI_DYN_SOF
*
* PacketDescriptor = NT
*
*
* The NT_NetFile...() functions does not require NTservice to be running.
*
* The following NTAPI functions are used:
* - @ref NT_ExplainError()
* - @ref NT_Init()
* - @ref NT_NetFileClose()
* - @ref NT_NetFileGet()
* - @ref NT_NetFileOpen()
* - @ref NT_NetFileRelease()
* - @ref NT_NET_GET_PKT_DESCR_PTR_DYN3()
* - @ref NT_NET_GET_PKT_L2_PTR()
* - @ref NT_NET_GET_PKT_WIRE_LENGTH()
* - @ref NT_NetTxClose()
* - @ref NT_NETTX_DESCRIPTOR_MODE_DYN3
* - @ref NT_NetTxGet()
* - @ref NT_NETTX_NUMA_ADAPTER_HB
* - @ref NT_NetTxOpen_Attr
* - @ref NT_NetTxOpenAttrSetDescriptorPosChecksumCmd()
* - @ref NT_NetTxOpenAttrSetDescriptorPosFrameType()
* - @ref NT_NetTxOpenAttrSetMinHostbufferSize()
* - @ref NT_NetTxOpenAttrSetName()
* - @ref NT_NetTxOpenAttrSetPortMask()
* - @ref NT_NetTxOpenAttrSetTxtDescriptorPosFcs()
* - @ref NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInject()
* - @ref NT_NetTxOpen()
* - @ref NT_NetTxRelease()
*
* @section replayfilewithtimestampinject_example_prerequisites Prerequisites
*
* - Capture file, that has been captured with the @ref
* net/capture/capture_example.c "net/capture/capture_example.c" example.
*
* - The capture filename should be given as first argument to this example.
*
* @section replayfilewithtimestampinject_example_flow Program flow
* @{
* The following is required to perform replay of a captured file
*
* - \#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.
* - @ref NT_NetFileOpen() - Open the captured file and assign it to a stream.
* - @ref NT_NetFileGet() - Get a segment from the file. This call will
* return @ref NT_SUCCESS upon return of a segment and
* @ref NT_STATUS_END_OF_FILE when there is no more segments
* avaialble. The latter will cause the example to exit.
* - @ref NT_NetFileRelease() - Release the segment from the file stream.
* - @ref NT_NetFileClose() - Close the file stream when no more segments can be found.
*
*<hr>
*
* @section replayfilewithtimestampinject_example_code Code
* @}
*
*/
// Include this in order to access the Napatech API
#include <nt.h>
#include <argparse.h>
#define PORT 0
// The struct below represents the TX dynamic descriptor
// used by this application
//
// The struct is based on a copy of Dynamic descriptor 3
// It is modified with the location of the command bits
// time stamp inject handling and FCS handling.
//
// This example uses 3 bits of the color_hi field
// for these command bits. In other words - the
// normal color_hi:28 has been replaced by the
// 3 command bits and a color_hi_unused:25
//
uint64_t capLength:14;
uint64_t wireLength:14;
uint64_t color_lo:14;
uint64_t rxPort:6;
uint64_t descrFormat:8;
uint64_t descrLength:6;
uint64_t tsColor:1;
uint64_t ntDynDescr:1;
uint64_t timestamp;
uint64_t offset0:10;
uint64_t offset1:10;
};
// Time stamp inject command bit values
// FCS command bits values
"USAGE: replayfilewithtimestampinject_example <nt3gd_capture_filename>\n"
"Commands:\n",
NULL};
/**
* Table of valid options.
*/
OPT_HELP(),
OPT_END(),
};
// printError is a simple convenience function for printing an NTAPI error
// message to stderr.
fprintf(stderr, "%s: %s\n", prefix, errorBuffer);
}
int status; // Status variable
size_t pktLen = 0; // packet lenght
int option;
const char* ntcap_filename = NULL;
NtNetStreamFile_t hNetFile; // Handle to the File stream
int running = 1;
if ((option >= 1) && (argv[0] != NULL)) {
ntcap_filename = argv[0];
} else {
argparse_usage(&argparse);
exit(0);
}
// Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
if ( status == NT_ERROR_NT_SERVICE_NOT_STARTED) {
printf("NOTE: NT service is not started.\n");
} else {
// Get the status code as text
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
return -1;
}
}
// Open the capture file to replay (captured with the capture example)
if ((status = NT_NetFileOpen(&hNetFile, "FileStream", NT_NET_INTERFACE_PACKET, ntcap_filename)) != NT_SUCCESS) {
// Get the status code as text
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetFileOpen() failed: %s\n", errorBuffer);
return -1;
}
// Open a TX stream
NtNetStreamTx_t hNetTx;
if (status != NT_SUCCESS) {
printError("NT_NetTxOpen() failed", status);
return -1;
}
NtNetTxAttr_t txAttr;
NT_NetTxOpenAttrInit(&txAttr);
NT_NetTxOpenAttrSetMinHostbufferSize(&txAttr, 0);
// Set the position of the various descriptor command
// in accordance with struct Dyn3_tx_descriptor
if (status != NT_SUCCESS) {
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetTxOpenAttrSetTxtDescriptorPosTimestampInjectCmd failed: %s\n", errorBuffer);
exit(1);
}
if (status != NT_SUCCESS) {
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetTxOpenAttrSetTxtDescriptorPosFcs failed: %s\n", errorBuffer);
exit(1);
}
// Open the TX network stream
status = NT_NetTxOpen_Attr(&hNetTx, &txAttr);
if (status != NT_SUCCESS) {
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetTxOpen() failed: %s\n", errorBuffer);
exit(1);
}
NtNetBuf_t hNetBufTx;
// Get packets from the file - update counters
while (running) {
// Get the packet
if (status == NT_STATUS_END_OF_FILE) {
// The file has no more data
break;
}
// Get the status code as text
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetFileGet() failed: %s\n", errorBuffer);
return -1;
}
pktLen = NT_NET_GET_PKT_WIRE_LENGTH((hNetBufFile));
printf("Fetched packet: #%d: packet length: %lu bytes - total capture length: %lu bytes\n", numPackets, pktLen, numBytes);
// Get a packet TX buffer for this tx stream and port, without timeout
NT_NETTX_PACKET_OPTION_DYN, -1)) != NT_SUCCESS) {
printError("NT_NetTxGet() failed", status);
return -1;
}
// Release the TX buffer and the packet will be transmitted
// Get the status code as text
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetTxRelease() failed: %s\n", errorBuffer);
running = false;
}
numPackets++,
numBytes += pktLen;
// Release the file packet
// Get the status code as text
NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
fprintf(stderr, "NT_NetFileRelease() failed: %s\n", errorBuffer);
running = false;
}
}
// Close the TX stream
NT_NetTxClose(hNetTx);
// Close the file stream
NT_NetFileClose(hNetFile);
printf("Done: %d packets %lu bytes has been read\n", numPackets, numBytes);
return 0;
}