Skip to content

Commit 0f52d43

Browse files
authored
Merge pull request #182 from CESNET/mpls-plugin
Mpls plugin
2 parents 3477f26 + dc767f4 commit 0f52d43

File tree

7 files changed

+224
-2
lines changed

7 files changed

+224
-2
lines changed

Makefile.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ ipfixprobe_process_src=\
134134
process/nettisa.hpp \
135135
process/nettisa.cpp \
136136
process/flow_hash.hpp \
137-
process/flow_hash.cpp
137+
process/flow_hash.cpp \
138+
process/mpls.hpp \
139+
process/mpls.cpp
138140

139141
if WITH_QUIC
140142
ipfixprobe_process_src+=\

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,14 @@ List of fields exported together with basic flow fields on interface by flow_has
651651
|:------------------:|:------:|:---------------------------------:|
652652
| FLOW_ID | uint64 | Hash of the flow - unique flow id |
653653

654+
### MPLS
655+
656+
List of fields exported together with basic flow fields on interface by mpls plugin.
657+
658+
| Output field | Type | Description |
659+
|:----------------------------:|:-----:|:------------------------------------------------:|
660+
| MPLS_TOP_LABEL_STACK_SECTION | bytes | MPLS label section (without TTL), always 3 bytes |
661+
654662
## Simplified function diagram
655663
Diagram below shows how `ipfixprobe` works.
656664

