Skip to content

Commit 8fc07dc

Browse files
Merge pull request #228 from CESNET/ctt-input-parse
CTT Metadata input handling
2 parents 66a57bf + 4e888b4 commit 8fc07dc

File tree

13 files changed

+3148
-10
lines changed

13 files changed

+3148
-10
lines changed

ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2024-10-17 ipfixprobe-4.13.0
2+
* usability: introduce docker/podman container to convert PCAP files to CSV
3+
* IPFIX: fix order of TCP options flags
4+
* basicplus: update TCP options mask across flow packets
5+
* utils: introduce memcpy_le32toh() for ipfix representation
6+
* wg: fix parsing and exporting byte order (IPFIX)
7+
* DPDK-ring: optimization: prefetch; read timestamp from HW metadata if available
8+
* cache: optimization - prefetch
9+
* IPv6: fix header parsing
10+
* DPDK&DPDK-ring: fix use of parse_packet(), skip invalid packets causing crash
11+
112
2024-08-28 ipfixprobe-4.12.0
213
* ipfix plugin: support lz4 compression
314
* ipfixprobe: possibility to set workers affinity

Doxyfile

Lines changed: 2819 additions & 0 deletions
Large diffs are not rendered by default.

Makefile.am

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ ipfixprobe_headers_src=\
203203
include/ipfixprobe/ipfix-elements.hpp \
204204
include/ipfixprobe/rtp.hpp \
205205
include/ipfixprobe/telemetry-utils.hpp \
206-
include/ipfixprobe/parser-stats.hpp
206+
include/ipfixprobe/parser-stats.hpp \
207+
include/ipfixprobe/cttmeta.hpp
207208

208209
ipfixprobe_src=\
209210
$(ipfixprobe_input_src) \
@@ -336,3 +337,7 @@ deb:
336337
else
337338
endif
338339

340+
.PHONY: doc
341+
doc:
342+
doxygen
343+

NEWS

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
2024-10-17 (Tomas Cejka): doc: include generated Doxyfile to create documentation
2+
2024-10-17 (Tomas Cejka): doc: add doxygen comment for parse_packet()
3+
2024-10-16 (Jan Sobol): dpdk-ring - fix checking if any packet has actually been parsed
4+
2024-10-16 (Jan Sobol): dpdk - fix checking if any packet has actually been parsed
5+
2024-10-02 (Damir Zainullin): Fix IPv6 header parsing
6+
2024-09-30 (Pavel Šiška): Merge pull request #220 from CESNET/prefetch-optimizations
7+
2024-09-30 (Pavel Šiška): Merge pull request #219 from CESNET/dpdk-ring-metadata-timestamp
8+
2024-09-30 (Pavel Šiška): Merge pull request #215 from CESNET/new-version
9+
2024-09-26 (Jan Sobol): cache - prefetch flow records before checking their expiration
10+
2024-09-26 (Jan Sobol): dpdk-ring - prefetch dequeued packets before processing
11+
2024-09-25 (Jan Sobol): dpdk-ring - read timestamp from hw metadata if available
12+
2024-09-20 (Tomas Cejka): Merge pull request #216 from CESNET/ipfixprobe-docker-wrapper
13+
2024-09-19 (Tomas Cejka): dist: include docker/ files into distribution archive
14+
2024-09-19 (Jan Sobol): wg - fix parsing and exporting byte order
15+
2024-09-19 (Jan Sobol): utils - introduce memcpy_le32toh function
16+
2024-09-18 (Jan Sobol): basicplus test - fix reference values of tcp options
17+
2024-09-18 (Jan Sobol): basicplus - update tcp options mask across flow packets
18+
2024-09-18 (Jan Sobol): parser - fix order of tcp options flags according to ipfix standard https://www.iana.org/assignments/ipfix/ipfix.xhtml, entity 209 - tcpOptions
19+
2024-09-17 (Jaroslav Pesek): process container - introduce docker/podman container wrapper for processing pcaps to csvs
20+
121
2024-08-28 (Pavel Siska): ipfixprobed - add new option LZ4_COMPRESSION to init script and config example
222
2024-08-28 (Pavel Siska): README.md - add LZ4 compression info
323
2024-08-28 (Jakub Antonín Štigler): ipfix plugin: add lz4 compression

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Process this file with autoconf to produce a configure script.
33

