mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2026-10-25 06:17:39 -05:00
Eliminate all time fetching calls except one, and store the result in the dissector. Minor speed improvement.
This commit is contained in:
1 parent
4a8be30c09
commit
82ecd5eb17
6 files changed
+36
-49
No files matched your search
@@ -322,6 +322,7 @@
|
||||
html += "<th>DL ⬇️</th>";
|
||||
html += "<th>UL RTT</th>";
|
||||
html += "<th>DL RTT</th>";
|
||||
html += "<th>TCP Retries</th>";
|
||||
html += "<th>Remote ASN</th>";
|
||||
html += "<th>Country</th>";
|
||||
html += "</thead><tbody>";
|
||||
@@ -336,6 +337,7 @@
|
||||
html += "<td>" + scaleNumber(data[i].rate_estimate_bps[1] * 8) + "</td>";
|
||||
html += "<td>" + (data[i].last_rtt[0] / 1000000).toFixed(2) + "</td>";
|
||||
html += "<td>" + (data[i].last_rtt[1] / 1000000).toFixed(2) + "</td>";
|
||||
html += "<td>" + data[i].retries[0] + "/" + data[i].retries[1] + "</td>";
|
||||
html += "<td>" + data[i].remote_asn_name + "</td>";
|
||||
html += "<td>" + data[i].remote_asn_country + "</td>";
|
||||
html += "</tr>";
|
||||
|
||||
@@ -54,6 +54,7 @@ struct dissector_t
|
||||
__u32 tsecr;
|
||||
__u32 sequence;
|
||||
__u32 ack_seq;
|
||||
__u64 now;
|
||||
};
|
||||
|
||||
// Representation of the VLAN header type.
|
||||
@@ -118,6 +119,7 @@ static __always_inline bool dissector_new(
|
||||
dissector->tos = 0;
|
||||
dissector->sequence = 0;
|
||||
dissector->ack_seq = 0;
|
||||
dissector->now = bpf_ktime_get_boot_ns();
|
||||
|
||||
// Check that there's room for an ethernet header
|
||||
if SKB_OVERFLOW (dissector->start, dissector->end, ethhdr)
|
||||
|
||||
@@ -86,19 +86,17 @@ struct
|
||||
|
||||
// Construct an empty flow_data_t structure, using default values.
|
||||
static __always_inline struct flow_data_t new_flow_data(
|
||||
// The current time in nanoseconds, from bpf_ktime_get_boot_ns
|
||||
__u64 now,
|
||||
// The packet dissector from the previous step
|
||||
struct dissector_t *dissector
|
||||
) {
|
||||
struct flow_data_t data = {
|
||||
.start_time = now,
|
||||
.start_time = dissector->now,
|
||||
.bytes_sent = { 0, 0 },
|
||||
.packets_sent = { 0, 0 },
|
||||
// Track flow rates at an MS scale rather than per-second
|
||||
// to minimize rounding errors.
|
||||
.next_count_time = { now + SECOND_IN_NANOS, now + SECOND_IN_NANOS },
|
||||
.last_count_time = { now, now },
|
||||
.next_count_time = { dissector->now + SECOND_IN_NANOS, dissector->now + SECOND_IN_NANOS },
|
||||
.last_count_time = { dissector->now, dissector->now },
|
||||
.next_count_bytes = { dissector->skb_len, dissector->skb_len },
|
||||
.rate_estimate_bps = { 0, 0 },
|
||||
.last_sequence = { 0, 0 },
|
||||
@@ -148,25 +146,23 @@ static __always_inline void update_flow_rates(
|
||||
// The rate index (0 = to internet, 1 = to local network)
|
||||
u_int8_t rate_index,
|
||||
// The flow data structure to update
|
||||
struct flow_data_t *data,
|
||||
// The current time in nanoseconds, from bpf_ktime_get_boot_ns
|
||||
__u64 now
|
||||
struct flow_data_t *data
|
||||
) {
|
||||
data->last_seen = now;
|
||||
data->last_seen = dissector->now;
|
||||
data->end_status = 0; // Reset the end status
|
||||
|
||||
// Update bytes and packets sent
|
||||
data->bytes_sent[rate_index] += dissector->skb_len;
|
||||
data->packets_sent[rate_index]++;
|
||||
|
||||
if (now > data->next_count_time[rate_index]) {
|
||||
if (dissector->now > data->next_count_time[rate_index]) {
|
||||
// Calculate the rate estimate
|
||||
__u64 bits = (data->bytes_sent[rate_index] - data->next_count_bytes[rate_index])*8;
|
||||
__u64 time = (now - data->last_count_time[rate_index]) / 10000000; // 1 Second
|
||||
__u64 time = (dissector->now - data->last_count_time[rate_index]) / 10000000; // 1 Second
|
||||
data->rate_estimate_bps[rate_index] = (bits/time); // bits per second
|
||||
data->next_count_time[rate_index] = now + SECOND_IN_NANOS;
|
||||
data->next_count_time[rate_index] = dissector->now + SECOND_IN_NANOS;
|
||||
data->next_count_bytes[rate_index] = data->bytes_sent[rate_index];
|
||||
data->last_count_time[rate_index] = now;
|
||||
data->last_count_time[rate_index] = dissector->now;
|
||||
//bpf_debug("[FLOWS] Rate Estimate: %llu", data->rate_estimate_bps[rate_index]);
|
||||
}
|
||||
}
|
||||
@@ -176,14 +172,13 @@ static __always_inline void process_icmp(
|
||||
struct dissector_t *dissector,
|
||||
u_int8_t direction,
|
||||
u_int8_t rate_index,
|
||||
u_int8_t other_rate_index,
|
||||
u_int64_t now
|
||||
u_int8_t other_rate_index
|
||||
) {
|
||||
struct flow_key_t key = build_flow_key(dissector, direction);
|
||||
struct flow_data_t *data = bpf_map_lookup_elem(&flowbee, &key);
|
||||
if (data == NULL) {
|
||||
// There isn't a flow, so we need to make one
|
||||
struct flow_data_t new_data = new_flow_data(now, dissector);
|
||||
struct flow_data_t new_data = new_flow_data(dissector);
|
||||
if (bpf_map_update_elem(&flowbee, &key, &new_data, BPF_ANY) != 0) {
|
||||
bpf_debug("[FLOWS] Failed to add new flow to map");
|
||||
return;
|
||||
@@ -191,7 +186,7 @@ static __always_inline void process_icmp(
|
||||
data = bpf_map_lookup_elem(&flowbee, &key);
|
||||
if (data == NULL) return;
|
||||
}
|
||||
update_flow_rates(dissector, rate_index, data, now);
|
||||
update_flow_rates(dissector, rate_index, data);
|
||||
}
|
||||
|
||||
// Handle Per-Flow UDP Analysis
|
||||
@@ -199,14 +194,13 @@ static __always_inline void process_udp(
|
||||
struct dissector_t *dissector,
|
||||
u_int8_t direction,
|
||||
u_int8_t rate_index,
|
||||
u_int8_t other_rate_index,
|
||||
u_int64_t now
|
||||
u_int8_t other_rate_index
|
||||
) {
|
||||
struct flow_key_t key = build_flow_key(dissector, direction);
|
||||
struct flow_data_t *data = bpf_map_lookup_elem(&flowbee, &key);
|
||||
if (data == NULL) {
|
||||
// There isn't a flow, so we need to make one
|
||||
struct flow_data_t new_data = new_flow_data(now, dissector);
|
||||
struct flow_data_t new_data = new_flow_data(dissector);
|
||||
if (bpf_map_update_elem(&flowbee, &key, &new_data, BPF_ANY) != 0) {
|
||||
bpf_debug("[FLOWS] Failed to add new flow to map");
|
||||
return;
|
||||
@@ -214,7 +208,7 @@ static __always_inline void process_udp(
|
||||
data = bpf_map_lookup_elem(&flowbee, &key);
|
||||
if (data == NULL) return;
|
||||
}
|
||||
update_flow_rates(dissector, rate_index, data, now);
|
||||
update_flow_rates(dissector, rate_index, data);
|
||||
}
|
||||
|
||||
// Store the most recent sequence and ack numbers, and detect retransmissions.
|
||||
@@ -249,8 +243,7 @@ static __always_inline void process_tcp(
|
||||
struct dissector_t *dissector,
|
||||
u_int8_t direction,
|
||||
u_int8_t rate_index,
|
||||
u_int8_t other_rate_index,
|
||||
u_int64_t now
|
||||
u_int8_t other_rate_index
|
||||
) {
|
||||
// SYN packet indicating the start of a conversation. We are explicitly ignoring
|
||||
// SYN-ACK packets, we just want to catch the opening of a new connection.
|
||||
@@ -262,7 +255,7 @@ static __always_inline void process_tcp(
|
||||
bpf_debug("[FLOWS] New TCP Connection Detected (%u)", direction);
|
||||
#endif
|
||||
struct flow_key_t key = build_flow_key(dissector, direction);
|
||||
struct flow_data_t data = new_flow_data(now, dissector);
|
||||
struct flow_data_t data = new_flow_data(dissector);
|
||||
data.tos = dissector->tos;
|
||||
data.ip_flags = 0; // Obtain these
|
||||
if (bpf_map_update_elem(&flowbee, &key, &data, BPF_ANY) != 0) {
|
||||
@@ -281,7 +274,7 @@ static __always_inline void process_tcp(
|
||||
}
|
||||
|
||||
// Update the flow data with the current packet's information
|
||||
update_flow_rates(dissector, rate_index, data, now);
|
||||
update_flow_rates(dissector, rate_index, data);
|
||||
|
||||
// Sequence and Acknowledgement numbers
|
||||
detect_retries(dissector, rate_index, data);
|
||||
@@ -294,12 +287,12 @@ static __always_inline void process_tcp(
|
||||
if (tsval != data->tsval[rate_index] && tsecr != data->tsecr[rate_index]) {
|
||||
|
||||
if (tsecr == data->tsval[other_rate_index]) {
|
||||
__u64 elapsed = now - data->ts_change_time[other_rate_index];
|
||||
__u64 elapsed = dissector->now - data->ts_change_time[other_rate_index];
|
||||
data->last_rtt[rate_index] = elapsed;
|
||||
//bpf_debug("[FLOWS][%d] RTT: %llu", direction, elapsed);
|
||||
}
|
||||
|
||||
data->ts_change_time[rate_index] = now;
|
||||
data->ts_change_time[rate_index] = dissector->now;
|
||||
data->tsval[rate_index] = tsval;
|
||||
data->tsecr[rate_index] = tsecr;
|
||||
}
|
||||
@@ -319,8 +312,6 @@ static __always_inline void track_flows(
|
||||
struct dissector_t *dissector, // The packet dissector from the previous step
|
||||
u_int8_t direction // The direction of the packet (1 = to internet, 2 = to local network)
|
||||
) {
|
||||
__u64 now = bpf_ktime_get_boot_ns();
|
||||
|
||||
u_int8_t rate_index;
|
||||
u_int8_t other_rate_index;
|
||||
if (direction == TO_INTERNET) {
|
||||
@@ -334,9 +325,9 @@ static __always_inline void track_flows(
|
||||
// Pass to the appropriate protocol handler
|
||||
switch (dissector->ip_protocol)
|
||||
{
|
||||
case IPPROTO_TCP: process_tcp(dissector, direction, rate_index, other_rate_index, now); break;
|
||||
case IPPROTO_UDP: process_udp(dissector, direction, rate_index, other_rate_index, now); break;
|
||||
case IPPROTO_ICMP: process_icmp(dissector, direction, rate_index, other_rate_index, now); break;
|
||||
case IPPROTO_TCP: process_tcp(dissector, direction, rate_index, other_rate_index); break;
|
||||
case IPPROTO_UDP: process_udp(dissector, direction, rate_index, other_rate_index); break;
|
||||
case IPPROTO_ICMP: process_icmp(dissector, direction, rate_index, other_rate_index); break;
|
||||
default: {
|
||||
#ifdef VERBOSE
|
||||
bpf_debug("[FLOWS] Unsupported protocol: %d", dissector->ip_protocol);
|
||||
|
||||
@@ -137,7 +137,7 @@ static __always_inline void update_heimdall(struct dissector_t *dissector, __u32
|
||||
struct heimdall_data *counter = (struct heimdall_data *)bpf_map_lookup_elem(&heimdall, &key);
|
||||
if (counter)
|
||||
{
|
||||
counter->last_seen = bpf_ktime_get_boot_ns();
|
||||
counter->last_seen = dissector->now;
|
||||
counter->packets += 1;
|
||||
counter->bytes += size;
|
||||
if (dissector->tos != 0)
|
||||
@@ -148,7 +148,7 @@ static __always_inline void update_heimdall(struct dissector_t *dissector, __u32
|
||||
else
|
||||
{
|
||||
struct heimdall_data counter = {0};
|
||||
counter.last_seen = bpf_ktime_get_boot_ns();
|
||||
counter.last_seen = dissector->now;
|
||||
counter.bytes = size;
|
||||
counter.packets = 1;
|
||||
counter.tos = dissector->tos;
|
||||
@@ -160,7 +160,7 @@ static __always_inline void update_heimdall(struct dissector_t *dissector, __u32
|
||||
}
|
||||
} else if (mode == 2) {
|
||||
struct heimdall_event event = {0};
|
||||
event.timetamp = bpf_ktime_get_boot_ns();
|
||||
event.timetamp = dissector->now;
|
||||
event.src = dissector->src_ip;
|
||||
event.dst = dissector->dst_ip;
|
||||
event.src_port = dissector->src_port;
|
||||
|
||||
@@ -33,13 +33,14 @@ static __always_inline void track_traffic(
|
||||
int direction,
|
||||
struct in6_addr * key,
|
||||
__u32 size,
|
||||
__u32 tc_handle
|
||||
__u32 tc_handle,
|
||||
__u64 now
|
||||
) {
|
||||
// Count the bits. It's per-CPU, so we can't be interrupted - no sync required
|
||||
struct host_counter * counter =
|
||||
(struct host_counter *)bpf_map_lookup_elem(&map_traffic, key);
|
||||
if (counter) {
|
||||
counter->last_seen = bpf_ktime_get_boot_ns();
|
||||
counter->last_seen = now;
|
||||
counter->tc_handle = tc_handle;
|
||||
if (direction == 1) {
|
||||
// Download
|
||||
@@ -53,7 +54,7 @@ static __always_inline void track_traffic(
|
||||
} else {
|
||||
struct host_counter new_host = {0};
|
||||
new_host.tc_handle = tc_handle;
|
||||
new_host.last_seen = bpf_ktime_get_boot_ns();
|
||||
new_host.last_seen = now;
|
||||
if (direction == 1) {
|
||||
new_host.download_packets = 1;
|
||||
new_host.download_bytes = size;
|
||||
|
||||
@@ -147,7 +147,8 @@ int xdp_prog(struct xdp_md *ctx)
|
||||
effective_direction,
|
||||
&lookup_key.address,
|
||||
ctx->data_end - ctx->data, // end - data = length
|
||||
tc_handle
|
||||
tc_handle,
|
||||
dissector.now
|
||||
);
|
||||
|
||||
// Send on its way
|
||||
@@ -303,16 +304,6 @@ int tc_iphash_to_cpu(struct __sk_buff *skb)
|
||||
bpf_debug("(TC) effective direction: %d", effective_direction);
|
||||
#endif
|
||||
|
||||
/*
|
||||
// Call pping to obtain RTT times
|
||||
struct parsing_context context = {0};
|
||||
context.now = bpf_ktime_get_ns();
|
||||
context.tcp = NULL;
|
||||
context.dissector = &dissector;
|
||||
context.active_host = &lookup_key.address;
|
||||
tc_pping_start(&context);
|
||||
*/
|
||||
|
||||
if (ip_info && ip_info->tc_handle != 0) {
|
||||
// We found a matching mapped TC flow
|
||||
#ifdef VERBOSE
|
||||
|
||||
Reference in new issue
Block a user