include/ipfixprobe/ipfix-elements.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ namespace ipxp {
277277
#define NTS_TIME_DISTRIBUTION(F) F(8057, 1031, 4, nullptr)
278278
#define NTS_SWITCHING_RATIO(F) F(8057, 1032, 4, nullptr)
279279

280+
#define MPLS_TOP_LABEL_STACK_SECTION F(0, 70, -1, nullptr)
281+
280282

281283
/**
282284
* IPFIX Templates - list of elements
@@ -534,6 +536,9 @@ namespace ipxp {
534536
#define IPFIX_FLOW_HASH_TEMPLATE(F) \
535537
F(FLOW_ID)
536538

539+
#define IPFIX_MPLS_TEMPLATE(F) \
540+
F(MPLS_TOP_LABEL_STACK_SECTION)
541+
537542
#ifdef WITH_FLEXPROBE
538543
#define IPFIX_FLEXPROBE_DATA_TEMPLATE(F) F(FX_FRAME_SIGNATURE) F(FX_INPUT_INTERFACE)
539544
#define IPFIX_FLEXPROBE_TCP_TEMPLATE(F) F(FX_TCP_TRACKING)

include/ipfixprobe/packet.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ struct Packet : public Record {
7070
uint32_t tcp_seq;
7171
uint32_t tcp_ack;
7272

73+
/**
74+
* @brief The top level mpls
75+
*
76+
* Contents are (from MSb to LSb):
77+
* 20-bit - Label,
78+
* 3-bit - Traffic class / EXP,
79+
* 1-bit - Bottom of stack (true if last),
80+
* 8-bit - TTL (Time To Live)
81+
*/
82+
uint32_t mplsTop;
83+
7384
const uint8_t *packet; /**< Pointer to begin of packet, if available */
7485
uint16_t packet_len; /**< Length of data in packet buffer, packet_len <= packet_len_wire */
7586
uint16_t packet_len_wire; /**< Original packet length on wire */
@@ -96,7 +107,7 @@ struct Packet : public Record {
96107
ip_len(0), ip_payload_len(0), ip_version(0), ip_ttl(0),
97108
ip_proto(0), ip_tos(0), ip_flags(0), src_ip({0}), dst_ip({0}), vlan_id(0),
98109
src_port(0), dst_port(0), tcp_flags(0), tcp_window(0),
99-
tcp_options(0), tcp_mss(0), tcp_seq(0), tcp_ack(0),
110+
tcp_options(0), tcp_mss(0), tcp_seq(0), tcp_ack(0), mplsTop(0),
100111
packet(nullptr), packet_len(0), packet_len_wire(0),
101112
payload(nullptr), payload_len(0), payload_len_wire(0),
102113
custom(nullptr), custom_len(0),

input/parser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ uint16_t process_mpls_stack(const u_char *data_ptr, uint16_t data_len)
568568
uint16_t process_mpls(const u_char *data_ptr, uint16_t data_len, Packet *pkt)
569569
{
570570
Packet tmp;
571+
pkt->mplsTop = ntohl(*reinterpret_cast<const uint32_t *>(data_ptr));
571572
uint16_t length = process_mpls_stack(data_ptr, data_len);
572573
uint8_t next_hdr = (*(data_ptr + length) & 0xF0) >> 4;
573574

@@ -656,6 +657,7 @@ void parse_packet(parser_opt_t *opt, struct timeval ts, const uint8_t *data, uin
656657
pkt->tcp_window = 0;
657658
pkt->tcp_options = 0;
658659
pkt->tcp_mss = 0;
660+
pkt->mplsTop = 0;
659661

660662
uint32_t l3_hdr_offset = 0;
661663
uint32_t l4_hdr_offset = 0;

process/mpls.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* \file mpls.cpp
3+
* \brief Plugin for parsing mpls traffic.
4+
* \author Jakub Antonín Štigler [email protected]
5+
* \date 2023
6+
*/
7+
/*
8+
* Copyright (C) 2023 CESNET
9+
*
10+
* LICENSE TERMS
11+
*
12+
* Redistribution and use in source and binary forms, with or without
13+
* modification, are permitted provided that the following conditions
14+
* are met:
15+
* 1. Redistributions of source code must retain the above copyright
16+
* notice, this list of conditions and the following disclaimer.
17+
* 2. Redistributions in binary form must reproduce the above copyright
18+
* notice, this list of conditions and the following disclaimer in
19+
* the documentation and/or other materials provided with the
20+
* distribution.
21+
* 3. Neither the name of the Company nor the names of its contributors
22+
* may be used to endorse or promote products derived from this
23+
* software without specific prior written permission.
24+
*
25+
*
26+
*
27+
*/
28+
29+
#include <iostream>
30+
31+
#include "mpls.hpp"
32+
33+
namespace ipxp {
34+
35+
int RecordExtMPLS::REGISTERED_ID = -1;
36+
37+
__attribute__((constructor)) static void register_this_plugin()
38+
{
39+
static PluginRecord rec = PluginRecord("mpls", [](){return new MPLSPlugin();});
40+
register_plugin(&rec);
41+
RecordExtMPLS::REGISTERED_ID = register_extension();
42+
}
43+
44+
ProcessPlugin *MPLSPlugin::copy()
45+
{
46+
return new MPLSPlugin(*this);
47+
}
48+
49+
int MPLSPlugin::post_create(Flow &rec, const Packet &pkt)
50+
{
51+
if (pkt.mplsTop == 0) {
52+
return 0;
53+
}
54+
55+
auto ext = new RecordExtMPLS();
56+
ext->mpls = pkt.mplsTop;
57+
58+
rec.add_extension(ext);
59+
return 0;
60+
}
61+
62+
}
63+

process/mpls.hpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* \file mpls.hpp
3+
* \brief Plugin for parsing mpls traffic.
4+
* \author Jakub Antonín Štigler [email protected]
5+
* \date 2023
6+
*/
7+
/*
8+
* Copyright (C) 2023 CESNET
9+
*
10+
* LICENSE TERMS
11+
*
12+
* Redistribution and use in source and binary forms, with or without
13+
* modification, are permitted provided that the following conditions
14+
* are met:
15+
* 1. Redistributions of source code must retain the above copyright
16+
* notice, this list of conditions and the following disclaimer.
17+
* 2. Redistributions in binary form must reproduce the above copyright
18+
* notice, this list of conditions and the following disclaimer in
19+
* the documentation and/or other materials provided with the
20+
* distribution.
21+
* 3. Neither the name of the Company nor the names of its contributors
22+
* may be used to endorse or promote products derived from this
23+
* software without specific prior written permission.
24+
*
25+
*
26+
*
27+
*/
28+
29+
#ifndef IPXP_PROCESS_MPLS_HPP
30+
#define IPXP_PROCESS_MPLS_HPP
31+
32+
#include <cstring>
33+
#include <string>
34+
#include <sstream>
35+
36+
#ifdef WITH_NEMEA
37+
#include "fields.h"
38+
#endif
39+
40+
#include <ipfixprobe/process.hpp>
41+
#include <ipfixprobe/flowifc.hpp>
42+
#include <ipfixprobe/packet.hpp>
43+
#include <ipfixprobe/ipfix-elements.hpp>
44+
45+
namespace ipxp {
46+
47+
#define MPLS_LABEL_SECTION_LENGTH 3
48+
49+
#define MPLS_UNIREC_TEMPLATE "MPLS_TOP_LABEL_STACK_SECTION"
50+
51+
UR_FIELDS (
52+
bytes MPLS_TOP_LABEL_STACK_SECTION
53+
)
54+
55+
/**
56+
* \brief Flow record extension header for storing parsed MPLS data.
57+
*/
58+
struct RecordExtMPLS : public RecordExt {
59+
static int REGISTERED_ID;
60+
61+
// Contents are (from MSb to LSb):
62+
// 20-bit - Label,
63+
// 3-bit - Traffic class / EXP,
64+
// 1-bit - Bottom of stack (true if last),
65+
// 8-bit - TTL (Time To Live)
66+
uint32_t mpls;
67+
68+
RecordExtMPLS() : RecordExt(REGISTERED_ID), mpls(0) { }
69+
70+
#ifdef WITH_NEMEA
71+
void fill_unirec(ur_template_t *tmplt, void *record) override
72+
{
73+
auto v = htonl(mpls);
74+
auto arr = reinterpret_cast<uint8_t *>(&v);
75+
ur_set_var(tmplt, record, F_MPLS_TOP_LABEL_STACK_SECTION, arr, MPLS_LABEL_SECTION_LENGTH);
76+
}
77+
78+
const char *get_unirec_tmplt() const
79+
{
80+
return MPLS_UNIREC_TEMPLATE;
81+
}
82+
#endif
83+
84+
int fill_ipfix(uint8_t *buffer, int size) override
85+
{
86+
if (size < MPLS_LABEL_SECTION_LENGTH + 1) {
87+
return -1;
88+
}
89+
90+
buffer[0] = MPLS_LABEL_SECTION_LENGTH;
91+
auto v = htonl(mpls);
92+
auto arr = reinterpret_cast<uint8_t *>(&v);
93+
memcpy(buffer + 2, arr, MPLS_LABEL_SECTION_LENGTH);
94+
95+
return MPLS_LABEL_SECTION_LENGTH + 1;
96+
}
97+
98+
const char **get_ipfix_tmplt() const
99+
{
100+
static const char *ipfix_template[] = {
101+
IPFIX_MPLS_TEMPLATE(IPFIX_FIELD_NAMES)
102+
NULL
103+
};
104+
return ipfix_template;
105+
}
106+
107+
std::string get_text() const
108+
{
109+
std::ostringstream out;
110+
out << "mpls_label_1=\"" << (mpls >> 8) << '"';
111+
return out.str();
112+
}
113+
};
114+
115+
/**
116+
* \brief Process plugin for parsing MPLS packets.
117+
*/
118+
class MPLSPlugin : public ProcessPlugin
119+
{
120+
public:
121+
OptionsParser *get_parser() const { return new OptionsParser("mpls", "Parse MPLS traffic"); }
122+
std::string get_name() const { return "mpls"; }
123+
RecordExt *get_ext() const { return new RecordExtMPLS(); }
124+
ProcessPlugin *copy();
125+
126+
int post_create(Flow &rec, const Packet &pkt);
127+
};
128+
129+
}
130+
#endif /* IPXP_PROCESS_MPLS_HPP */
131+

0 commit comments

Comments
 (0)