bypass/config/bypass_config_example.c

Reference Documentation

Platform
Intel® PAC
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.10
Napatech Software Suite: bypass/config/bypass_config_example.c
bypass/config/bypass_config_example.c

Description

This source file is an example of how to use the Configuration stream interface in NTAPI for Napatech bypass accelerator and port configuration.

This example switches the state of the relays every time it is run.

The following NTAPI functions are used:


Prerequisites

A working system is needed with a Napatech bypass accelerator.

Program flow

The following is required to perform read and write operations on the configuration stream:


/*
*
* Copyright 2023 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 "NP-0405 Napatech 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 bypass/config/bypass_config_example.c
* @section Description Description
*
* This source file is an example of how to use the @ref ConfigStream
* "Configuration stream" interface in NTAPI for Napatech bypass accelerator and port configuration.
*
* This example switches the state of the relays every time it is run.
*
* The following NTAPI functions are used:
* - @ref NT_Init()
* - @ref NT_InfoOpen()
* - @ref NT_InfoRead()
* - @ref NT_InfoClose()
* - @ref NT_ConfigOpen()
* - @ref NT_ConfigWrite()
* - @ref NT_ConfigRead()
* - @ref NT_ConfigClose()
* - @ref NT_Done()
* - @ref NT_ExplainError()
*
* <hr>
* @section Prerequisites_l Prerequisites
* A working system is needed with a Napatech bypass accelerator.
*
* @section Flow Program flow
* @{
* The following is required to perform read and write operations on
* the @ref ConfigStream "configuration stream":
*
* - \#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_InfoOpen() - Open an info stream.
* - @ref NT_InfoRead() - Read info stream.
* - @ref NT_InfoClose() - Close the stream when terminating.
* - @ref NT_ConfigOpen() - Open a configuration stream.
* - @ref NT_ConfigRead() - Read configuration.
* - @ref NT_ConfigWrite() - Write configuration.
* - @ref NT_ConfigClose() - Close the stream when terminating.
* - @ref NT_Done() - Close down the NTAPI library.
* - @ref NT_ExplainError() - Explain an error code returned by NTAPI functions.
*
*<hr>
* @}
*/
// Include this in order to access the Napatech API
#include <nt.h>
#if defined(__linux__) || defined(__FreeBSD__)
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
//
// main()
//
int main(void)
{
NtError_t status;
char errBuf[NT_ERRBUF_SIZE];
//
NtInfo_t infoSystem;
NtInfo_t infoAdapter;
NtInfo_t infoPort;
//
NtConfig_t configPort;
//
uint8_t adapter;
uint8_t port;
//
const char* aBpState[] = {"NA", "Normal", "Bypass"};
const char* aBpFlags[] = {"Off", "On"};
//
//
//
// Initialize NTAPI library
if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_Init failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
// Open the information stream
if ((status = NT_InfoOpen(&hInfo, "bypass_config_example")) != NT_SUCCESS) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, ">>> Error: NT_InfoOpen failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
// Read system information
if ((status = NT_InfoRead(hInfo, &infoSystem)) != NT_SUCCESS) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_InfoRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
printf("System: %d.%d.%d.%d\n\n", infoSystem.u.system.data.version.major,
infoSystem.u.system.data.version.minor,
infoSystem.u.system.data.version.patch,
infoSystem.u.system.data.version.tag);
printf("Adapters: %u\n", infoSystem.u.system.data.numAdapters);
printf("Ports: %u\n", infoSystem.u.system.data.numPorts);
printf("\n");
// Open the config stream
status = NT_ConfigOpen(&hConfig, "bypass_config_example");
if (status != NT_SUCCESS) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, ">>> Error: NT_ConfigOpen failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
for (adapter = 0; adapter < infoSystem.u.system.data.numAdapters; adapter++) {
infoAdapter.u.adapter_v6.adapterNo = adapter;
if ((status = NT_InfoRead(hInfo, &infoAdapter)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_InfoRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
printf("Adapter %u (%u ports):\n", infoAdapter.u.adapter_v6.adapterNo, infoAdapter.u.adapter_v6.data.numPorts);
configPort.u.bypassConfig.u.adapterNo = adapter;
status = NT_ConfigRead(hConfig, &configPort);
if (status != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigRead failed. Code 0x%x = %s\n", status, errBuf);
continue; // skip this and continue to next adapter
}
else {
//
// Invert bypass adapter state - based on the current bypass adapter state
// Skip this step if the already read bypass adapter state is unknown - this means that the ports can be individually configured.
//
} else {
}
}
//
// Then write the changed configuration back...
//
configPort.u.bypassConfig.u.adapterNo = adapter;
if ((status = NT_ConfigWrite(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigWrite failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
//
// Display bypass configuration for the adapter
//
configPort.u.bypassConfig.u.adapterNo = adapter;
if ((status = NT_ConfigRead(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
printf(" bypass adapter current state: %s\n", aBpState[configPort.u.bypassConfig.data.currentBypassPortState]);
printf(" bypass adapter onInit state: %s\n", aBpState[configPort.u.bypassConfig.data.onInitBypassPortState]);
printf(" bypass adapter onPwrFail state: %s\n", aBpState[configPort.u.bypassConfig.data.onPowerFailBypassPortState]);
printf(" bypass adapter onWdtFail state: %s\n", aBpState[configPort.u.bypassConfig.data.onWatchdogFailBypassPortState]);
printf(" bypass adapter onPwrFail detect trigger: %s\n", aBpFlags[((configPort.u.bypassConfig.data.bypassTriggerModes & NT_BYPASS_TRIGGER_PWRFAIL)==0?0:1)]);
}
printf("\n");
for (port = 0; port < infoAdapter.u.adapter_v6.data.numPorts; port++) {
infoPort.u.port_v9.portNo = (uint8_t)(infoAdapter.u.adapter_v6.data.portOffset + port);
if ((status = NT_InfoRead(hInfo, &infoPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_InfoRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
printf(" Port %i (adapter #%i port #%i):\n", infoPort.u.port_v9.portNo, infoPort.u.port_v9.data.adapterNo, port);
//
// There is no need to configure both ports in a bypass portset pair.
// You only need configure one of the ports in a bypass portset pair.
// The other port automatically will mirror the bypass configuration of the first port.
//
if ((port & 0x01) == 0) {
//
// Read current configuration
//
configPort.u.bypassConfig.u.portNo = (uint8_t)(infoAdapter.u.adapter_v6.data.portOffset + port);
if ((status = NT_ConfigRead(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
//
// Invert bypass portset state - based on the current bypass portset state
//
} else {
}
//
// Then write the changed configuration back...
//
configPort.u.bypassConfig.u.portNo = (uint8_t)(infoAdapter.u.adapter_v6.data.portOffset + port);
if ((status = NT_ConfigWrite(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigWrite failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
}
//
// Display result of configuration for all ports in a bypass portset
// The second port in a bypass portset should have mirrored the settings applied to the first port.
//
configPort.u.bypassConfig.u.portNo = (uint8_t)(infoAdapter.u.adapter_v6.data.portOffset + port);
if ((status = NT_ConfigRead(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigRead failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
printf(" bypass port current state: %s\n", aBpState[configPort.u.bypassConfig.data.currentBypassPortState]);
printf(" bypass port onInit state: %s\n", aBpState[configPort.u.bypassConfig.data.onInitBypassPortState]);
printf(" bypass port onPwrFail state: %s\n", aBpState[configPort.u.bypassConfig.data.onPowerFailBypassPortState]);
printf(" bypass port onWdtFail state: %s\n", aBpState[configPort.u.bypassConfig.data.onWatchdogFailBypassPortState]);
printf(" bypass port onPwrFail detect trigger: %s\n", aBpFlags[((configPort.u.bypassConfig.data.bypassTriggerModes & NT_BYPASS_TRIGGER_PWRFAIL)==0?0:1)]);
configPort.u.bypassConfig.u.portNo = (uint8_t)(infoAdapter.u.adapter_v6.data.portOffset + port);
if ((status = NT_ConfigWrite(hConfig, &configPort)) != 0) {
NT_ExplainError(status, errBuf, sizeof(errBuf));
fprintf(stderr, "ERROR: NT_ConfigWrite failed. Code 0x%x = %s\n", status, errBuf);
return status;
}
}
printf("\n");
}
printf("\n");
}
printf("\n");
// Close down the NTAPI library
return 0;
}
//
// EOF
//