diff --git a/src/gui/windows/debug_network_advanced.zig b/src/gui/windows/debug_network_advanced.zig index 549d1ed77a..6854940015 100644 --- a/src/gui/windows/debug_network_advanced.zig +++ b/src/gui/windows/debug_network_advanced.zig @@ -31,7 +31,7 @@ fn renderConnectionData(conn: *main.network.Connection, name: []const u8, y: *f3 conn.lossyChannel.getStatistics(&unconfirmed[0], &queued[0]); conn.secureChannel.getStatistics(&unconfirmed[1], &queued[1]); conn.slowChannel.getStatistics(&unconfirmed[2], &queued[2]); - draw.print("{s} | RTT = {d:.1} ms | {d:.0} kiB/RTT", .{name, conn.rttEstimate/1000.0, conn.bandwidthEstimateInBytesPerRtt/1024.0}, 0, y.*, 8); + draw.print("{s} | RTT = {d:.1} ms | {d:.0} kiB/RTT | MTU: {d}", .{name, conn.rttEstimate/1000.0, conn.bandwidthEstimateInBytesPerRtt/1024.0, conn.mtuEstimate}, 0, y.*, 8); y.* += 8; draw.print("Waiting in queue: {: >6} kiB |{: >6} kiB |{: >6} kiB", .{queued[0] >> 10, queued[1] >> 10, queued[2] >> 10}, 0, y.*, 8); y.* += 8; diff --git a/src/network.zig b/src/network.zig index 7b6477bf4e..3e931654d3 100644 --- a/src/network.zig +++ b/src/network.zig @@ -24,6 +24,7 @@ inline fn networkTimestamp() i64 { const Socket = struct { const posix = std.posix; socketID: if (builtin.os.tag == .windows) c.SOCKET else posix.socket_t, + interfaceMtu: ?u16 = null, fn windowsError(err: c_int) !void { if (err == 0) return; @@ -57,7 +58,7 @@ const Socket = struct { } fn init(localPort: u16) !Socket { - const self = Socket{ + var self = Socket{ .socketID = blk: { if (builtin.os.tag == .windows) { const socket = c.socket(c.AF_INET, c.SOCK_DGRAM, c.IPPROTO_UDP); @@ -100,6 +101,7 @@ const Socket = struct { }, } } + self.interfaceMtu = self.getInterfaceMtu(); return self; } @@ -226,6 +228,25 @@ const Socket = struct { } return @byteSwap(addr.port); } + + fn getInterfaceMtu(self: Socket) ?u16 { + if (builtin.os.tag == .windows) { + return null; + } else { + var req: std.posix.ifreq = undefined; + req.ifrn.name = .{'l', 'o'} ++ @as([14]u8, @splat(0)); + const result = std.c.ioctl(self.socketID, std.os.linux.SIOCGIFMTU, &req); + switch (std.posix.errno(result)) { + .SUCCESS => { + return @truncate(@as(u32, @bitCast(@min(req.ifru.mtu, 65535) - 20 - 8))); // its often reported to be 65536, but the IPv4 header has only a 16 bit length field + }, + else => |err| { + std.log.warn("Failed to get the mtu of 'lo' interface from ioctl: {s}", .{@tagName(err)}); + return null; + }, + } + } + } }; pub fn init() !void { @@ -293,6 +314,12 @@ pub const SocketAddress = struct { }, }; } + + fn isLoopback(self: *const SocketAddress) bool { + return switch (self.address) { + inline else => |ip| ip.eql(.loopback(ip.port)), + }; + } }; const Request = struct { @@ -1554,6 +1581,7 @@ pub const Connection = struct { // MARK: Connection if (result.connectionIdentifier == 0) result.connectionIdentifier = 1; result.remoteAddress = try SocketAddress.resolve(ipPort, settings.defaultPort); result.bruteforcingPort = result.remoteAddress.isSymmetricNAT; + if (result.remoteAddress.isLoopback() and manager.socket.interfaceMtu != null) result.mtuEstimate = manager.socket.interfaceMtu.?; try result.manager.addConnection(result); return result;