44
AC_PREREQ([2.69])
5-
AC_INIT([ipfixprobe], [4.12.0], [[email protected]])
5+
AC_INIT([ipfixprobe], [4.13.0], [[email protected]])
66

77
AC_CONFIG_SRCDIR([main.cpp])
88
AC_CONFIG_HEADERS([config.h])

include/ipfixprobe/cttmeta.hpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#ifndef IPXP_INPUT_CTT_HPP
2+
#define IPXP_INPUT_CTT_HPP
3+
4+
#include <bits/types/struct_timeval.h>
5+
#include <cstdint>
6+
7+
namespace ipxp {
8+
9+
enum CsumStatus : uint8_t {
10+
CSUM_UNKNOWN = 0x0, ///< No information about the checksum
11+
CSUM_BAD = 0x1, ///< The checksum in the packet is wrong
12+
CSUM_GOOD = 0x2, ///< The checksum in the packet is valid
13+
CSUM_NONE = 0x3 ///< Checksum not correct but header integrity verified
14+
};
15+
16+
enum ParserStatus : uint8_t {
17+
PA_OK = 0x0, ///< Parsing completed successfully
18+
PA_UNKNOWN = 0x1, ///< Parser stopped at an unknown protocol
19+
PA_LIMIT = 0x2, ///< Parser stopped at its own limit (e.g., VLAN=4)
20+
PA_ERROR = 0x3 ///< Error in protocol header or parsing overflow
21+
};
22+
23+
enum L2PType : uint8_t {
24+
L2_UNKNOWN = 0x0, ///< Unknown L2 protocol
25+
L2_ETHER_IP = 0x1, ///< Ethernet with IP payload
26+
L2_ETHER_TIMESYNC = 0x2, ///< Ethernet with TimeSync protocol
27+
L2_ETHER_ARP = 0x3, ///< Ethernet with ARP protocol
28+
L2_ETHER_LLDP = 0x4, ///< Ethernet with LLDP protocol
29+
L2_ETHER_NSH = 0x5, ///< Ethernet with NSH protocol
30+
L2_ETHER_VLAN = 0x6, ///< Ethernet with VLAN tagging
31+
L2_ETHER_QINQ = 0x7, ///< Ethernet with QinQ tagging
32+
L2_ETHER_PPPOE = 0x8, ///< Ethernet with PPPoE encapsulation
33+
L2_ETHER_FCOE = 0x9, ///< Ethernet with FCoE protocol
34+
L2_ETHER_MPLS = 0xA ///< Ethernet with MPLS
35+
};
36+
37+
enum L3PType : uint8_t {
38+
L3_UNKNOWN = 0x0, ///< Unknown L3 protocol
39+
L3_IPV4 = 0x1, ///< IPv4 protocol
40+
L3_IPV4_EXT = 0x3, ///< IPv4 with extensions
41+
L3_IPV6 = 0x4, ///< IPv6 protocol
42+
L3_IPV6_EXT = 0xC ///< IPv6 with extensions
43+
};
44+
45+
enum L4PType : uint8_t {
46+
L4_UNKNOWN = 0x0, ///< Unknown L4 protocol
47+
L4_TCP = 0x1, ///< TCP protocol
48+
L4_UDP = 0x2, ///< UDP protocol
49+
L4_FRAG = 0x3, ///< Fragmented packet
50+
L4_SCTP = 0x4, ///< SCTP protocol
51+
L4_ICMP = 0x5, ///< ICMP protocol
52+
L4_NONFRAG = 0x6, ///< Non-fragmented packet
53+
L4_IGMP = 0x7 ///< IGMP protocol
54+
};
55+
56+
struct Metadata_CTT {
57+
struct timeval ts; ///< Timestamp; invalid if all bits are 1
58+
uint16_t vlan_tci; ///< VLAN Tag Control Information from outer VLAN
59+
bool vlan_vld : 1; ///< VLAN valid flag; indicates if VLAN TCI is valid
60+
bool vlan_stripped : 1; ///< VLAN stripped flag; outer VLAN only
61+
CsumStatus ip_csum_status : 2; ///< IP checksum status
62+
CsumStatus l4_csum_status : 2; ///< Layer 4 checksum status
63+
ParserStatus parser_status : 2;///< Final state of FPGA parser
64+
uint8_t ifc; ///< Interface (IFC) number
65+
uint16_t filter_bitmap; ///< Filter bitmap; each filter rule can have several mark bits
66+
bool ctt_export_trig : 1; ///< CTT flag; packet triggered export in CTT
67+
bool ctt_rec_matched : 1; ///< CTT flag; packet matched record in CTT
68+
bool ctt_rec_created : 1; ///< CTT flag; packet created record in CTT
69+
bool ctt_rec_deleted : 1; ///< CTT flag; packet deleted record in CTT
70+
uint64_t flow_hash; ///< Flow hash; not the same as RSS hash
71+
uint8_t l2_len : 7; ///< Length of the L2 layer, if known
72+
uint16_t l3_len : 9; ///< Length of the L3 layer, if known
73+
uint8_t l4_len : 8; ///< Length of the L4 layer, if known
74+
L2PType l2_ptype : 4; ///< Type of the L2 layer
75+
L3PType l3_ptype : 4; ///< Type of the L3 layer
76+
L4PType l4_ptype : 4; ///< Type of the L4 layer
77+
};
78+
79+
}
80+
81+
#endif // IPXP_INPUT_CTT_HPP

