Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sFlow for tunnels: Tunnel extension & IPv6 encapsulation support #574

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

simonschdev
Copy link

Hi Peter, we have another suggestion for tunneling support in sFlow, building on our previous pull request.

Let us know what you think! :)

Background

Motivated by pull request #559, sfcapd was recently extended with the capability to parse the nested headers used in GRE tunnels. Given the new command-line option -o gre, sfcapd will consider the innermost header stack (i.e., the tunneled flow) to be relevant for the stored flow information. In absence of that command-line option, the outermost header stack (i.e., the tunneling flow) is considered critical.

Problem

While being a valuable first step, previous sfcapd tunnel functionality would benefit from the following two extensions:

  • Complete tunnel information: The current command-line option forces the user to choose between analyzing the tunneled flow and analyzing the tunneling flow. However, it is often interesting to know which tunnels encapsulated which flows, and thus to store the combination of the tunneling flow and tunneled flow.
  • IPv6 encapsulation support: To tunnel IPv6 traffic in IPv4 traffic, using GRE for tunneling is actually unnecessary, as IPv6 encapsulation (IP protocol number 41, e.g. 6to4 and 6in4) allows to simply concatenate an IPv4 header and an IPv6 header (without intermediate GRE header). Since such encapsulation tunnels might thus appear frequently in practice, sfcapd support for such IPv6 encapsulation would be desirable.

Solution approach

We implement the extensions mentioned above as follows:

  • Complete tunnel information: The information from the outermost IP header is stored in the already existing tunnel extension, which was already suggested in the discussion of pull request GRE tunnel introspection for sFlow #559.
  • IPv6 encapsulation support: Upon discovery of an IP header with protocol number 41, the header parsing is restarted recursively after that header - analogously to the parsing behavior upon discovery of a GRE header. The user can now use the option 6in4 (i.e., with -o 6in4) to convey that the parsing should advance beyond encapsulation headers.

Result & Tests

For demonstations, we provide a PCAP file (extended with a 6in4 flow compared to pull request #559), containing sFlow records for 6 different flows that are encapsulated in an IP flow from 1.1.1.1 to 2.2.2.2. When recording these packets with sfcapd using -o gre,6in4 , nfdump now shows the following records:

Date first seen         Duration         Proto      Src IP Addr:Port          Dst IP Addr:Port   Packets    Bytes Flows
2024-11-01 16:24:19.768     00:00:00.000 GRE            1.1.1.1:53    ->          2.2.2.2:53           1       84     1
2024-11-01 16:24:19.768     00:00:00.000 UDP            3.3.3.3:53    ->          4.4.4.4:53           1       84     1
2024-11-01 16:24:19.768     00:00:00.000 GRE            1.1.1.1:53    ->          2.2.2.2:53           1       70     1
2024-11-01 16:24:19.768     00:00:00.000 UDP            5.5.5.5:53    ->          6.6.6.6:53           1       70     1
2024-11-01 16:24:19.768     00:00:00.000 GRE            1.1.1.1:53    ->          2.2.2.2:53           1       90     1
2024-11-01 16:24:19.768     00:00:00.000 UDP    7:7:7:7:7:7:7:7.53    ->  8:8:8:8:8:8:8:8.53           1       90     1
2024-11-01 16:24:19.768     00:00:00.000 GRE            1.1.1.1:53    ->          2.2.2.2:53           1      106     1
2024-11-01 16:24:19.768     00:00:00.000 UDP        11.11.11.11:53    ->      12.12.12.12:53           1      106     1
2024-11-01 16:24:19.768     00:00:00.000 GRE            1.1.1.1:0     ->          2.2.2.2:0            1       42     1
2024-11-01 16:24:19.768     00:00:00.000 IPv6           1.1.1.1:53    ->          2.2.2.2:53           1       86     1
2024-11-01 16:24:19.768     00:00:00.000 UDP   13:13:1..3:13:13.53    -> 14:14:1..4:14:14.53           1       86     1

(The third-to-last flow record comes from a pathological packet with an empty GRE payload).

Moreover, all tests run with make check still pass.

Contributors

This pull request is proposed by Simon Scherrer from NetFabric.ai.

@phaag
Copy link
Owner

phaag commented Dec 13, 2024

Thanks Simon. I will review the patch.

@phaag phaag self-assigned this Dec 13, 2024
@phaag phaag added enhancement improve code, speed, quality Feature request Feature request labels Dec 13, 2024
@phaag
Copy link
Owner

phaag commented Dec 28, 2024

I would propose to merge to two options "gre" and "6in4" into a more generic option "tunnel". That would offer more flexibility for future tunnel decoding '4in6' or whatever would be proposed. The single option should not cause conflicts in my view.
Any remarks on that?

Copy link
Owner

@phaag phaag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Propose one single option parse_tunnel to include all current and future tunnel decodings.

@@ -96,7 +96,7 @@ static int verbose = 0;
typedef ssize_t (*packet_function_t)(int, void *, size_t, int, struct sockaddr *, socklen_t *);

static option_t sfcapdConfig[] = {
{.name = "gre", .valBool = 0, .flags = OPTDEFAULT}, {.name = "maxworkers", .valUint64 = 2, .flags = OPTDEFAULT}, {.name = NULL}};
{.name = "gre", .valBool = 0, .flags = OPTDEFAULT}, {.name = "6in4", .valBool = 0, .flags = OPTDEFAULT}, {.name = "maxworkers", .valUint64 = 2, .flags = OPTDEFAULT}, {.name = NULL}};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one option .name = "tunnel" ..

@@ -115,7 +115,7 @@ static void IntHandler(int signal);
static inline FlowSource_t *GetFlowSource(struct sockaddr_storage *ss);

static void run(packet_function_t receive_packet, int socket, int pfd, int rfd, time_t twin, time_t t_begin, char *time_extension, int compress,
int parse_gre);
int parse_gre, int parse_6in4);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One argument -> int parse_tunnel

@@ -272,7 +272,7 @@ static int SendRepeaterMessage(int fd, void *in_buff, size_t cnt, struct sockadd
} // End of SendRepeaterMessage

static void run(packet_function_t receive_packet, int socket, int pfd, int rfd, time_t twin, time_t t_begin, char *time_extension, int compress,
int parse_gre) {
int parse_gre, int parse_6in4) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one option -> int parse_tunnel

Comment on lines +283 to +284
int parse_gre; /* Enable GRE tunnel introspection */
int parse_6in4; /* Enable 6in4 tunnel introspection */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One single option int parse_tunnel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement improve code, speed, quality Feature request Feature request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants