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

Add TCP out of order or duplicate segments sampler via BPF #255

Merged
merged 7 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/METRICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@ This sampler provides telemetry about TCP traffic and connections.
* `tcp/drop` - number of packets dropped in the kernel TCP stack
* `tcp/tlp` - number of Tail Loss Recovery Probes sent
* `tcp/transmit/retransmit_timeout` - number of retransmit timeouts
* `tcp/receive/duplicate` - number of duplicate TCP segments received.
* `tcp/receive/out_of_order` - number of out of order TCP segments received.

## UDP

Expand Down
29 changes: 29 additions & 0 deletions src/samplers/tcp/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <net/inet_sock.h>
#include <bcc/proto.h>
#include <linux/tcp.h>
#include <net/tcp.h>

// stores the stats of a connection.
struct sock_stats_t {
Expand All @@ -34,6 +35,8 @@ BPF_ARRAY(conn_initiated, u64, 1);
BPF_ARRAY(drop, u64, 1);
BPF_ARRAY(tlp, u64, 1);
BPF_ARRAY(rto, u64, 1);
BPF_ARRAY(duplicate, u64, 1);
BPF_ARRAY(ooo, u64, 1);

// store a pointer by the pid
static void store_ptr(u64 pid, u64 ptr)
Expand Down Expand Up @@ -269,3 +272,29 @@ int trace_rto(struct pt_regs *ctx, struct sock *sk)
add_value(rto.lookup(&loc), 1);
return 0;
}

// Run on incoming package validation
int trace_validate_incoming(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) {
if (sk == NULL || skb == NULL)
return 0;

struct tcp_sock *tp = tcp_sk(sk);
u32 seq = TCP_SKB_CB(skb)->seq;

// Segment sequence before the expected one
// which means this was a duplicated segment
if ((seq - tp->rcv_nxt) < 0) {
// Increment duplicate counter
int loc = 0;
add_value(duplicate.lookup(&loc), 1);
}

// Segment sequence after the expected one
// which means this segment was received out of order
if ((tp->rcv_nxt - seq) < 0) {
// Increment out of order counter
int loc = 0;
add_value(ooo.lookup(&loc), 1);
}
return 0;
}
16 changes: 16 additions & 0 deletions src/samplers/tcp/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ pub enum TcpStatistic {
TailLossProbe,
#[strum(serialize = "tcp/transmit/retransmit_timeout")]
RetransmitTimeout,
#[strum(serialize = "tcp/receive/duplicate")]
Duplicate,
#[strum(serialize = "tcp/receive/out_of_order")]
OutOfOrder,
}

impl TcpStatistic {
Expand Down Expand Up @@ -129,6 +133,8 @@ impl TcpStatistic {
Self::Drop => Some("drop"),
Self::TailLossProbe => Some("tlp"),
Self::RetransmitTimeout => Some("rto"),
Self::Duplicate => Some("duplicate"),
Self::OutOfOrder => Some("ooo"),
_ => None,
}
}
Expand Down Expand Up @@ -232,6 +238,14 @@ impl TcpStatistic {
binary_path: None,
sub_system: None,
};
let tcp_validate_incoming_probe = Probe {
name: "tcp_validate_incoming".to_string(),
handler: "trace_validate_incoming".to_string(),
probe_type: ProbeType::Kernel,
probe_location: ProbeLocation::Entry,
binary_path: None,
sub_system: None,
};

// specify what probes are required for each telemetry.
match self {
Expand All @@ -253,6 +267,8 @@ impl TcpStatistic {
Self::Drop => vec![tcp_drop_probe],
Self::TailLossProbe => vec![tcp_tlp_probe],
Self::RetransmitTimeout => vec![tcp_rto_probe],
Self::Duplicate => vec![tcp_validate_incoming_probe],
Self::OutOfOrder => vec![tcp_validate_incoming_probe],
_ => Vec::new(),
}
}
Expand Down