addPacket_example.c 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/addPacket/addPacket_example.c Source File
addPacket_example.c
Go to the documentation of this file.
1 // Include this in order to access the Napatech API
2 #include <nt.h>
3 
4 #include <string.h> // memcpy
5 
6 #if defined(WIN32) || defined (WIN64)
7  #define snprintf(dst, ...) _snprintf_s((dst), _countof(dst), __VA_ARGS__)
8 #endif
9 
10 // default PORTs
11 #define RX_PORT 0
12 #define TX_PORT 1
13 
14 #define PACKETS 3 // if set to 0, unlimited receive (loop with VLAN-tagging)
15 
16 int main(void)
17 {
18  int size=0;
19 
20  uint64_t numPackets=0; // The number of packets received
21  char ntplStr[200];
22  char errorBuffer[NT_ERRBUF_SIZE]; // Error buffer
23  int status; // Status variable
24  NtNetStreamRx_t hNetRx; // Handle to the RX stream
25  NtConfigStream_t hCfgStream; // Handle to a config stream
26  NtNtplInfo_t ntplInfo; // Return data structure from the NT_NTPL() call.
27  NtNetBuf_t hNetBuf; // Net buffer container. Packet data is returned in this when calling NT_NetRxGet().
28 
29  NtNetStreamTx_t hNetTx; // Handle to the TX stream
30  NtNetTxFragment_t addPacketFragmentList[3]; // Array to hold fragmented packet (meta)data
31 
32 
33  // Initialize the NTAPI library and thereby check if NTAPI_VERSION can be used together with this library
34  if ((status = NT_Init(NTAPI_VERSION)) != NT_SUCCESS) {
35  // Get the status code as text
36  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
37  fprintf(stderr, "NT_Init() failed: %s\n", errorBuffer);
38  return -1;
39  }
40 
41  // Open a config stream to assign a filter to a stream ID.
42  if ((status = NT_ConfigOpen(&hCfgStream, "TestStream")) != NT_SUCCESS) {
43  // Get the status code as text
44  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
45  fprintf(stderr, "NT_ConfigOpen() failed: %s\n", errorBuffer);
46  return -1;
47  }
48 
49  // Assign all traffic on defined RX_PORT to stream ID 1
50  snprintf(ntplStr, sizeof(ntplStr), "Assign[streamid=1] = port == %d", RX_PORT);
51  if ((status = NT_NTPL(hCfgStream, ntplStr, &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
52  // Get the status code as text
53  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
54  fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer);
55  fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode);
56  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]);
57  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]);
58  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]);
59  return -1;
60  }
61 
62  // Get a stream handle with the hostBuffer mapped to it. NT_NET_INTERFACE_PACKET receive data packet-by-packet
63  if ((status = NT_NetRxOpen(&hNetRx, "TestStream", NT_NET_INTERFACE_PACKET, 1, -1)) != NT_SUCCESS) {
64  // Get the status code as text
65  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
66  fprintf(stderr, "NT_NetRxOpen() failed: %s\n", errorBuffer);
67  return -1;
68  }
69 
70  // Open a TX hostbuffer from NUMA node of adapters location and transmit to defined TX_PORT
71  if ((status = NT_NetTxOpen(&hNetTx, "TxStreamPort", (1<<TX_PORT), NT_NETTX_NUMA_ADAPTER_HB, 0)) != NT_SUCCESS) {
72  // Get the status code as text
73  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
74  fprintf(stderr, "NT_NetTxOpen() failed: %s\n", errorBuffer);
75  return -1;
76  }
77 
78  // Optional step. Wait for the first packet that hit the NTPL assign command
79  printf("Waiting for the first packet on port %d\n", RX_PORT );
80  while (1) {
81  if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) {
82  if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) {
83  // Timeouts are ok, we just need to wait a little longer for a packet
84  continue;
85  }
86  // Get the status code as text
87  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
88  fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer);
89  return -1;
90  }
91  // We got a packet. Check if the timestamp is newer than when the NTPL assign command was applied
92  if (NT_NET_GET_PKT_TIMESTAMP(hNetBuf) > ntplInfo.ts) {
93  break; // Break out, we have received a packet that is received after the NTPL assign command was applied
94  }
95  // Release the packet, it is too "old".
96  if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) {
97  // Get the status code as text
98  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
99  fprintf(stderr, "NT_NetRxRelease() failed: %s\n", errorBuffer);
100  return -1;
101  }
102  }
103 
104  struct __vlan_tag {
105  uint16_t tpid;
106  uint16_t tci;
107  } vlan_tag[3] = {{0x8100,0x0001},{0x8100,0x0002},{0x8100,0x0003}};
108  int vlantag=1;
109 
110 
111 //The fixed parts of the fragment structure for a TX-packet must be completed before the “forward loop”:
112  addPacketFragmentList[0].size = 6+6; // macDst(6),macSrc(6)
113  addPacketFragmentList[1].data = (uint8_t*) &vlan_tag[ vlantag ];
114  addPacketFragmentList[1].size = 2+2; // VLAN : TPID(2), TCI(2)
115 
116  //Enter the Get/addPacket loop
117  while (1) {
118 
119  struct _mac {
120  uint8_t dst[6];
121  uint8_t src[6];
122  uint16_t typelen;
123  } *mac = (struct _mac*) NT_NET_GET_PKT_L2_PTR(hNetBuf);
124  size = NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf);
125 #if 0
126  printf("%6s %016llX - %04d - %02X:%02X:%02X:%02X:%02X:%02X %02X:%02X:%02X:%02X:%02X:%02X %04x\n",
127  (NT_NET_GET_PKT_DESCRIPTOR_TYPE(hNetBuf)==NT_PACKET_DESCRIPTOR_TYPE_PCAP?"PCAP":
128  NT_NET_GET_PKT_DESCRIPTOR_TYPE(hNetBuf)==NT_PACKET_DESCRIPTOR_TYPE_NT?"NT":
129  NT_NET_GET_PKT_DESCRIPTOR_TYPE(hNetBuf)==NT_PACKET_DESCRIPTOR_TYPE_NT_EXTENDED?"NT_EXT":"Unknown"),
130  (unsigned long long)NT_NET_GET_PKT_TIMESTAMP(hNetBuf),
131  size/*NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf)*/,
132  mac->dst[0], mac->dst[1], mac->dst[2], mac->dst[3], mac->dst[4], mac->dst[5],
133  mac->src[0], mac->src[1], mac->src[2], mac->src[3], mac->src[4], mac->src[5],
134  mac->typelen);
135 #endif
136  addPacketFragmentList[0].data = (uint8_t*) mac;
137  addPacketFragmentList[2].data = (uint8_t*) (addPacketFragmentList[0].data + addPacketFragmentList[0].size);
138  addPacketFragmentList[2].size = (uint16_t)(size - (6+6 + 2+2)); //-FCS
139 
140  // Send the packet including the new data(VLAN). Wait forever on TX packet buffer
141  if ((status =NT_NetTxAddPacket(hNetTx, TX_PORT, addPacketFragmentList, 3, -1) != NT_SUCCESS)) {
142  // Get the status code as text
143  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
144  fprintf(stderr, "NT_NetTxAddPacket() failed: %s\n", errorBuffer);
145  return -1;
146  }
147 
148  // Increment the number of packets processed.
149  numPackets++;
150 #if 0
151  // Increment the bytes received
152  numBytes+=NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf);
153 
154  size= NT_NET_GET_PKT_WIRE_LENGTH(hNetBuf);
155  printf("size: %04d", size);
156 #endif
157 
158  // Release the current packet
159  if ((status = NT_NetRxRelease(hNetRx, hNetBuf)) != NT_SUCCESS) {
160  // Get the status code as text
161  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
162  fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer);
163  return -1;
164  }
165 
166  // Dump packet info. Stop when (DumpStop) packets has been received
167  if (numPackets == PACKETS) {
168  if (!(PACKETS == 0))
169  break;
170  }
171 
172  // Get the next packet
173  while (1) {
174  if ((status = NT_NetRxGet(hNetRx, &hNetBuf, 1000)) != NT_SUCCESS) {
175  if ((status == NT_STATUS_TIMEOUT) || (status == NT_STATUS_TRYAGAIN)) {
176  // Timeouts are ok, we just need to wait a little longer for a packet
177  continue;
178  }
179  // Get the status code as text
180  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
181  fprintf(stderr, "NT_NetRxGet() failed: %s\n", errorBuffer);
182  return -1;
183  }
184  break; // We got a packet
185  }
186  }
187 
188  // Delete the filter
189  snprintf(ntplStr, sizeof(ntplStr), "delete=%d", ntplInfo.ntplId);
190  if ((status = NT_NTPL(hCfgStream, ntplStr, &ntplInfo, NT_NTPL_PARSER_VALIDATE_NORMAL)) != NT_SUCCESS) {
191  // Get the status code as text
192  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
193  fprintf(stderr, "NT_NTPL() failed: %s\n", errorBuffer);
194  fprintf(stderr, ">>> NTPL errorcode: %X\n", ntplInfo.u.errorData.errCode);
195  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[0]);
196  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[1]);
197  fprintf(stderr, ">>> %s\n", ntplInfo.u.errorData.errBuffer[2]);
198  return -1;
199  }
200 
201  // Close the config stream
202  if ((status = NT_ConfigClose(hCfgStream)) != NT_SUCCESS) {
203  // Get the status code as text
204  NT_ExplainError(status, errorBuffer, sizeof(errorBuffer));
205  fprintf(stderr, "NT_ConfigClose() failed: %s\n", errorBuffer);
206  return -1;
207  }
208 
209  // Close the stream and release the hostbuffer. This will also remove the NTPL assignments performed.
210  NT_NetRxClose(hNetRx);
211  // Close the TX stream
212  NT_NetTxClose(hNetTx);
213 
214  return 0;
215 }