mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-16 14:34:45 -06:00
Circuit data now includes TCP retransmits. Made the tables a little less unpleasant to look at.
This commit is contained in:
parent
b01ab42a3b
commit
a4c8093401
@ -24,6 +24,9 @@ pub struct IpStats {
|
||||
|
||||
/// Associated TC traffic control handle.
|
||||
pub tc_handle: TcHandle,
|
||||
|
||||
/// TCP Retransmits for this host at the current time.
|
||||
pub tcp_retransmits: (u64, u64),
|
||||
}
|
||||
|
||||
/// Represents an IP Mapping in the XDP IP to TC/CPU mapping system.
|
||||
|
@ -22,6 +22,7 @@ pub struct IpStatsWithPlan {
|
||||
pub tc_handle: TcHandle,
|
||||
pub circuit_id: String,
|
||||
pub plan: (u32, u32),
|
||||
pub tcp_retransmits: (u64, u64),
|
||||
}
|
||||
|
||||
impl From<&IpStats> for IpStatsWithPlan {
|
||||
@ -34,6 +35,7 @@ impl From<&IpStats> for IpStatsWithPlan {
|
||||
tc_handle: i.tc_handle,
|
||||
circuit_id: i.circuit_id.clone(),
|
||||
plan: (0, 0),
|
||||
tcp_retransmits: i.tcp_retransmits,
|
||||
};
|
||||
|
||||
if !result.circuit_id.is_empty() {
|
||||
|
@ -34,6 +34,7 @@ const IpStats = {
|
||||
"tc_handle": 4,
|
||||
"circuit_id": 5,
|
||||
"plan": 6,
|
||||
"tcp_retransmits": 7,
|
||||
}
|
||||
|
||||
const FlowTrans = {
|
||||
|
@ -228,7 +228,7 @@
|
||||
|
||||
function updateSiteFunnel() {
|
||||
msgPackGet("/api/network_tree_summary/", (data) => {
|
||||
let table = "<table class='table' style='font-size: 8pt;'>";
|
||||
let table = "<table class='table table-striped' style='font-size: 8pt;'>";
|
||||
for (let i = 0; i < data.length; ++i) {
|
||||
let id = data[i][0];
|
||||
let name = data[i][1][NetTrans.name];
|
||||
@ -280,11 +280,12 @@
|
||||
}
|
||||
|
||||
function updateNTable(target, tt) {
|
||||
let html = "<table class='table'>";
|
||||
html += "<thead><th>IP Address</th><th>DL ⬇️</th><th>UL ⬆️</th><th>RTT (ms)</th><th>Shaped</th></thead>";
|
||||
let html = "<table class='table table-striped' style='font-size: 8pt'>";
|
||||
html += "<thead><th></th><th>IP Address</th><th>DL ⬇️</th><th>UL ⬆️</th><th>RTT (ms)</th><th>TCP Retransmits</th><th>Shaped</th></thead>";
|
||||
for (let i = 0; i < tt.length; i++) {
|
||||
let color = color_ramp(tt[i][IpStats.median_tcp_rtt]);
|
||||
html += "<tr style='background-color: " + color + "'>";
|
||||
html += "<tr>";
|
||||
html += "<td style='color: " + color + "'>⬤</td>";
|
||||
if (tt[i][IpStats.circuit_id] != "") {
|
||||
html += "<td><a class='redact' href='/circuit_queue?id=" + encodeURI(tt[i][IpStats.circuit_id]) + "'>" + redactText(tt[i][IpStats.ip_address]) + "</td>";
|
||||
} else {
|
||||
@ -293,6 +294,7 @@
|
||||
html += "<td>" + scaleNumber(tt[i][IpStats.bits_per_second][0]) + "</td>";
|
||||
html += "<td>" + scaleNumber(tt[i][IpStats.bits_per_second][1]) + "</td>";
|
||||
html += "<td>" + tt[i][IpStats.median_tcp_rtt].toFixed(2) + "</td>";
|
||||
html += "<td>" + tt[i][IpStats.tcp_retransmits][0] + "/" + tt[i][IpStats.tcp_retransmits][1] + "</td>";
|
||||
if (tt[i].tc_handle != 0) {
|
||||
html += "<td><i class='fa fa-check-circle'></i> (" + tt[i][IpStats.plan][0] + "/" + tt[i][IpStats.plan][1] + ")</td>";
|
||||
} else {
|
||||
@ -319,7 +321,7 @@
|
||||
|
||||
function updateTop10Flows() {
|
||||
$.get("/api/flows/top/10/rate", data => {
|
||||
let html = "<table class='table' style='font-size: 8pt'>";
|
||||
let html = "<table class='table table-striped' style='font-size: 8pt'>";
|
||||
html += "<thead>";
|
||||
html += "<th>Protocol</th>";
|
||||
html += "<th>Local IP</th>";
|
||||
@ -356,7 +358,7 @@
|
||||
function updateTop10Endpoints() {
|
||||
$.get("/api/flows/by_country", data => {
|
||||
//console.log(data);
|
||||
let html = "<table class='table' style='font-size: 8pt'>";
|
||||
let html = "<table class='table table-striped' style='font-size: 8pt'>";
|
||||
html += "<thead>";
|
||||
html += "<th>Country</th>";
|
||||
html += "<th>UL ⬆️</th>";
|
||||
|
@ -202,7 +202,7 @@ fn retire_check(cycle: u64, recent_cycle: u64) -> bool {
|
||||
cycle < recent_cycle + RETIRE_AFTER_SECONDS
|
||||
}
|
||||
|
||||
type TopList = (XdpIpAddress, (u64, u64), (u64, u64), f32, TcHandle, String);
|
||||
type TopList = (XdpIpAddress, (u64, u64), (u64, u64), f32, TcHandle, String, (u64, u64));
|
||||
|
||||
pub fn top_n(start: u32, end: u32) -> BusResponse {
|
||||
let mut full_list: Vec<TopList> = {
|
||||
@ -222,6 +222,7 @@ pub fn top_n(start: u32, end: u32) -> BusResponse {
|
||||
te.median_latency().unwrap_or(0.0),
|
||||
te.tc_handle,
|
||||
te.circuit_id.as_ref().unwrap_or(&String::new()).clone(),
|
||||
te.tcp_retransmits,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
@ -239,6 +240,7 @@ pub fn top_n(start: u32, end: u32) -> BusResponse {
|
||||
median_rtt,
|
||||
tc_handle,
|
||||
circuit_id,
|
||||
tcp_retransmits,
|
||||
)| IpStats {
|
||||
ip_address: ip.as_ip().to_string(),
|
||||
circuit_id: circuit_id.clone(),
|
||||
@ -246,6 +248,7 @@ pub fn top_n(start: u32, end: u32) -> BusResponse {
|
||||
packets_per_second: (*packets_dn, *packets_up),
|
||||
median_tcp_rtt: *median_rtt,
|
||||
tc_handle: *tc_handle,
|
||||
tcp_retransmits: *tcp_retransmits,
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
@ -271,6 +274,7 @@ pub fn worst_n(start: u32, end: u32) -> BusResponse {
|
||||
te.median_latency().unwrap_or(0.0),
|
||||
te.tc_handle,
|
||||
te.circuit_id.as_ref().unwrap_or(&String::new()).clone(),
|
||||
te.tcp_retransmits,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
@ -288,6 +292,7 @@ pub fn worst_n(start: u32, end: u32) -> BusResponse {
|
||||
median_rtt,
|
||||
tc_handle,
|
||||
circuit_id,
|
||||
tcp_retransmits,
|
||||
)| IpStats {
|
||||
ip_address: ip.as_ip().to_string(),
|
||||
circuit_id: circuit_id.clone(),
|
||||
@ -295,6 +300,7 @@ pub fn worst_n(start: u32, end: u32) -> BusResponse {
|
||||
packets_per_second: (*packets_dn, *packets_up),
|
||||
median_tcp_rtt: *median_rtt,
|
||||
tc_handle: *tc_handle,
|
||||
tcp_retransmits: *tcp_retransmits,
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
@ -320,6 +326,7 @@ pub fn best_n(start: u32, end: u32) -> BusResponse {
|
||||
te.median_latency().unwrap_or(0.0),
|
||||
te.tc_handle,
|
||||
te.circuit_id.as_ref().unwrap_or(&String::new()).clone(),
|
||||
te.tcp_retransmits,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
@ -338,6 +345,7 @@ pub fn best_n(start: u32, end: u32) -> BusResponse {
|
||||
median_rtt,
|
||||
tc_handle,
|
||||
circuit_id,
|
||||
tcp_retransmits,
|
||||
)| IpStats {
|
||||
ip_address: ip.as_ip().to_string(),
|
||||
circuit_id: circuit_id.clone(),
|
||||
@ -345,6 +353,7 @@ pub fn best_n(start: u32, end: u32) -> BusResponse {
|
||||
packets_per_second: (*packets_dn, *packets_up),
|
||||
median_tcp_rtt: *median_rtt,
|
||||
tc_handle: *tc_handle,
|
||||
tcp_retransmits: *tcp_retransmits,
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
@ -493,6 +502,7 @@ pub fn all_unknown_ips() -> BusResponse {
|
||||
packets_per_second: (*packets_dn, *packets_up),
|
||||
median_tcp_rtt: *median_rtt,
|
||||
tc_handle: *tc_handle,
|
||||
tcp_retransmits: (0, 0),
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
|
@ -17,6 +17,8 @@ pub(crate) struct ThroughputEntry {
|
||||
pub(crate) recent_rtt_data: [RttData; 60],
|
||||
pub(crate) last_fresh_rtt_data_cycle: u64,
|
||||
pub(crate) last_seen: u64, // Last seen in kernel time since boot
|
||||
pub(crate) tcp_retransmits: (u64, u64),
|
||||
pub(crate) last_tcp_retransmits: (u64, u64),
|
||||
}
|
||||
|
||||
impl ThroughputEntry {
|
||||
|
@ -154,6 +154,8 @@ impl ThroughputTracker {
|
||||
recent_rtt_data: [RttData::from_nanos(0); 60],
|
||||
last_fresh_rtt_data_cycle: 0,
|
||||
last_seen: 0,
|
||||
tcp_retransmits: (0, 0),
|
||||
last_tcp_retransmits: (0, 0),
|
||||
};
|
||||
for c in counts {
|
||||
entry.bytes.0 += c.download_bytes;
|
||||
@ -189,6 +191,9 @@ impl ThroughputTracker {
|
||||
// should limit outliers.
|
||||
let mut rtt_circuit_tracker: FxHashMap<XdpIpAddress, [Vec<RttData>; 2]> = FxHashMap::default();
|
||||
|
||||
// Tracker for TCP retries. We're storing these per second.
|
||||
let mut tcp_retries: FxHashMap<XdpIpAddress, [u64; 2]> = FxHashMap::default();
|
||||
|
||||
// Track the expired keys
|
||||
let mut expired_keys = Vec::new();
|
||||
|
||||
@ -244,6 +249,14 @@ impl ThroughputTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// TCP Retries
|
||||
if let Some(retries) = tcp_retries.get_mut(&key.local_ip) {
|
||||
retries[0] += data.tcp_retransmits[0] as u64;
|
||||
retries[1] += data.tcp_retransmits[1] as u64;
|
||||
} else {
|
||||
tcp_retries.insert(key.local_ip, [data.tcp_retransmits[0] as u64, data.tcp_retransmits[1] as u64]);
|
||||
}
|
||||
|
||||
if data.end_status != 0 {
|
||||
// The flow has ended. We need to remove it from the map.
|
||||
expired_keys.push(key.clone());
|
||||
@ -279,6 +292,21 @@ impl ThroughputTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// Merge in the TCP retries
|
||||
// Reset all entries in the tracker to 0
|
||||
for mut circuit in self.raw_data.iter_mut() {
|
||||
circuit.tcp_retransmits = (0, 0);
|
||||
}
|
||||
// Apply the new ones
|
||||
for (local_ip, retries) in tcp_retries {
|
||||
if let Some(mut tracker) = self.raw_data.get_mut(&local_ip) {
|
||||
tracker.tcp_retransmits.0 = retries[0].saturating_sub(tracker.last_tcp_retransmits.0);
|
||||
tracker.tcp_retransmits.1 = retries[1].saturating_sub(tracker.last_tcp_retransmits.1);
|
||||
tracker.last_tcp_retransmits.0 = retries[0];
|
||||
tracker.last_tcp_retransmits.1 = retries[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Key Expiration
|
||||
if !expired_keys.is_empty() {
|
||||
for key in expired_keys.iter() {
|
||||
|
Loading…
Reference in New Issue
Block a user