Merge pull request #55 from simosund/pping-skip-syn

PPing: Add option to ignore SYN-packets
This commit is contained in:
Toke Høiland-Jørgensen
2022-11-06 14:18:10 +01:00
committed by GitHub
3 changed files with 39 additions and 24 deletions

View File

@@ -102,6 +102,7 @@ static const struct option long_options[] = {
{ "tcp", no_argument, NULL, 'T' }, // Calculate and report RTTs for TCP traffic (with TCP timestamps)
{ "icmp", no_argument, NULL, 'C' }, // Calculate and report RTTs for ICMP echo-reply traffic
{ "include-local", no_argument, NULL, 'l' }, // Also report "internal" RTTs
{ "include-SYN", no_argument, NULL, 's' }, // Include SYN-packets in tracking (may fill up flow state with half-open connections)
{ 0, 0, NULL, 0 }
};
@@ -170,8 +171,9 @@ static int parse_arguments(int argc, char *argv[], struct pping_config *config)
config->force = false;
config->bpf_config.track_tcp = false;
config->bpf_config.track_icmp = false;
config->bpf_config.skip_syn = true;
while ((opt = getopt_long(argc, argv, "hflTCi:r:R:t:c:F:I:",
while ((opt = getopt_long(argc, argv, "hflTCsi:r:R:t:c:F:I:",
long_options, NULL)) != -1) {
switch (opt) {
case 'i':
@@ -266,6 +268,9 @@ static int parse_arguments(int argc, char *argv[], struct pping_config *config)
case 'C':
config->bpf_config.track_icmp = true;
break;
case 's':
config->bpf_config.skip_syn = false;
break;
case 'h':
printf("HELP:\n");
print_usage(argv);

View File

@@ -64,7 +64,8 @@ struct bpf_config {
bool track_tcp;
bool track_icmp;
bool localfilt;
__u32 reserved;
bool skip_syn;
__u8 reserved[3];
};
/*
@@ -105,7 +106,8 @@ struct flow_state {
__u32 outstanding_timestamps;
enum connection_state conn_state;
enum flow_event_reason opening_reason;
__u8 reserved[6];
bool has_been_timestamped;
__u8 reserved[5];
};
/*

View File

@@ -104,6 +104,7 @@ struct packet_info {
bool reply_pid_valid; // reply_identifier can be used to match packet
enum flow_event_type event_type; // flow event triggered by packet
enum flow_event_reason event_reason; // reason for triggering flow event
bool wait_first_edge; // Do we need to wait for the first identifier change before timestamping?
};
/*
@@ -116,6 +117,7 @@ struct protocol_info {
bool reply_pid_valid;
enum flow_event_type event_type;
enum flow_event_reason event_reason;
bool wait_first_edge;
};
char _license[] SEC("license") = "GPL";
@@ -339,6 +341,9 @@ static int parse_tcp_identifier(struct parsing_context *pctx,
if (parse_tcphdr(&pctx->nh, pctx->data_end, &hdr) < 0)
return -1;
if (config.skip_syn && hdr->syn)
return -1;
if (parse_tcp_ts(hdr, pctx->data_end, &proto_info->pid,
&proto_info->reply_pid) < 0)
return -1; //Possible TODO, fall back on seq/ack instead
@@ -361,9 +366,11 @@ static int parse_tcp_identifier(struct parsing_context *pctx,
proto_info->event_type = FLOW_EVENT_OPENING;
proto_info->event_reason =
hdr->ack ? EVENT_REASON_SYN_ACK : EVENT_REASON_SYN;
proto_info->wait_first_edge = false;
} else {
proto_info->event_type = FLOW_EVENT_NONE;
proto_info->event_reason = EVENT_REASON_NONE;
proto_info->wait_first_edge = true;
}
*sport = hdr->source;
@@ -416,6 +423,7 @@ static int parse_icmp6_identifier(struct parsing_context *pctx,
proto_info->event_type = FLOW_EVENT_NONE;
proto_info->event_reason = EVENT_REASON_NONE;
proto_info->wait_first_edge = false;
*sport = hdr->icmp6_identifier;
*dport = hdr->icmp6_identifier;
*icmp6h = hdr;
@@ -453,6 +461,7 @@ static int parse_icmp_identifier(struct parsing_context *pctx,
proto_info->event_type = FLOW_EVENT_NONE;
proto_info->event_reason = EVENT_REASON_NONE;
proto_info->wait_first_edge = false;
*sport = hdr->un.echo.id;
*dport = hdr->un.echo.id;
*icmph = hdr;
@@ -531,6 +540,7 @@ static int parse_packet_identifier(struct parsing_context *pctx,
p_info->reply_pid_valid = proto_info.reply_pid_valid;
p_info->event_type = proto_info.event_type;
p_info->event_reason = proto_info.event_reason;
p_info->wait_first_edge = proto_info.wait_first_edge;
if (p_info->pid.flow.ipv == AF_INET) {
map_ipv4_to_ipv6(&p_info->pid.flow.saddr.ip,
@@ -705,14 +715,19 @@ static void init_flowstate(struct flow_state *f_state,
{
f_state->conn_state = CONNECTION_STATE_WAITOPEN;
f_state->last_timestamp = p_info->time;
/* We should only ever create new flows for packet with valid pid,
so assume pid is valid*/
f_state->last_id = p_info->pid.identifier;
f_state->opening_reason = p_info->event_type == FLOW_EVENT_OPENING ?
p_info->event_reason :
EVENT_REASON_FIRST_OBS_PCKT;
f_state->has_been_timestamped = false;
}
static void init_empty_flowstate(struct flow_state *f_state)
{
f_state->conn_state = CONNECTION_STATE_EMPTY;
f_state->has_been_timestamped = false;
}
/*
@@ -732,18 +747,15 @@ static void init_dualflow_state(struct dual_flow_state *df_state,
}
static struct dual_flow_state *
create_dualflow_state(void *ctx, struct packet_info *p_info, bool *new_flow)
create_dualflow_state(void *ctx, struct packet_info *p_info)
{
struct network_tuple *key = get_dualflow_key_from_packet(p_info);
struct dual_flow_state new_state = { 0 };
init_dualflow_state(&new_state, p_info);
if (bpf_map_update_elem(&flow_state, key, &new_state, BPF_NOEXIST) ==
if (bpf_map_update_elem(&flow_state, key, &new_state, BPF_NOEXIST) !=
0) {
if (new_flow)
*new_flow = true;
} else {
send_map_full_event(ctx, p_info, PPING_MAP_FLOWSTATE);
return NULL;
}
@@ -752,8 +764,7 @@ create_dualflow_state(void *ctx, struct packet_info *p_info, bool *new_flow)
}
static struct dual_flow_state *
lookup_or_create_dualflow_state(void *ctx, struct packet_info *p_info,
bool *new_flow)
lookup_or_create_dualflow_state(void *ctx, struct packet_info *p_info)
{
struct dual_flow_state *df_state;
@@ -768,7 +779,7 @@ lookup_or_create_dualflow_state(void *ctx, struct packet_info *p_info,
p_info->event_type == FLOW_EVENT_CLOSING_BOTH)
return NULL;
return create_dualflow_state(ctx, p_info, new_flow);
return create_dualflow_state(ctx, p_info);
}
static bool is_flowstate_active(struct flow_state *f_state)
@@ -778,15 +789,11 @@ static bool is_flowstate_active(struct flow_state *f_state)
}
static void update_forward_flowstate(struct packet_info *p_info,
struct flow_state *f_state, bool *new_flow)
struct flow_state *f_state)
{
// "Create" flowstate if it's empty
if (f_state->conn_state == CONNECTION_STATE_EMPTY &&
p_info->pid_valid) {
if (f_state->conn_state == CONNECTION_STATE_EMPTY && p_info->pid_valid)
init_flowstate(f_state, p_info);
if (new_flow)
*new_flow = true;
}
if (is_flowstate_active(f_state)) {
f_state->sent_pkts++;
@@ -902,7 +909,7 @@ static bool is_new_identifier(struct packet_id *pid, struct flow_state *f_state)
* Attempt to create a timestamp-entry for packet p_info for flow in f_state
*/
static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
struct packet_info *p_info, bool new_flow)
struct packet_info *p_info)
{
if (!is_flowstate_active(f_state) || !p_info->pid_valid)
return;
@@ -912,12 +919,13 @@ static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
return;
// Check if identfier is new
if (!new_flow && !is_new_identifier(&p_info->pid, f_state))
if ((f_state->has_been_timestamped || p_info->wait_first_edge) &&
!is_new_identifier(&p_info->pid, f_state))
return;
f_state->last_id = p_info->pid.identifier;
// Check rate-limit
if (!new_flow &&
if (f_state->has_been_timestamped &&
is_rate_limited(p_info->time, f_state->last_timestamp,
config.use_srtt ? f_state->srtt : f_state->min_rtt))
return;
@@ -928,6 +936,7 @@ static void pping_timestamp_packet(struct flow_state *f_state, void *ctx,
* the next available map slot somewhat fairer between heavy and sparse
* flows.
*/
f_state->has_been_timestamped = true;
f_state->last_timestamp = p_info->time;
if (bpf_map_update_elem(&packet_ts, &p_info->pid, &p_info->time,
@@ -993,15 +1002,14 @@ static void pping_parsed_packet(void *ctx, struct packet_info *p_info)
{
struct dual_flow_state *df_state;
struct flow_state *fw_flow, *rev_flow;
bool new_flow = false;
df_state = lookup_or_create_dualflow_state(ctx, p_info, &new_flow);
df_state = lookup_or_create_dualflow_state(ctx, p_info);
if (!df_state)
return;
fw_flow = get_flowstate_from_packet(df_state, p_info);
update_forward_flowstate(p_info, fw_flow, &new_flow);
pping_timestamp_packet(fw_flow, ctx, p_info, new_flow);
update_forward_flowstate(p_info, fw_flow);
pping_timestamp_packet(fw_flow, ctx, p_info);
rev_flow = get_reverse_flowstate_from_packet(df_state, p_info);
update_reverse_flowstate(ctx, p_info, rev_flow);