include/ipfixprobe/packet.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@
3838

3939
#include <ipfixprobe/ipaddr.hpp>
4040
#include <ipfixprobe/flowifc.hpp>
41+
#include <ipfixprobe/cttmeta.hpp>
4142

4243
namespace ipxp {
4344

4445
/**
4546
* \brief Structure for storing parsed packet fields
4647
*/
4748
struct Packet : public Record {
49+
Metadata_CTT cttmeta; /**< Metadata from CTT */
4850
struct timeval ts;
4951

5052
uint8_t dst_mac[6];

input/dpdk-ring.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ InputPlugin::Result DpdkRingReader::get(PacketBlock& packets)
211211
m_stats.receivedPackets += pkts_read_;
212212
m_stats.receivedBytes += packets.bytes;
213213

214-
return Result::PARSED;
214+
return opt.pblock->cnt ? Result::PARSED : Result::NOT_PARSED;
215215
}
216216

217217
telemetry::Content DpdkRingReader::get_queue_telemetry()

input/dpdk.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ InputPlugin::Result DpdkReader::get(PacketBlock& packets)
292292
m_stats.receivedPackets += receivedPackets;
293293
m_stats.receivedBytes += packets.bytes;
294294

295-
return Result::PARSED;
295+
return packets.cnt ? Result::PARSED : Result::NOT_PARSED;
296296
}
297297

298298
}

input/ndp.cpp

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,41 @@
2727
*
2828
*/
2929

30+
#include <cstdint>
3031
#include <cstdio>
3132
#include <cstring>
32-
#include <iostream>
33+
#include <netinet/in.h>
34+
#include <sys/types.h>
35+
#include <cstdint>
36+
#include <cstddef>
37+
#include <inttypes.h>
3338

3439
#include "ndp.hpp"
40+
#include "ipfixprobe/packet.hpp"
41+
#include "ipfixprobe/plugin.hpp"
3542
#include "parser.hpp"
3643

