checksum_example.cpp 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/checksum/checksum_example.cpp Source File
checksum_example.cpp
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/checksum/checksum_example.cpp
46  * @section checksum_example_description Description
47  *
48  * This example transmits 10 packets where
49  * L3/L4 checksum calculation is controlled
50  * via control bits in the packet descriptor.
51  *
52  * By default this program transmits packets where
53  * the adapter recalculates both L3 and L4 checksum.
54  *
55  * It is controlled by these code lines:
56  *
57  * constexpr ChecksumCmdLayer3 cmd_l3 = CHECKSUM_LAYER3_GOOD;
58  *
59  * constexpr ChecksumCmdLayer4 cmd_l4 = CHECKSUM_LAYER4_GOOD;
60  *
61  * By changing these code lines and recompiling, the
62  * behavior can be changed to perform other action
63  * on the L3 and L4 checksum.
64  *
65  * L3 options:
66  *
67  * CHECKSUM_LAYER3_DO_NOTHING
68  *
69  * CHECKSUM_LAYER3_BAD
70  *
71  * CHECKSUM_LAYER3_GOOD
72  *
73  *
74  * L4 options:
75  *
76  * CHECKSUM_LAYER4_DO_NOTHING
77  *
78  * CHECKSUM_LAYER4_BAD
79  *
80  * CHECKSUM_LAYER4_GOOD
81  *
82  * CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP
83  *
84  * CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP_IPV4
85  *
86  * CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_TUNNEL
87  *
88  * CHECKSUM_LAYER4_GOOD_TCP_UDP_ZERO_UDP_IPV4_TUNNEL
89  *
90  *
91  */
92 
93 // Include this in order to access the Napatech API
94 #include <nt.h>
95 
96 #include <cstdint>
97 #include <cstdlib>
98 #include <cstring>
99 #include <iostream>
100 
101 /**
102  * IPv4 UDP packet with IPv4 checksum error and UDP checksum error.
103  * No FCS included. Size: 96 byte.
104  */
105 static constexpr uint8_t Test_packet[] {
106  0x42, 0xb3, 0xbb, 0x9b, 0x7b, 0x6b, 0x02, 0xe1,
107  0x27, 0xc4, 0x33, 0x0f, 0x08, 0x00, 0x45, 0x00,
108  0x00, 0x52, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
109  0x79, 0x2c, 0x73, 0x35, 0xd7, 0xbe, 0x18, 0xdf,
110  0x1a, 0x71, 0x34, 0x8b, 0xcf, 0x5f, 0x00, 0x3e,
111  0xce, 0xe8, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70,
112  0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a,
113  0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69,
114  0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61,
115  0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a,
116  0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x70,
117  0x69, 0x7a, 0x7a, 0x61, 0x70, 0x69, 0x7a, 0x7a
118 };
119 
120 /**
121  * An overlay struct for NtDyn3Descr_t making c-style or reinterpret cast possible.
122  * frame_type: Bit position 128. Overlays bit [3:0] in NtDyn3Descr_t.color_hi
123  * checksum_cmd: Bit position 132. Overlays bit [8:4] in NtDyn3Descr_t.color_hi
124  */
126  uint64_t dont_care0;
127  uint64_t dont_care1;
128  uint64_t frame_type:4;
129  uint64_t checksum_cmd:5;
130  uint64_t dont_care2:39;
131 };
132 
133 /**
134  * Valid values for layer 3 checksum command.
135  */
137  CHECKSUM_LAYER3_DO_NOTHING = 0, // Do nothing
138  CHECKSUM_LAYER3_BAD = 2, // Insert BAD checksum in IPv4 header
139  CHECKSUM_LAYER3_GOOD = 3, // Insert GOOD checksum in IPv4 header
140 };
141 
142 /**
143  * Valid values for layer 4 checksum command.
144  */
146  CHECKSUM_LAYER4_DO_NOTHING = 0, // Do nothing
147  CHECKSUM_LAYER4_BAD = 2, // Insert BAD checksum in TCP/UDP header
148  CHECKSUM_LAYER4_GOOD = 3, // Insert GOOD checksum in TCP/UDP header
149  CHECKSUM_LAYER4_GOOD_TCP_ZERO_UDP = 4, // Insert GOOD checksum in TCP header and a value of ZERO in UDP header
150  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
151  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
152  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
153 };
154 
155 /**
156  * Valid values for a descriptor frame type.
157  *
158  * Bit [ 0]: Value 0: Not tunneled
159  * Value 1: Tunneled
160  *
161  * Bit [ 1]: Value 0: IPv4 or other
162  * Value 1: IPv6
163  *
164  * Bit [3:2]: Value 0: Other
165  * Value 1: TCP
166  * Value 2: UDP
167  * Value 3: Reserved
168  */
169 enum FrameType {
170  FRAME_TYPE_IPV4_TCP = 0x0 | 0x0 | 0x4,
171  FRAME_TYPE_IPV4_UDP = 0x0 | 0x0 | 0x8,
172  FRAME_TYPE_IPV6_TCP = 0x0 | 0x2 | 0x4,
173  FRAME_TYPE_IPV6_UDP = 0x0 | 0x2 | 0x8,
174  FRAME_TYPE_IPV4_TCP_TUNNELED = 0x1 | 0x0 | 0x4,
175  FRAME_TYPE_IPV4_UDP_TUNNELED = 0x1 | 0x0 | 0x8,
176  FRAME_TYPE_IPV6_TCP_TUNNELED = 0x1 | 0x2 | 0x4,
177  FRAME_TYPE_IPV6_UDP_TUNNELED = 0x1 | 0x2 | 0x8,
178 };
179 
180 /**
181  * Correctly combines layer 3 checksum command and layer 4 checksum command.
182  */
184 {
185  return (((uint64_t)l3 & 0x3) << 3) | ((uint64_t)l4 & 0x7);
186 }
187 
188 /**
189  * Handles and prints NT error messages, and the terminates the program.
190  */
191 static inline void handle_error_status(int status, const char* message)
192 {
193  if (status != NT_SUCCESS) {
194  char error_buffer[NT_ERRBUF_SIZE];
195  NT_ExplainError(status, error_buffer, sizeof(error_buffer));
196  std::cerr << message << ": " << error_buffer << std::endl;
197  std::exit(EXIT_FAILURE);
198  }
199 }
200 
201 int main(int, char**)
202 {
203  constexpr uint64_t fcs_size = 4;
204  constexpr uint64_t num_packets = 10;
205  constexpr uint32_t tx_port = 0;
206 
207  constexpr ChecksumCmdLayer3 cmd_l3 = CHECKSUM_LAYER3_GOOD;
208  constexpr ChecksumCmdLayer4 cmd_l4 = CHECKSUM_LAYER4_GOOD;
209 
210  int status;
211  NtNetBuf_t net_buffer;
212  NtNetStreamTx_t net_tx_stream;
213  NtNetTxAttr_t attr;
214 
215  // Initialize NT API.
216  status = NT_Init(NTAPI_VERSION);
217  handle_error_status(status, "NT_Init() failed");
218 
219  // Initialize TX attributes struct and set up relevant stream related attributes.
220  NT_NetTxOpenAttrInit(&attr);
221  NT_NetTxOpenAttrSetName(&attr, "Checksum example NetTx");
222  NT_NetTxOpenAttrSetPortMask(&attr, 1 << tx_port);
223 
224  // Setting descriptor mode to DYN3 will cause Net Buffers received from NT_NetTxGet
225  // to be initialized with a DYN3 packet descriptor.
227  handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorMode() failed");
228 
229  // To tell the adapter where to look for the frame type and checksum command bits.
230  status = NT_NetTxOpenAttrSetDescriptorPosFrameType(&attr, true, 128); // Bit position of Dyn3_checksum_overlay.frame_type
231  handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorPosFrameType() failed");
232  status = NT_NetTxOpenAttrSetDescriptorPosChecksumCmd(&attr, true, 132); // Bit position of Dyn3_checksum_overlay.checksum_cmd
233  handle_error_status(status, "NT_NetTxOpenAttrSetDescriptorPosChecksumCmd() failed");
234 
235  // Open TX stream with attributes
236  status = NT_NetTxOpen_Attr(&net_tx_stream, &attr);
237  handle_error_status(status, "NT_NetTxOpen() failed");
238 
239  for (uint64_t i = 0; i < num_packets; ++i) {
240  // Use the option NT_NETTX_PACKET_OPTION_DYN to get a net buffer initialized with
241  // the DYN3 packet descriptor that was specified in NT_NetTxOpenAttrSetDescriptorMode.
242  // Note: Since the DYN3 packet descriptor does not contain a wire-length argument
243  // must be the correct size of the packet, not just big enough.
244  status = NT_NetTxGet(net_tx_stream, &net_buffer, tx_port, sizeof(Test_packet) + fcs_size, NT_NETTX_PACKET_OPTION_DYN, 100);
245  handle_error_status(status, "NT_NetTxGet() failed");
246 
247  // Get a pointer to the beginning of the Ethernet frame, and copy Test_packet to that memory.
248  uint8_t* l2_ptr = reinterpret_cast<uint8_t*>(NT_NET_GET_PKT_L2_PTR(net_buffer));
249  std::memcpy(l2_ptr, Test_packet, sizeof(Test_packet));
250 
251  // Get pointer to DYN3 packet descriptor.
252  auto descr_ptr = NT_NET_GET_PKT_DESCR_PTR_DYN3(net_buffer);
253  auto overlay_ptr = reinterpret_cast<Dyn3_checksum_overlay*>(descr_ptr);
254 
255  // Set offset 0 to start of IP header, and offset 1 to start of UDP header.
256  descr_ptr->offset0 = 14; // Point to start of Layer 3, i.e. set to size of Ethernet header
257  descr_ptr->offset1 = 34; // Point to start of Layer 4, i.e. set to size of Ethernet header + IPv4 header with no options
258 
259  // Set color values via the overlay struct.
260  overlay_ptr->frame_type = FRAME_TYPE_IPV4_UDP & 0xF;
261  overlay_ptr->checksum_cmd = checksum_command(cmd_l3, cmd_l4) & 0x1F;
262 
263  // Release / transmit net buffer from NT_NetTxGet
264  status = NT_NetTxRelease(net_tx_stream, net_buffer);
265  handle_error_status(status, "NT_NetTxRelease() failed");
266  }
267 
268  // Close TX stream, and then the NT API.
269  status = NT_NetTxClose(net_tx_stream);
270  handle_error_status(status, "NT_NetTxClose() failed");
271 
272  NT_Done();
273 
274  return 0;
275 }