flowmatch_example_transmitter.cpp Source File

Reference Documentation

Platform
Napatech SmartNIC
Content Type
Reference Information
Capture Software Version
Link™ Capture Software 12.15
Napatech Software Suite: examples/flowmatch/flowmatch_example_transmitter.cpp Source File
flowmatch_example_transmitter.cpp
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2025 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 "NA-0009 Software License Agreement.pdf"
18  *
19  * 4. Redistributions of source code must retain this copyright notice,
20  * list of conditions and the following disclaimer.
21  *
22  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, EXPRESS OR
23  * IMPLIED, AND NAPATECH DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING ANY
24  * IMPLIED WARRANTY OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, OR OF
25  * FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT NOT PROHIBITED BY
26  * APPLICABLE LAW, IN NO EVENT SHALL NAPATECH BE LIABLE FOR PERSONAL INJURY,
27  * OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER,
28  * INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR
29  * LOSS OF DATA, FAILURE TO TRANSMIT OR RECEIVE ANY DATA OR INFORMATION,
30  * BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING
31  * OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE NAPATECH SOFTWARE OR
32  * SERVICES OR ANY THIRD PARTY SOFTWARE OR APPLICATIONS IN CONJUNCTION WITH
33  * THE NAPATECH SOFTWARE OR SERVICES, HOWEVER CAUSED, REGARDLESS OF THE THEORY
34  * OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF NAPATECH HAS BEEN
35  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW
36  * THE EXCLUSION OR LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF
37  * INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU.
38  *
39  *
40 
41  */
42 
43 // Include this in order to access the Napatech API
44 #include <nt.h>
45 
46 #include <algorithm>
47 #include <chrono>
48 #include <cstdint>
49 #include <cstring>
50 #include <thread>
51 
53 
55 
56 namespace {
57 
58 /**
59  * Swap the IP addresses and port numbers for a packet.
60  * Works for both IPv4 and IPv6.
61  */
62 void swapIpAndPort(uint8_t* packet)
63 {
64  unsigned int etherType = 12;
65  unsigned int ipHeader = 0;
66  unsigned int tcpHeader = 0;
67 
68  // Handle IEEE 802.1Q
69  if (packet[etherType] == 0x81 && packet[etherType+1] == 0x00) etherType += 4;
70  ipHeader = etherType + 2;
71 
72  if (packet[etherType] == 0x08 && packet[etherType+1] == 0x00) { // IPv4
73  unsigned int internetHeaderLength = static_cast<unsigned int>(packet[ipHeader] & 0x0f) * 4;
74  tcpHeader = ipHeader + internetHeaderLength;
75 
76  std::swap_ranges(packet+ipHeader+12,packet+ipHeader+12+4,packet+ipHeader+16);
77  }
78  else if (packet[etherType] == 0x86 && packet[etherType+1] == 0xdd) { // IPv6
79  tcpHeader = ipHeader + 40;
80 
81  std::swap_ranges(packet+ipHeader+8,packet+ipHeader+8+16,packet+ipHeader+24);
82  }
83  else {
84  return;
85  }
86 
87  std::swap_ranges(packet+tcpHeader+0,packet+tcpHeader+0+2,packet+tcpHeader+2);
88 }
89 
90 } // Unnamed namespace
91 
92 void taskTransmitter(uint32_t port, const uint8_t* packet, size_t packetSize,
93  size_t frameSize, int numPackets, uint64_t perPacketDelay, bool swapIp)
94 {
95  int status;
96  NtNetStreamTx_t hNetTx;
97  NtNetBuf_t hNetBufTx;
98 
99  // Open a TX stream.
100  status = NT_NetTxOpen(&hNetTx, "flowmatch_example_transmitter", 1ULL << port, NT_NETTX_NUMA_ANY_HB, 0);
101  handleErrorStatus(status, "NT_NetTxOpen() failed");
102 
103  for (int i = 0; i < numPackets; ++i) {
104  // Get a packet TX buffer for this tx stream and port, 100 ms timeout.
105  status = NT_NetTxGet(hNetTx, &hNetBufTx, port, frameSize, NT_NETTX_PACKET_OPTION_DEFAULT, 100);
106  handleErrorStatus(status, "NT_NetTxGet() failed");
107 
108  // Set data to be transmitted.
109  uint8_t* ptr = static_cast<uint8_t*>(NT_NET_GET_PKT_L2_PTR(hNetBufTx));
110  std::memset(ptr, 0, frameSize);
111  std::memcpy(ptr, packet, packetSize);
112  if (swapIp) {
113  swapIpAndPort(ptr);
114  }
115 
116  // Release the TX buffer to transmit the packet.
117  status = NT_NetTxRelease(hNetTx, hNetBufTx);
118  handleErrorStatus(status, "NT_NetTxRelease() failed");
119 
120  if (perPacketDelay != 0) {
121  std::this_thread::sleep_for(std::chrono::milliseconds(perPacketDelay));
122  }
123  }
124 
125  // Give the daemon time to transmit all packets before closing.
126  std::this_thread::sleep_for(std::chrono::milliseconds(100));
127 
128  // Close TX stream.
129  status = NT_NetTxClose(hNetTx);
130  handleErrorStatus(status, "NT_NetTxClose() failed");
131 
132  // Delay before NT_NetTxOpen is called again.
133  std::this_thread::sleep_for(std::chrono::milliseconds(100));
134 }