3744
namespace ipxp {
3845

46+
uint64_t extract(const uint8_t* bitvec, size_t start_bit, size_t bit_length) {
47+
size_t start_byte = start_bit / 8;
48+
size_t end_bit = start_bit + bit_length;
49+
size_t end_byte = (end_bit + 7) / 8;
50+
uint64_t value = 0;
51+
for (size_t i = 0; i < end_byte - start_byte; ++i) {
52+
value |= static_cast<uint64_t>(bitvec[start_byte + i]) << (8 * i);
53+
}
54+
value >>= (start_bit % 8);
55+
uint64_t mask = (bit_length == 64) ? ~0ULL : ((1ULL << bit_length) - 1);
56+
return value & mask;
57+
}
58+
3959
telemetry::Content NdpPacketReader::get_queue_telemetry()
4060
{
4161
telemetry::Dict dict;
4262
dict["received_packets"] = m_stats.receivedPackets;
4363
dict["received_bytes"] = m_stats.receivedBytes;
64+
dict["bad_metadata"] = m_stats.bad_metadata;
4465
return dict;
4566
}
4667

@@ -71,6 +92,9 @@ void NdpPacketReader::init(const char *params)
7192
if (parser.m_dev.empty()) {
7293
throw PluginError("specify device path");
7394
}
95+
if (parser.m_metadata == "ctt") {
96+
m_ctt_metadata = true;
97+
}
7498
init_ifc(parser.m_dev);
7599
}
76100

@@ -86,6 +110,38 @@ void NdpPacketReader::init_ifc(const std::string &dev)
86110
}
87111
}
88112

113+
int NdpPacketReader::parse_ctt_metadata(const ndp_packet *ndp_packet, Metadata_CTT &ctt)
114+
{
115+
if (ndp_packet->header_length != 32) {
116+
return -1;
117+
}
118+
const uint8_t *metadata = ndp_packet->header;
119+
120+
ctt.ts.tv_usec = extract(metadata, 0, 32);
121+
ctt.ts.tv_sec = extract(metadata, 32, 32);
122+
ctt.vlan_tci = extract(metadata, 64, 16);
123+
ctt.vlan_vld = extract(metadata, 80, 1);
124+
ctt.vlan_stripped = extract(metadata, 81, 1);
125+
ctt.ip_csum_status = static_cast<CsumStatus>(extract(metadata, 82, 2));
126+
ctt.l4_csum_status = static_cast<CsumStatus>(extract(metadata, 84, 2));
127+
ctt.parser_status = static_cast<ParserStatus>(extract(metadata, 86, 2));
128+
ctt.ifc = extract(metadata, 88, 8);
129+
ctt.filter_bitmap = extract(metadata, 96, 16);
130+
ctt.ctt_export_trig = extract(metadata, 112, 1);
131+
ctt.ctt_rec_matched = extract(metadata, 113, 1);
132+
ctt.ctt_rec_created = extract(metadata, 114, 1);
133+
ctt.ctt_rec_deleted = extract(metadata, 115, 1);
134+
ctt.flow_hash = extract(metadata, 128, 64);
135+
ctt.l2_len = extract(metadata, 192, 7);
136+
ctt.l3_len = extract(metadata, 199, 9);
137+
ctt.l4_len = extract(metadata, 208, 8);
138+
ctt.l2_ptype = static_cast<L2PType>(extract(metadata, 216, 4));
139+
ctt.l3_ptype = static_cast<L3PType>(extract(metadata, 220, 4));
140+
ctt.l4_ptype = static_cast<L4PType>(extract(metadata, 224, 4));
141+
142+
return 0;
143+
}
144+
89145
InputPlugin::Result NdpPacketReader::get(PacketBlock &packets)
90146
{
91147
parser_opt_t opt = {&packets, false, false, 0};
@@ -107,7 +163,18 @@ InputPlugin::Result NdpPacketReader::get(PacketBlock &packets)
107163
throw PluginError(ndpReader.error_msg);
108164
}
109165
read_pkts++;
110-
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
166+
if (m_ctt_metadata) {
167+
Metadata_CTT ctt;
168+
int ret = parse_ctt_metadata(ndp_packet, ctt);
169+
if (ret == -1) {
170+
m_stats.bad_metadata++;
171+
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
172+
} else {
173+
parse_packet_ctt_metadata(&opt, m_parser_stats, ctt, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
174+
}
175+
} else {
176+
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
177+
}
111178
}
112179

113180
m_seen += read_pkts;

0 commit comments

Comments
 (0)