Use this example to handle unknown packets and learn them.
Once a flow stream to the SmartNIC has been established, flow learn records can be send to the SmartNIC via the NT_FlowWrite function. Flow learn records are implemented as the c-style structure NtFlow_t. The snippet below shows how a flow learn record is filled from a received packet from RX stream ID 1.
The flow learn record contains all relevant information for the flow manager, which includes IPv4 TCP data, and the Key ID that ties the flow learn record to the NTPL Assign command. It is important to note the gfi field is set to 1; this will cause flow info records to be generated when the flow is unlearned. Flow info records are discussed in following sections.
uint64_t idCounter = 0; uint32_t streamId = 1; NtNetStreamRx_t hNetRx; NtNetBuf_t hNetBuffer; // While not included here, it is needed to open a stream with // StreamId=1 for hNetRx before the while loop. while( /* Check application should continue */ ) { // Get package from rx stream. status = NT_NetRxGetNextPacket(hNetRx, &hNetBuffer, 100); if(status == NT_STATUS_TIMEOUT || status == NT_STATUS_TRYAGAIN) continue; if(status != NT_SUCCESS) { /* Handle error */ } // For this example the descriptor DYN3 is used, which is set up via NTPL. NtDyn4Descr_t* dyn4 = _NT_NET_GET_PKT_DESCR_PTR_DYN4(hNetBuffer); uint8_t* packet = reinterpret_cast<uint8_t*>(dyn4) + dyn4->descrLength; // In this example, the ID is a simple incremental value; // however, any value can be used, including the raw value of pointers. NtFlow_t flow; std::memset(&flow, 0x0, sizeof(NtFlow_t)); flow.id = idCounter++; // User defined ID flow.color = 0; // Flow color flow.ipProtocolField = 6; // IP protocol number of next header (6: TCP) flow.keyId = 1; // Key ID as used in the NTPL Key Test flow.keySetId = 4; // Ket Set ID as used in the NTPL filter flow.op = 1; // Flow programming operation flow.gfi = 1; // Generate flow info record flow.tau = 1; // TCP auto unlearn // The NTPL filters in this snippet set up an alternative offset0, // such that it points directly to the IP source address. std::memcpy(flow.keyData, packet + dyn4->offset0, 4); // IPv4 src std::memcpy(flow.keyData + 4, packet + dyn4->offset0 + 4, 4); // IPv4 dst std::memcpy(flow.keyData + 8, packet + dyn4->offset1, 2); // TCP port src std::memcpy(flow.keyData + 10, packet + dyn4->offset1 + 2, 2); // TCP port dst // Program the flow into the adapter. status = NT_FlowWrite(flowStream, &flow, -1); if(status != NT_SUCCESS) { /* Handle error */ } }