forked from I2P_Developers/i2p.i2p
* SSU MTU (ticket #682):
- Use local MTU detection - i2np.udp.mtu now sets max MTU, not initial MTU - Put local MTU in netDb - Fix receive MTU calculations - Track remote MTU based on actual received packet size - Display local MTU on peers page
This commit is contained in:
@@ -146,7 +146,7 @@ class EstablishmentManager {
|
||||
RemoteHostId to = null;
|
||||
InetAddress remAddr = addr.getHostAddress();
|
||||
int port = addr.getPort();
|
||||
if ( (remAddr != null) && (port > 0) ) {
|
||||
if (remAddr != null && port > 0 && port <= 65535) {
|
||||
to = new RemoteHostId(remAddr.getAddress(), port);
|
||||
|
||||
if (!_transport.isValid(to.getIP())) {
|
||||
|
||||
@@ -152,9 +152,11 @@ class PeerState {
|
||||
* we can use to publish that fact.
|
||||
*/
|
||||
private long _theyRelayToUsAs;
|
||||
/** what is the largest packet we can send to the peer? */
|
||||
/** what is the largest packet we can currently send to the peer? */
|
||||
private int _mtu;
|
||||
private int _mtuReceive;
|
||||
/** what is the largest packet we will ever send to the peer? */
|
||||
private final int _largeMTU;
|
||||
/* how many consecutive packets at or under the min MTU have been received */
|
||||
private long _consecutiveSmall;
|
||||
/** when did we last check the MTU? */
|
||||
@@ -259,8 +261,6 @@ class PeerState {
|
||||
|
||||
private static final int MIN_RTO = 100 + ACKSender.ACK_FREQUENCY;
|
||||
private static final int MAX_RTO = 3000; // 5000;
|
||||
/** override the default MTU */
|
||||
private static final String PROP_DEFAULT_MTU = "i2np.udp.mtu";
|
||||
|
||||
public PeerState(RouterContext ctx, UDPTransport transport,
|
||||
byte[] remoteIP, int remotePort, Hash remotePeer, boolean isInbound) {
|
||||
@@ -281,8 +281,9 @@ class PeerState {
|
||||
_receivePeriodBegin = now;
|
||||
_lastCongestionOccurred = -1;
|
||||
_remotePort = remotePort;
|
||||
_mtu = getDefaultMTU();
|
||||
_mtu = DEFAULT_MTU;
|
||||
_mtuReceive = _mtu;
|
||||
_largeMTU = transport.getMTU();
|
||||
//_mtuLastChecked = -1;
|
||||
_lastACKSend = -1;
|
||||
_rto = MIN_RTO;
|
||||
@@ -297,10 +298,6 @@ class PeerState {
|
||||
_remoteHostId = new RemoteHostId(remoteIP, remotePort);
|
||||
}
|
||||
|
||||
private int getDefaultMTU() {
|
||||
return _context.getProperty(PROP_DEFAULT_MTU, DEFAULT_MTU);
|
||||
}
|
||||
|
||||
/**
|
||||
* The peer are we talking to. This should be set as soon as this
|
||||
* state is created if we are initiating a connection, but if we are
|
||||
@@ -1025,13 +1022,13 @@ class PeerState {
|
||||
if (_packetsTransmitted > 10) {
|
||||
retransPct = (double)_packetsRetransmitted/(double)_packetsTransmitted;
|
||||
boolean wantLarge = retransPct < .30d; // heuristic to allow fairly lossy links to use large MTUs
|
||||
if (wantLarge && _mtu != LARGE_MTU) {
|
||||
if (wantLarge && _mtu != _largeMTU) {
|
||||
if (_context.random().nextLong(_mtuDecreases) <= 0) {
|
||||
_mtu = LARGE_MTU;
|
||||
_mtu = _largeMTU;
|
||||
_mtuIncreases++;
|
||||
_context.statManager().addRateData("udp.mtuIncrease", _mtuIncreases, _mtuDecreases);
|
||||
}
|
||||
} else if (!wantLarge && _mtu == LARGE_MTU) {
|
||||
} else if (!wantLarge && _mtu == _largeMTU) {
|
||||
_mtu = MIN_MTU;
|
||||
_mtuDecreases++;
|
||||
_context.statManager().addRateData("udp.mtuDecrease", _mtuDecreases, _mtuIncreases);
|
||||
@@ -1060,6 +1057,7 @@ class PeerState {
|
||||
adjustMTU();
|
||||
//_rto *= 2;
|
||||
}
|
||||
|
||||
public void packetsTransmitted(int packets) {
|
||||
//long now = _context.clock().now();
|
||||
_packetsTransmitted += packets;
|
||||
@@ -1073,6 +1071,7 @@ class PeerState {
|
||||
}
|
||||
*****/
|
||||
}
|
||||
|
||||
/** how long does it usually take to get a message ACKed? */
|
||||
public int getRTT() { return _rtt; }
|
||||
/** how soon should we retransmit an unacked packet? */
|
||||
@@ -1092,23 +1091,25 @@ class PeerState {
|
||||
public long getPacketsReceivedDuplicate() { return _packetsReceivedDuplicate; }
|
||||
|
||||
private static final int MTU_RCV_DISPLAY_THRESHOLD = 20;
|
||||
/** 60 */
|
||||
private static final int OVERHEAD_SIZE = PacketBuilder.IP_HEADER_SIZE + PacketBuilder.UDP_HEADER_SIZE +
|
||||
UDPPacket.MAC_SIZE + UDPPacket.IV_SIZE;
|
||||
|
||||
/**
|
||||
* @param size not including IP header, UDP header, MAC or IV
|
||||
*/
|
||||
public void packetReceived(int size) {
|
||||
_packetsReceived++;
|
||||
size += OVERHEAD_SIZE;
|
||||
if (size <= MIN_MTU) {
|
||||
_consecutiveSmall++;
|
||||
if (_consecutiveSmall >= MTU_RCV_DISPLAY_THRESHOLD)
|
||||
_mtuReceive = MIN_MTU;
|
||||
} else {
|
||||
_consecutiveSmall = 0;
|
||||
_mtuReceive = LARGE_MTU;
|
||||
return;
|
||||
if (size > _mtuReceive)
|
||||
_mtuReceive = size;
|
||||
}
|
||||
|
||||
if (_packetsReceived > MTU_RCV_DISPLAY_THRESHOLD) {
|
||||
if (_consecutiveSmall < MTU_RCV_DISPLAY_THRESHOLD)
|
||||
_mtuReceive = LARGE_MTU;
|
||||
else
|
||||
_mtuReceive = MIN_MTU;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,12 @@ public class UDPAddress {
|
||||
private int _introPorts[];
|
||||
private byte[] _introKeys[];
|
||||
private long _introTags[];
|
||||
private int _mtu;
|
||||
|
||||
public static final String PROP_PORT = "port";
|
||||
public static final String PROP_HOST = "host";
|
||||
public static final String PROP_INTRO_KEY = "key";
|
||||
public static final String PROP_MTU = "mtu";
|
||||
|
||||
public static final String PROP_CAPACITY = "caps";
|
||||
public static final char CAPACITY_TESTING = 'B';
|
||||
@@ -72,6 +74,11 @@ public class UDPAddress {
|
||||
} catch (NumberFormatException nfe) {
|
||||
_port = -1;
|
||||
}
|
||||
try {
|
||||
String mtu = addr.getOption(PROP_MTU);
|
||||
if (mtu != null)
|
||||
_mtu = MTU.rectify(Integer.parseInt(mtu));
|
||||
} catch (NumberFormatException nfe) {}
|
||||
String key = addr.getOption(PROP_INTRO_KEY);
|
||||
if (key != null)
|
||||
_introKey = Base64.decode(key.trim());
|
||||
@@ -91,7 +98,7 @@ public class UDPAddress {
|
||||
int p = -1;
|
||||
try {
|
||||
p = Integer.parseInt(port);
|
||||
if (p <= 0) continue;
|
||||
if (p <= 0 || p > 65535) continue;
|
||||
} catch (NumberFormatException nfe) {
|
||||
continue;
|
||||
}
|
||||
@@ -161,7 +168,12 @@ public class UDPAddress {
|
||||
}
|
||||
return _hostAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 0 if unset; -1 if invalid
|
||||
*/
|
||||
public int getPort() { return _port; }
|
||||
|
||||
byte[] getIntroKey() { return _introKey; }
|
||||
|
||||
int getIntroducerCount() { return (_introAddresses == null ? 0 : _introAddresses.length); }
|
||||
@@ -179,4 +191,11 @@ public class UDPAddress {
|
||||
byte[] getIntroducerKey(int i) { return _introKeys[i]; }
|
||||
long getIntroducerTag(int i) { return _introTags[i]; }
|
||||
|
||||
/**
|
||||
* @return 0 if unset or invalid; recitified via MTU.rectify()
|
||||
* @since 0.9.2
|
||||
*/
|
||||
int getMTU() {
|
||||
return _introPorts[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,15 +154,4 @@ class UDPEndpoint {
|
||||
return null;
|
||||
return _receiver.receiveNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* The MTU for the socket interface, if available.
|
||||
* Not available for Java 5.
|
||||
* @return 0 if Java 5, or if bound to an address;
|
||||
* limited to range MIN_MTU to LARGE_MTU.
|
||||
* @since 0.9.2
|
||||
*/
|
||||
public int getMTU() {
|
||||
return MTU.getMTU(_bindAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,12 @@ class UDPPacketReader {
|
||||
|
||||
/** parse out the data message */
|
||||
public class DataReader {
|
||||
|
||||
/**
|
||||
* @return the data size, NOT including IP header, UDP header, IV, or MAC
|
||||
*/
|
||||
public int getPacketSize() { return _payloadLength; }
|
||||
|
||||
public boolean readACKsIncluded() {
|
||||
return flagSet(UDPPacket.DATA_FLAG_EXPLICIT_ACK);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
private long _introducersSelectedOn;
|
||||
private long _lastInboundReceivedOn;
|
||||
private final DHSessionKeyBuilder.Factory _dhFactory;
|
||||
private int _mtu;
|
||||
|
||||
/** do we need to rebuild our external router address asap? */
|
||||
private boolean _needsRebuild;
|
||||
@@ -141,6 +142,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
public static final String PROP_ALLOW_DIRECT = "i2np.udp.allowDirect";
|
||||
/** this is rarely if ever used, default is to bind to wildcard address */
|
||||
public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface";
|
||||
/** override the "large" (max) MTU, default is PeerState.LARGE_MTU */
|
||||
private static final String PROP_DEFAULT_MTU = "i2np.udp.mtu";
|
||||
|
||||
/** how many relays offered to us will we use at a time? */
|
||||
public static final int PUBLIC_RELAY_COUNT = 3;
|
||||
@@ -213,6 +216,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_introManager = new IntroductionManager(_context, this);
|
||||
_introducersSelectedOn = -1;
|
||||
_lastInboundReceivedOn = -1;
|
||||
_mtu = PeerState.LARGE_MTU;
|
||||
_needsRebuild = true;
|
||||
|
||||
_context.statManager().createRateStat("udp.alreadyConnected", "What is the lifetime of a reestablished session", "udp", RATES);
|
||||
@@ -307,6 +311,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
// todo, set bind address too
|
||||
_endpoint.setListenPort(port);
|
||||
}
|
||||
setMTU(bindToAddr);
|
||||
|
||||
if (_establisher == null)
|
||||
_establisher = new EstablishmentManager(_context, this);
|
||||
@@ -403,6 +408,35 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
return _context.getProperty(PROP_INTERNAL_PORT, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the MTU for the socket interface at addr.
|
||||
* @param addr null ok
|
||||
* @since 0.9.2
|
||||
*/
|
||||
private void setMTU(InetAddress addr) {
|
||||
String p = _context.getProperty(PROP_DEFAULT_MTU);
|
||||
if (p != null) {
|
||||
try {
|
||||
_mtu = MTU.rectify(Integer.parseInt(p));
|
||||
return;
|
||||
} catch (NumberFormatException nfe) {}
|
||||
}
|
||||
int mtu = MTU.getMTU(addr);
|
||||
if (mtu <= 0)
|
||||
mtu = PeerState.LARGE_MTU;
|
||||
_mtu = mtu;
|
||||
}
|
||||
|
||||
/**
|
||||
* The MTU for the socket interface.
|
||||
* To be used as the "large" MTU.
|
||||
* @return limited to range PeerState.MIN_MTU to PeerState.LARGE_MTU.
|
||||
* @since 0.9.2
|
||||
*/
|
||||
public int getMTU() {
|
||||
return _mtu;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have received an inbound connection in the last 2 minutes, don't allow
|
||||
* our IP to change.
|
||||
@@ -1331,6 +1365,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
else
|
||||
options.setProperty(UDPAddress.PROP_CAPACITY, ""+UDPAddress.CAPACITY_TESTING + UDPAddress.CAPACITY_INTRODUCER);
|
||||
|
||||
// MTU since 0.9.2
|
||||
if (_mtu < PeerState.LARGE_MTU)
|
||||
options.setProperty(UDPAddress.PROP_MTU, Integer.toString(_mtu));
|
||||
|
||||
if (directIncluded || introducersIncluded) {
|
||||
// This is called via TransportManager.configTransports() before startup(), prevent NPE
|
||||
if (_introKey != null)
|
||||
@@ -2171,7 +2209,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
|
||||
// buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
|
||||
buf.append("<tr class=\"tablefooter\"> <td colspan=\"3\" align=\"left\"><b>").append(_("SUMMARY")).append("</b></td>" +
|
||||
buf.append("<tr class=\"tablefooter\"><td colspan=\"3\" align=\"left\"><b>").append(_("SUMMARY")).append("</b></td>" +
|
||||
"<td align=\"center\" nowrap><b>");
|
||||
buf.append(formatKBps(bpsIn)).append(THINSP).append(formatKBps(bpsOut));
|
||||
long x = numPeers > 0 ? uptimeMsTotal/numPeers : 0;
|
||||
@@ -2184,10 +2222,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
buf.append("</b></td><td> </td>\n" +
|
||||
"<td align=\"center\"><b>");
|
||||
buf.append(numPeers > 0 ? DataHelper.formatDuration2(rttTotal/numPeers) : '0');
|
||||
buf.append("</b></td><td> </td> <td align=\"center\"><b>");
|
||||
buf.append("</b></td><td> </td><td align=\"center\"><b>");
|
||||
buf.append(numPeers > 0 ? DataHelper.formatDuration2(rtoTotal/numPeers) : '0');
|
||||
buf.append("</b></td><td> </td> <td align=\"center\"><b>");
|
||||
buf.append(sendTotal).append("</b></td> <td align=\"center\"><b>").append(recvTotal).append("</b></td>\n" +
|
||||
buf.append("</b></td><td align=\"center\"><b>").append(_mtu).append("</b></td><td align=\"center\"><b>");
|
||||
buf.append(sendTotal).append("</b></td><td align=\"center\"><b>").append(recvTotal).append("</b></td>\n" +
|
||||
"<td align=\"center\"><b>").append(resentTotal);
|
||||
buf.append("</b></td><td align=\"center\"><b>").append(dupRecvTotal).append("</b></td>\n" +
|
||||
"</tr></table>\n");
|
||||
|
||||
Reference in New Issue
Block a user