net/checksum/checksum_example.cpp

Reference Documentation

product_line_custom
IntelĀ® PAC
Napatech SmartNIC
category
Reference Information
Napatech Software Suite: net/checksum/checksum_example.cpp
net/checksum/checksum_example.cpp

Description

This example transmits 10 packets where L3/L4 checksum calculation is controlled via control bits in the packet descriptor.

By default this program transmits packets where the adapter recalculates both L3 and L4 checksum.

It is controlled by these code lines:

constexpr ChecksumCmdLayer3 cmd_l3 = CHECKSUM_LAYER3_GOOD;

constexpr ChecksumCmdLayer4 cmd_l4 = CHECKSUM_LAYER4_GOOD;

By changing these code lines and recompiling, the behavior can be changed to perform other action on the L3 and L4 checksum.

L3 options:

CHECKSUM_LAYER3_DO_NOTHING

CHECKSUM_LAYER3_BAD

CHECKSUM_LAYER3_GOOD

L4 options:

CHECKSUM_LAYER4_DO_NOTHING

CHECKSUM_LAYER4_BAD

CHECKSUM_LAYER4_GOOD

CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP

CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP_IPV4

CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_TUNNEL

CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_IPV4_TUNNEL

/*
*
* Copyright 2020 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 net/checksum/checksum_example.cpp
* @section checksum_example_description Description
*
* This example transmits 10 packets where
* L3/L4 checksum calculation is controlled
* via control bits in the packet descriptor.
*
* By default this program transmits packets where
* the adapter recalculates both L3 and L4 checksum.
*
* It is controlled by these code lines:
*
* constexpr ChecksumCmdLayer3 cmd_l3 = CHECKSUM_LAYER3_GOOD;
*
* constexpr ChecksumCmdLayer4 cmd_l4 = CHECKSUM_LAYER4_GOOD;
*
* By changing these code lines and recompiling, the
* behavior can be changed to perform other action
* on the L3 and L4 checksum.
*
* L3 options:
*
* CHECKSUM_LAYER3_DO_NOTHING
*
* CHECKSUM_LAYER3_BAD
*
* CHECKSUM_LAYER3_GOOD
*
*
* L4 options:
*
* CHECKSUM_LAYER4_DO_NOTHING
*
* CHECKSUM_LAYER4_BAD
*
* CHECKSUM_LAYER4_GOOD
*
* CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP
*
* CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP_IPV4
*
* CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_TUNNEL
*
* CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_IPV4_TUNNEL
*
*
*/
#include <nt.h>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
/**
* IPv4 UDP packet with IPv4 checksum error and UDP checksum error.
* No FCS included. Size: 96 byte.
*/
static constexpr uint8_t Test_packet[] {
0x42, 0xb3, 0xbb, 0x9b, 0x7b, 0x6b, 0x02, 0xe1,
0x27, 0xc4, 0x33, 0x0f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x52, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
0x79, 0x2c, 0x73, 0x35, 0xd7, 0xbe, 0x18, 0xdf,
0x1a, 0x71, 0x34, 0x8b, 0xcf, 0x5f, 0x00, 0x3e,
0xce, 0xe8, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70,
0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a,
0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69,
0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61,
0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a,
0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70,
0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a
};
/**
* An overlay struct for NtDyn3Descr_t making c-style or reinterpret cast possible.
* frame_type: Bit position 128. Overlays bit [3:0] in NtDyn3Descr_t.color_hi
* checksum_cmd: Bit position 132. Overlays bit [8:4] in NtDyn3Descr_t.color_hi
*/
uint64_t dont_care0;
uint64_t dont_care1;
uint64_t frame_type:4;
uint64_t checksum_cmd:5;
uint64_t dont_care2:39;
};
/**
* Valid values for layer 3 checksum command.
*/
CHECKSUM_LAYER3_DO_NOTHING = 0, // Do nothing
CHECKSUM_LAYER3_BAD = 2, // Insert BAD checksum in IPv4 header
CHECKSUM_LAYER3_GOOD = 3, // Insert GOOD checksum in IPv4 header
};
/**
* Valid values for layer 4 checksum command.
*/
CHECKSUM_LAYER4_DO_NOTHING = 0, // Do nothing
CHECKSUM_LAYER4_BAD = 2, // Insert BAD checksum in TCP/UDP header
CHECKSUM_LAYER4_GOOD = 3, // Insert GOOD checksum in TCP/UDP header
CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP = 4, // Insert GOOD checksum in TCP header and a value of ZERO in UDP header
CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP_IPV4 = 5, // Insert GOOD checksum in TCP header and a value of ZERO in UDP header when IP is IPv4
CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_TUNNEL = 6, // Insert GOOD checksum in TCP/UDP header and a value of ZERO in UDP header when part of a tunnel
CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_IPV4_TUNNEL = 7, // Insert GOOD checksum in TCP/UDP header and a value of ZERO in UDP header when IP is IPv4 and part of a tunnel
};
/**
* Valid values for a descriptor frame type.
*
* Bit [ 0]: Value 0: Not tunneled
* Value 1: Tunneled
*
* Bit [ 1]: Value 0: IPv4 or other
* Value 1: IPv6
*
* Bit [3:2]: Value 0: Other
* Value 1: TCP
* Value 2: UDP
* Value 3: Reserved
*/
enum FrameType {
FRAME_TYPE_IPV4_TCP = 0x0 | 0x0 | 0x4,
FRAME_TYPE_IPV4_UDP = 0x0 | 0x0 | 0x8,
FRAME_TYPE_IPV6_TCP = 0x0 | 0x2 | 0x4,
FRAME_TYPE_IPV6_UDP = 0x0 | 0x2 | 0x8,
FRAME_TYPE_IPV4_TCP_TUNNELED = 0x1 | 0x0 | 0x4,
FRAME_TYPE_IPV4_UDP_TUNNELED = 0x1 | 0x0 | 0x8,
FRAME_TYPE_IPV6_TCP_TUNNELED = 0x1 | 0x2 | 0x4,
FRAME_TYPE_IPV6_UDP_TUNNELED = 0x1 | 0x2 | 0x8,
};
/**
* Correctly combines layer 3 checksum command and layer 4 checksum command.
*/
{
return (((uint64_t)l3 & 0x3) << 3) | ((uint64_t)l4 & 0x7);
}
/**
* Handles and prints NT error messages, and the terminates the program.
*/
static inline void handle_error_status(int status, const char* message)
{
if(status != NT_SUCCESS) {
char error_buffer[NT_ERRBUF_SIZE];
NT_ExplainError(status, error_buffer, sizeof(error_buffer));
std::cerr << message << ": " << error_buffer << std::endl;
std::exit(EXIT_FAILURE);
}
}
int main(int, char**)
{
constexpr uint64_t fcs_size = 4;
constexpr uint64_t num_packets = 10;
constexpr uint32_t tx_port = 0;
int status;
NtNetBuf_t net_buffer;
NtNetStreamTx_t net_tx_stream;
// Initialize NT API.
handle_error_status(status, "NT_Init() failed");
// Initialize TX attributes struct and set up relevant stream related attributes.
NT_NetTxOpenAttrSetName(&attr, "Checksum example NetTx");
NT_NetTxOpenAttrSetPortMask(&attr, 1 << tx_port);
// Setting descriptor mode to DYN3 will cause Net Buffers received from NT_NetTxGet
// to be initialized with a DYN3 packet descriptor.
handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorMode() failed");
// To tell the adapter where to look for the frame type and checksum command bits.
status = NT_NetTxOpenAttrSetDescriptorPosFrameType(&attr, true, 128); // Bit position of Dyn3_checksum_overlay.frame_type
handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorPosFrameType() failed");
status = NT_NetTxOpenAttrSetDescriptorPosChecksumCmd(&attr, true, 132); // Bit position of Dyn3_checksum_overlay.checksum_cmd
handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorPosChecksumCmd() failed");
// Open TX stream with attributes
status = NT_NetTxOpen_Attr(&net_tx_stream, &attr);
handle_error_status(status, "NT_NetTxOpen() failed");
for(uint64_t i = 0; i < num_packets; ++i) {
// Use the option NT_NETTX_PACKET_OPTION_DYN to get a net buffer initialized with
// the DYN3 packet descriptor that was specified in NT_NetTxOpenAttrSetDescriptorMode.
// Note: Since the DYN3 packet descriptor does not contain a wire-length argument
// must be the correct size of the packet, not just big enough.
status = NT_NetTxGet(net_tx_stream, &net_buffer, tx_port, sizeof(Test_packet) + fcs_size, NT_NETTX_PACKET_OPTION_DYN, 100);
handle_error_status(status, "NT_NetTxGet() failed");
// Get a pointer to the beginning of the Ethernet frame, and copy Test_packet to that memory.
uint8_t* l2_ptr = reinterpret_cast<uint8_t*>(NT_NET_GET_PKT_L2_PTR(net_buffer));
std::memcpy(l2_ptr, Test_packet, sizeof(Test_packet));
// Get pointer to DYN3 packet descriptor.
auto descr_ptr = NT_NET_GET_PKT_DESCR_PTR_DYN3(net_buffer);
auto overlay_ptr = reinterpret_cast<Dyn3_checksum_overlay*>(descr_ptr);
// Set offset 0 to start of IP header, and offset 1 to start of UDP header.
descr_ptr->offset0 = 14; // Point to start of Layer 3, i.e. set to size of Ethernet header
descr_ptr->offset1 = 34; // Point to start of Layer 4, i.e. set to size of Ethernet header + IPv4 header with no options
// Set color values via the overlay struct.
overlay_ptr->frame_type = FRAME_TYPE_IPV4_UDP & 0xF;
overlay_ptr->checksum_cmd = checksum_command(cmd_l3, cmd_l4) & 0x1F;
// Release / transmit net buffer from NT_NetTxGet
status = NT_NetTxRelease(net_tx_stream, net_buffer);
handle_error_status(status, "NT_NetTxRelease() failed");
}
// Close TX stream, and then the NT API.
status = NT_NetTxClose(net_tx_stream);
handle_error_status(status, "NT_NetTxClose() failed");
return 0;
}