Skip to content

Commit c0c8c56

Browse files
committed
CTT - Update NDP input plugin
1 parent 0006711 commit c0c8c56

File tree

2 files changed

+109
-4
lines changed

2 files changed

+109
-4
lines changed

input/ndp.cpp

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,42 @@
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

3745
namespace 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+
3960
telemetry::Content NdpPacketReader::get_queue_telemetry()
4061
{
4162
telemetry::Dict dict;
4263
dict["received_packets"] = m_stats.receivedPackets;
4364
dict["received_bytes"] = m_stats.receivedBytes;
65+
dict["bad_metadata"] = m_stats.bad_metadata;
4466
return dict;
4567
}
4668

@@ -71,21 +93,72 @@ void NdpPacketReader::init(const char *params)
7193
if (parser.m_dev.empty()) {
7294
throw PluginError("specify device path");
7395
}
96+
if (parser.m_metadata == "ctt") {
97+
m_ctt_metadata = true;
98+
}
7499
init_ifc(parser.m_dev);
100+
m_device = parser.m_dev;
75101
}
76102

77103
void NdpPacketReader::close()
78104
{
79105
ndpReader.close();
80106
}
81107

108+
#ifdef WITH_CTT
109+
std::pair<std::string, unsigned> NdpPacketReader::get_ctt_config() const
110+
{
111+
std::string dev = m_device;
112+
int channel_id = 0;
113+
std::size_t delimiter_found = m_device.find_last_of(":");
114+
if (delimiter_found != std::string::npos) {
115+
std::string channel_str = m_device.substr(delimiter_found + 1);
116+
dev = m_device.substr(0, delimiter_found);
117+
channel_id = std::stoi(channel_str);
118+
}
119+
return std::make_pair(dev, channel_id);
120+
}
121+
#endif /* WITH_CTT */
122+
82123
void NdpPacketReader::init_ifc(const std::string &dev)
83124
{
84125
if (ndpReader.init_interface(dev) != 0) {
85126
throw PluginError(ndpReader.error_msg);
86127
}
87128
}
88129

130+
int NdpPacketReader::parse_ctt_metadata(const ndp_packet *ndp_packet, Metadata_CTT &ctt)
131+
{
132+
if (ndp_packet->header_length != 32) {
133+
return -1;
134+
}
135+
const uint8_t *metadata = ndp_packet->header;
136+
137+
ctt.ts.tv_usec = extract(metadata, 0, 32);
138+
ctt.ts.tv_sec = extract(metadata, 32, 32);
139+
ctt.vlan_tci = extract(metadata, 64, 16);
140+
ctt.vlan_vld = extract(metadata, 80, 1);
141+
ctt.vlan_stripped = extract(metadata, 81, 1);
142+
ctt.ip_csum_status = static_cast<CsumStatus>(extract(metadata, 82, 2));
143+
ctt.l4_csum_status = static_cast<CsumStatus>(extract(metadata, 84, 2));
144+
ctt.parser_status = static_cast<ParserStatus>(extract(metadata, 86, 2));
145+
ctt.ifc = extract(metadata, 88, 8);
146+
ctt.filter_bitmap = extract(metadata, 96, 16);
147+
ctt.ctt_export_trig = extract(metadata, 112, 1);
148+
ctt.ctt_rec_matched = extract(metadata, 113, 1);
149+
ctt.ctt_rec_created = extract(metadata, 114, 1);
150+
ctt.ctt_rec_deleted = extract(metadata, 115, 1);
151+
ctt.flow_hash = extract(metadata, 128, 64);
152+
ctt.l2_len = extract(metadata, 192, 7);
153+
ctt.l3_len = extract(metadata, 199, 9);
154+
ctt.l4_len = extract(metadata, 208, 8);
155+
ctt.l2_ptype = static_cast<L2PType>(extract(metadata, 216, 4));
156+
ctt.l3_ptype = static_cast<L3PType>(extract(metadata, 220, 4));
157+
ctt.l4_ptype = static_cast<L4PType>(extract(metadata, 224, 4));
158+
159+
return 0;
160+
}
161+
89162
InputPlugin::Result NdpPacketReader::get(PacketBlock &packets)
90163
{
91164
parser_opt_t opt = {&packets, false, false, 0};
@@ -107,7 +180,26 @@ InputPlugin::Result NdpPacketReader::get(PacketBlock &packets)
107180
throw PluginError(ndpReader.error_msg);
108181
}
109182
read_pkts++;
110-
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
183+
#ifdef WITH_CTT
184+
if (m_ctt_metadata) {
185+
Metadata_CTT ctt;
186+
auto flags = ndp_packet->flags;
187+
int ret = parse_ctt_metadata(ndp_packet, ctt);
188+
if (ret == -1) {
189+
m_stats.bad_metadata++;
190+
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
191+
} else {
192+
if (parse_packet_ctt_metadata(&opt, m_parser_stats, ctt, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length) == -1) {
193+
m_stats.bad_metadata++;
194+
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
195+
}
196+
}
197+
} else {
198+
#endif /* WITH_CTT */
199+
parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length);
200+
#ifdef WITH_CTT
201+
}
202+
#endif /* WITH_CTT */
111203
}
112204

