forked from I2P_Developers/i2p.i2p
* UDP:
- Revert change in UDPPacket that caused massive corruption - Reduce buffer sizes from 2048 to 1536 - Discard too-large received packets sooner - More cleanups - Notes on MTU
This commit is contained in:
@ -33,7 +33,8 @@ class InboundMessageState {
|
||||
private static final long MAX_RECEIVE_TIME = 10*1000;
|
||||
public static final int MAX_FRAGMENTS = 64;
|
||||
|
||||
private static final ByteCache _fragmentCache = ByteCache.getInstance(64, 2048);
|
||||
private static final int MAX_FRAGMENT_SIZE = UDPPacket.MAX_PACKET_SIZE;
|
||||
private static final ByteCache _fragmentCache = ByteCache.getInstance(64, MAX_FRAGMENT_SIZE);
|
||||
|
||||
public InboundMessageState(RouterContext ctx, long messageId, Hash from) {
|
||||
_context = ctx;
|
||||
|
@ -157,7 +157,7 @@ class PeerState {
|
||||
/* how many consecutive packets at or under the min MTU have been received */
|
||||
private long _consecutiveSmall;
|
||||
/** when did we last check the MTU? */
|
||||
private long _mtuLastChecked;
|
||||
//private long _mtuLastChecked;
|
||||
private long _mtuIncreases;
|
||||
private long _mtuDecreases;
|
||||
/** current round trip time estimate */
|
||||
@ -224,7 +224,7 @@ class PeerState {
|
||||
* of 608
|
||||
*
|
||||
* Well, we really need to count the acks as well, especially
|
||||
* 4 * MAX_RESEND_ACKS which can take up a significant amount of space.
|
||||
* 1 + (4 * MAX_RESEND_ACKS_SMALL) which can take up a significant amount of space.
|
||||
* We reduce the max acks when using the small MTU but it may not be enough...
|
||||
*
|
||||
*/
|
||||
@ -234,6 +234,12 @@ class PeerState {
|
||||
* based on measurements, 1350 fits nearly all reasonably small I2NP messages
|
||||
* (larger I2NP messages may be up to 1900B-4500B, which isn't going to fit
|
||||
* into a live network MTU anyway)
|
||||
*
|
||||
* TODO
|
||||
* VTBM is 2646, it would be nice to fit in two large
|
||||
* 2646 / 2 = 1323
|
||||
* 1323 + 74 + 46 + 1 + (4 * 9) = 1480
|
||||
* So why not make it 1492 (old ethernet is 1492, new is 1500)
|
||||
*/
|
||||
private static final int LARGE_MTU = 1350;
|
||||
|
||||
@ -261,7 +267,7 @@ class PeerState {
|
||||
_remotePort = -1;
|
||||
_mtu = getDefaultMTU();
|
||||
_mtuReceive = _mtu;
|
||||
_mtuLastChecked = -1;
|
||||
//_mtuLastChecked = -1;
|
||||
_lastACKSend = -1;
|
||||
_rto = MIN_RTO;
|
||||
_rtt = _rto/2;
|
||||
@ -370,13 +376,20 @@ class PeerState {
|
||||
public long getTheyRelayToUsAs() { return _theyRelayToUsAs; }
|
||||
/** what is the largest packet we can send to the peer? */
|
||||
public int getMTU() { return _mtu; }
|
||||
/** estimate how large the other side is sending packets */
|
||||
|
||||
/**
|
||||
* Estimate how large the other side's MTU is.
|
||||
* This could be wrong.
|
||||
* It is used only for the HTML status.
|
||||
*/
|
||||
public int getReceiveMTU() { return _mtuReceive; }
|
||||
|
||||
/** when did we last check the MTU? */
|
||||
/****
|
||||
public long getMTULastChecked() { return _mtuLastChecked; }
|
||||
public long getMTUIncreases() { return _mtuIncreases; }
|
||||
public long getMTUDecreases() { return _mtuDecreases; }
|
||||
|
||||
****/
|
||||
|
||||
/**
|
||||
* The peer are we talking to. This should be set as soon as this
|
||||
@ -537,11 +550,15 @@ class PeerState {
|
||||
* we can use to publish that fact.
|
||||
*/
|
||||
public void setTheyRelayToUsAs(long tag) { _theyRelayToUsAs = tag; }
|
||||
|
||||
/** what is the largest packet we can send to the peer? */
|
||||
/****
|
||||
public void setMTU(int mtu) {
|
||||
_mtu = mtu;
|
||||
_mtuLastChecked = _context.clock().now();
|
||||
}
|
||||
****/
|
||||
|
||||
public int getSlowStartThreshold() { return _slowStartThreshold; }
|
||||
public int getConcurrentSends() { return _concurrentMessagesActive; }
|
||||
public int getConcurrentSendWindow() { return _concurrentMessagesAllowed; }
|
||||
@ -979,15 +996,21 @@ class PeerState {
|
||||
public long getPacketRetransmissionRate() { return _packetRetransmissionRate; }
|
||||
public long getPacketsReceived() { return _packetsReceived; }
|
||||
public long getPacketsReceivedDuplicate() { return _packetsReceivedDuplicate; }
|
||||
|
||||
private static final int MTU_RCV_DISPLAY_THRESHOLD = 20;
|
||||
|
||||
public void packetReceived(int size) {
|
||||
_packetsReceived++;
|
||||
if (size <= MIN_MTU)
|
||||
if (size <= MIN_MTU) {
|
||||
_consecutiveSmall++;
|
||||
else
|
||||
} else {
|
||||
_consecutiveSmall = 0;
|
||||
_mtuReceive = LARGE_MTU;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_packetsReceived > 50) {
|
||||
if (_consecutiveSmall < 50)
|
||||
if (_packetsReceived > MTU_RCV_DISPLAY_THRESHOLD) {
|
||||
if (_consecutiveSmall < MTU_RCV_DISPLAY_THRESHOLD)
|
||||
_mtuReceive = LARGE_MTU;
|
||||
else
|
||||
_mtuReceive = MIN_MTU;
|
||||
@ -1287,7 +1310,11 @@ class PeerState {
|
||||
private static final int SSU_HEADER_SIZE = 46;
|
||||
static final int UDP_HEADER_SIZE = 8;
|
||||
static final int IP_HEADER_SIZE = 20;
|
||||
/** how much payload data can we shove in there? */
|
||||
|
||||
/**
|
||||
* how much payload data can we shove in there?
|
||||
* @return MTU - 74
|
||||
*/
|
||||
private static final int fragmentSize(int mtu) {
|
||||
return mtu - SSU_HEADER_SIZE - UDP_HEADER_SIZE - IP_HEADER_SIZE;
|
||||
}
|
||||
@ -1296,7 +1323,7 @@ class PeerState {
|
||||
long now = _context.clock().now();
|
||||
if (state.getNextSendTime() <= now) {
|
||||
if (!state.isFragmented()) {
|
||||
state.fragment(fragmentSize(getMTU()));
|
||||
state.fragment(fragmentSize(_mtu));
|
||||
if (state.getMessage() != null)
|
||||
state.getMessage().timestamp("fragment into " + state.getFragmentCount());
|
||||
|
||||
|
@ -51,7 +51,13 @@ class UDPPacket {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(UDPPacket.class);
|
||||
}
|
||||
|
||||
static final int MAX_PACKET_SIZE = 2048;
|
||||
/**
|
||||
* Actually it is one less than this, we assume
|
||||
* if a received packet is this big it is truncated.
|
||||
* This is bigger than PeerState.LARGE_MTU, as the far-end's
|
||||
* LARGE_MTU may be larger than ours.
|
||||
*/
|
||||
static final int MAX_PACKET_SIZE = 1536;
|
||||
public static final int IV_SIZE = 16;
|
||||
public static final int MAC_SIZE = 16;
|
||||
|
||||
@ -96,7 +102,12 @@ class UDPPacket {
|
||||
//_dataBuf = _dataCache.acquire();
|
||||
Arrays.fill(_data, (byte)0);
|
||||
//_packet = new DatagramPacket(_data, MAX_PACKET_SIZE);
|
||||
//_packet.setData(_data);
|
||||
//
|
||||
// WARNING -
|
||||
// Doesn't seem like we should have to do this every time,
|
||||
// from reading the DatagramPacket javadocs,
|
||||
// but we get massive corruption without it.
|
||||
_packet.setData(_data);
|
||||
// _isInbound = inbound;
|
||||
_initializeTime = _context.clock().now();
|
||||
_markedType = -1;
|
||||
|
@ -354,7 +354,9 @@ class UDPPacketReader {
|
||||
off++; // fragment info
|
||||
return ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF;
|
||||
}
|
||||
public void readMessageFragment(int fragmentNum, byte target[], int targetOffset) {
|
||||
|
||||
public void readMessageFragment(int fragmentNum, byte target[], int targetOffset)
|
||||
throws ArrayIndexOutOfBoundsException {
|
||||
int off = getFragmentBegin(fragmentNum);
|
||||
off += 4; // messageId
|
||||
off++; // fragment info
|
||||
|
@ -243,6 +243,10 @@ class UDPReceiver {
|
||||
|
||||
// and block after we know how much we read but before
|
||||
// we release the packet to the inbound queue
|
||||
if (size >= UDPPacket.MAX_PACKET_SIZE) {
|
||||
// DatagramSocket javadocs: If the message is longer than the packet's length, the message is truncated.
|
||||
throw new IOException("packet too large! truncated and dropped");
|
||||
}
|
||||
if (size > 0) {
|
||||
//FIFOBandwidthLimiter.Request req = _context.bandwidthLimiter().requestInbound(size, "UDP receiver");
|
||||
//_context.bandwidthLimiter().requestInbound(req, size, "UDP receiver");
|
||||
|
Reference in New Issue
Block a user