2727 *
2828 */
2929
30+ #include < cstdint>
3031#include < cstdio>
3132#include < cstring>
3233#include < iostream>
34+ #include < netinet/in.h>
35+ #include < sys/types.h>
36+ #include < cstdint>
37+ #include < cstddef>
38+ #include < inttypes.h>
3339
3440#include " ndp.hpp"
41+ #include " ipfixprobe/packet.hpp"
42+ #include " ipfixprobe/plugin.hpp"
3543#include " parser.hpp"
3644
3745namespace ipxp {
3846
47+ uint64_t extract (const uint8_t * bitvec, size_t start_bit, size_t bit_length) {
48+ size_t start_byte = start_bit / 8 ;
49+ size_t end_bit = start_bit + bit_length;
50+ size_t end_byte = (end_bit + 7 ) / 8 ;
51+ uint64_t value = 0 ;
52+ for (size_t i = 0 ; i < end_byte - start_byte; ++i) {
53+ value |= static_cast <uint64_t >(bitvec[start_byte + i]) << (8 * i);
54+ }
55+ value >>= (start_bit % 8 );
56+ uint64_t mask = (bit_length == 64 ) ? ~0ULL : ((1ULL << bit_length) - 1 );
57+ return value & mask;
58+ }
59+
3960telemetry::Content NdpPacketReader::get_queue_telemetry ()
4061{
4162 telemetry::Dict dict;
@@ -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+ void NdpPacketReader::parse_ctt_metadata (const ndp_packet *ndp_packet, Metadata_CTT &ctt)
114+ {
115+ if (ndp_packet->header_length != 32 ) {
116+ throw PluginError (" Metadata bad length, cannot parse, length: " + std::to_string (ndp_packet->header_length ));
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 = extract (metadata, 82 , 2 );
126+ ctt.l4_csum_status = extract (metadata, 84 , 2 );
127+ ctt.parser_status = 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 = extract (metadata, 216 , 4 );
139+ ctt.l3_ptype = extract (metadata, 220 , 4 );
140+ ctt.l4_ptype = extract (metadata, 224 , 4 );
141+
142+ return ;
143+ }
144+
89145InputPlugin::Result NdpPacketReader::get (PacketBlock &packets)
90146{
91147 parser_opt_t opt = {&packets, false , false , 0 };
@@ -107,7 +163,30 @@ 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+ parse_ctt_metadata (ndp_packet, ctt);
169+ parse_packet (&opt, m_parser_stats, timestamp, ndp_packet->data , ndp_packet->data_length , ndp_packet->data_length );
170+
171+ Packet *pkt = &opt.pblock ->pkts [opt.pblock ->cnt - 1 ];
172+
173+ // verify metadata with original parser
174+ if (ctt.l2_len + ctt.l3_len + ctt.l4_len != pkt->packet_len - pkt->payload_len ) {
175+ printf (" Error: ctt.l2_len (%d) + ctt.l3_len (%d) + ctt.l4_len (%d) != pkt->packet_len (%d) - pkt->payload_len (%d)\n " , ctt.l2_len , ctt.l3_len , ctt.l4_len , pkt->packet_len , pkt->payload_len );
176+ }
177+ if (pkt->ip_proto == IPPROTO_TCP) {
178+ if (ctt.l4_ptype != 0x1 ) {
179+ printf (" Error: ctt.l4_ptype (%d) != 0x1 but protocol is TCP (%d)\n " , ctt.l4_ptype , pkt->ip_proto );
180+ }
181+ }
182+ if (pkt->ip_proto == IPPROTO_UDP) {
183+ if (ctt.l4_ptype != 0x2 ) {
184+ printf (" Error: ctt.l4_ptype (%d) != 0x2 but protocol is UDP (%d)\n " , ctt.l4_ptype , pkt->ip_proto );
185+ }
186+ }
187+ } else {
188+ parse_packet (&opt, m_parser_stats, timestamp, ndp_packet->data , ndp_packet->data_length , ndp_packet->data_length );
189+ }
111190 }
112191
113192 m_seen += read_pkts;
0 commit comments