113205
m_seen += read_pkts;

input/ndp.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
#ifndef IPXP_INPUT_NDP_HPP
3131
#define IPXP_INPUT_NDP_HPP
3232

33+
#include <bits/types/struct_timeval.h>
3334
#include <ndpreader.hpp>
3435

3536
#include <ipfixprobe/input.hpp>
3637
#include <ipfixprobe/packet.hpp>
3738
#include <ipfixprobe/options.hpp>
3839
#include <ipfixprobe/utils.hpp>
40+
#include <ipfixprobe/cttmeta.hpp>
3941

4042
namespace ipxp {
4143

@@ -44,13 +46,14 @@ class NdpOptParser : public OptionsParser
4446
public:
4547
std::string m_dev;
4648
uint64_t m_id;
49+
std::string m_metadata;
4750

48-
NdpOptParser() : OptionsParser("ndp", "Input plugin for reading packets from a ndp device"), m_dev(""), m_id(0)
51+
NdpOptParser() : OptionsParser("ndp", "Input plugin for reading packets from a ndp device"), m_dev(""), m_id(0), m_metadata("")
4952
{
5053
register_option("d", "dev", "PATH", "Path to a device file", [this](const char *arg){m_dev = arg; return true;}, OptionFlags::RequiredArgument);
5154
register_option("I", "id", "NUM", "Link identifier number",
52-
[this](const char *arg){try {m_id = str2num<decltype(m_id)>(arg);} catch(std::invalid_argument &e) {return false;} return true;},
53-
OptionFlags::RequiredArgument);
55+
[this](const char *arg){try {m_id = str2num<decltype(m_id)>(arg);} catch(std::invalid_argument &e) {return false;} return true;}, OptionFlags::RequiredArgument);
56+
register_option("M", "meta", "Metadata type", "Choose metadata type if any", [this](const char *arg){m_metadata = arg; return true;}, OptionFlags::RequiredArgument);
5457
}
5558
};
5659

@@ -70,18 +73,28 @@ class NdpPacketReader : public InputPlugin
7073
std::shared_ptr<telemetry::Directory> plugin_dir,
7174
std::shared_ptr<telemetry::Directory> queues_dir) override;
7275

76+
#ifdef WITH_CTT
77+
virtual std::pair<std::string, unsigned> get_ctt_config() const override;
78+
#endif /* WITH_CTT */
79+
7380
private:
7481
struct RxStats {
7582
uint64_t receivedPackets;
7683
uint64_t receivedBytes;
84+
uint64_t bad_metadata;
7785
};
7886

7987
telemetry::Content get_queue_telemetry();
8088

8189
NdpReader ndpReader;
8290
RxStats m_stats = {};
8391

92+
bool m_ctt_metadata = false;
93+
94+
std::string m_device;
95+
8496
void init_ifc(const std::string &dev);
97+
int parse_ctt_metadata(const ndp_packet *ndp_packet, Metadata_CTT &ctt);
8598
};
8699

87100
}

0 commit comments

Comments
 (0)