SSU2: Fix overhead calculations

This commit is contained in:
zzz
2022-02-26 16:33:35 -05:00
parent e7f98e9243
commit e3db28542c
4 changed files with 76 additions and 18 deletions

View File

@@ -58,14 +58,14 @@ class PacketBuilder2 {
static final int TYPE_CREAT = 73;
/** IPv4 only */
public static final int IP_HEADER_SIZE = 20;
public static final int IP_HEADER_SIZE = PacketBuilder.IP_HEADER_SIZE;
/** Same for IPv4 and IPv6 */
public static final int UDP_HEADER_SIZE = 8;
public static final int UDP_HEADER_SIZE = PacketBuilder.UDP_HEADER_SIZE;
/** 74 */
public static final int MIN_DATA_PACKET_OVERHEAD = IP_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE + MAC_LEN;
public static final int IPV6_HEADER_SIZE = 40;
public static final int IPV6_HEADER_SIZE = PacketBuilder.IPV6_HEADER_SIZE;
/** 94 */
public static final int MIN_IPV6_DATA_PACKET_OVERHEAD = IPV6_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE + MAC_LEN;
@@ -135,7 +135,7 @@ class PacketBuilder2 {
// calculate data size
int numFragments = fragments.size();
int dataSize = 0;
int priority = 0;
int priority = PRIORITY_LOW;
for (int i = 0; i < numFragments; i++) {
Fragment frag = fragments.get(i);
OutboundMessageState state = frag.state;
@@ -176,7 +176,7 @@ class PacketBuilder2 {
// add the acks
if (availableForAcks >= SSU2Payload.BLOCK_HEADER_SIZE + 5) {
int maxRanges = (availableForAcks - (SSU2Payload.BLOCK_HEADER_SIZE + 5)) / 2;
int maxRanges = Math.min((availableForAcks - (SSU2Payload.BLOCK_HEADER_SIZE + 5)) / 2, ABSOLUTE_MAX_ACK_RANGES);
Block block = peer.getReceivedMessages().toAckBlock(maxRanges);
if (block != null) {
blocks.add(block);
@@ -255,7 +255,7 @@ class PacketBuilder2 {
pkt.setLength(off);
encryptDataPacket(packet, peer.getSendCipher(), pktNum, peer.getSendHeaderEncryptKey1(), peer.getSendHeaderEncryptKey2());
setTo(packet, peer.getRemoteIPAddress(), peer.getRemotePort());
packet.setPriority(0);
packet.setPriority(PRIORITY_LOW);
return packet;
}

View File

@@ -137,7 +137,7 @@ public class PeerState {
*/
private volatile int _slowStartThreshold;
/** what IP is the peer sending and receiving packets on? */
private final byte[] _remoteIP;
protected final byte[] _remoteIP;
/** cached IP address */
private volatile InetAddress _remoteIPAddress;
/** what port is the peer sending and receiving packets on? */
@@ -160,7 +160,7 @@ public class PeerState {
*/
private long _theyRelayToUsAs;
/** what is the largest packet we can currently send to the peer? */
private int _mtu;
protected int _mtu;
private int _mtuReceive;
/** what is the largest packet we will ever send to the peer? */
private int _largeMTU;
@@ -394,8 +394,6 @@ public class PeerState {
_keyEstablishedTime = now;
_lastSendTime = now;
_lastReceiveTime = now;
_currentACKs = new ConcurrentHashSet<Long>();
_currentACKsResend = new LinkedBlockingQueue<ResendACK>();
_slowStartThreshold = MAX_SEND_WINDOW_BYTES/2;
_receivePeriodBegin = now;
_remoteIP = addr.getAddress().getAddress();
@@ -428,11 +426,14 @@ public class PeerState {
_inboundMessages = new HashMap<Long, InboundMessageState>(8);
_outboundMessages = new CachedIteratorCollection<OutboundMessageState>();
_outboundQueue = new PriBlockingQueue<OutboundMessageState>(ctx, "UDP-PeerState", 32);
_ackedMessages = new AckedMessages();
_remotePeer = remotePeer;
_isInbound = isInbound;
_remoteHostId = new RemoteHostId(_remoteIP, _remotePort);
_bwEstimator = new SimpleBandwidthEstimator(ctx, this);
// Unused in SSU2
_currentACKs = null;
_currentACKsResend = null;
_ackedMessages = null;
}
/**

View File

@@ -3,6 +3,7 @@ package net.i2p.router.transport.udp;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.southernstorm.noise.protocol.CipherState;
@@ -66,8 +67,59 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
_sentMessages = new SSU2Bitfield(256, 0);
}
// SSU 1 overrides
@Override
public int getVersion() { return 2; }
/**
* how much payload data can we shove in there?
* Does NOT leave any room for acks, we'll fit them in when we can.
* This is 5 bytes too low for first or only fragment.
*
* @return MTU - 68 (IPv4), MTU - 88 (IPv6)
*/
@Override
int fragmentSize() {
// 20 + 8 + 16 + 3 + 5 + 16 = 68 (IPv4)
// 40 + 8 + 16 + 3 + 5 + 16 = 88 (IPv6)
return _mtu -
(_remoteIP.length == 4 ? PacketBuilder2.MIN_DATA_PACKET_OVERHEAD : PacketBuilder2.MIN_IPV6_DATA_PACKET_OVERHEAD) -
DATA_FOLLOWON_EXTRA_SIZE; // Followon fragment block overhead (5)
}
/**
* Packet overhead
* Does NOT leave any room for acks, we'll fit them in when we can.
* This is 5 bytes too high for first or only fragment.
*
* @return 68 (IPv4), 88 (IPv6)
*/
@Override
int fragmentOverhead() {
// 20 + 8 + 16 + 3 + 5 + 16 = 68 (IPv4)
// 40 + 8 + 16 + 3 + 5 + 16 = 88 (IPv6)
return (_remoteIP.length == 4 ? PacketBuilder2.MIN_DATA_PACKET_OVERHEAD : PacketBuilder2.MIN_IPV6_DATA_PACKET_OVERHEAD) +
DATA_FOLLOWON_EXTRA_SIZE; // Followon fragment block overhead (5)
}
// SSU 1 unsupported things
@Override
void setCurrentMACKey(SessionKey key) { throw new UnsupportedOperationException(); }
@Override
void setCurrentCipherKey(SessionKey key) { throw new UnsupportedOperationException(); }
@Override
List<Long> getCurrentFullACKs() { throw new UnsupportedOperationException(); }
@Override
List<Long> getCurrentResendACKs() { throw new UnsupportedOperationException(); }
@Override
void removeACKMessage(Long messageId) { throw new UnsupportedOperationException(); }
@Override
void fetchPartialACKs(List<ACKBitfield> rv) { throw new UnsupportedOperationException(); }
// SSU 2 things
long getNextPacketNumber() { return _packetNumber.incrementAndGet(); }
long getSendConnID() { return _sendConnID; }
long getRcvConnID() { return _rcvConnID; }

View File

@@ -55,17 +55,22 @@ final class SSU2Util {
public static final int MIN_HANDSHAKE_DATA_LEN = SESSION_HEADER_SIZE + TOTAL_PROT_SAMPLE_LEN;
/** 3 byte block header + 9 byte I2NP header = 12 */
public static final int FULL_I2NP_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 9;
/** 3 byte block header */
public static final int FULL_I2NP_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE;
/** 3 byte block header + 9 byte I2NP header = 12 */
public static final int FIRST_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 9;
/** 3 byte block header */
public static final int FIRST_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE;
/**
* 5 for flag and msg number in followon block
*/
public static final int DATA_FOLLOWON_EXTRA_SIZE = 5;
/** 3 byte block header + 4 byte msg ID + 1 byte fragment info = 8 */
public static final int FOLLOWON_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + 5;
public static final int FOLLOWON_FRAGMENT_HEADER_SIZE = SSU2Payload.BLOCK_HEADER_SIZE + DATA_FOLLOWON_EXTRA_SIZE;
/** 16 byte block header + 2 + 12 = 30 */
public static final int DATA_HEADER_SIZE = SHORT_HEADER_SIZE + 2 + FULL_I2NP_HEADER_SIZE;
/** 16 byte short header + 3 = 19 */
public static final int DATA_HEADER_SIZE = SHORT_HEADER_SIZE + FULL_I2NP_HEADER_SIZE;
/**
* The message types, 0-10, as bytes