Changeset 258effc


Ignore:
Timestamp:
Dec 7, 2011 12:51:31 AM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
1d842f02, 51f20c2
Parents:
3bd641a
Message:
  • UDP PacketBuilder?:
    • Again allow transmitting all new acks if there is room; only limit resend acks
    • Sanity checks to limit to 255 acks
Location:
router/java/src/net/i2p/router/transport/udp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/transport/udp/OutboundMessageFragments.java

    r3bd641a r258effc  
    373373            // ok, simplest possible thing is to always tack on the bitfields if
    374374            List<Long> msgIds = peer.getCurrentFullACKs();
     375            int newFullAckCount = msgIds.size();
     376            msgIds.addAll(peer.getCurrentResendACKs());
    375377            List<ACKBitfield> partialACKBitfields = new ArrayList();
    376378            peer.fetchPartialACKs(partialACKBitfields);
     
    383385            for (int i = 0; i < fragments; i++) {
    384386                if (state.needsSending(i)) {
     387                    int before = remaining.size();
    385388                    try {
    386                         rv[i] = _builder.buildPacket(state, i, peer, remaining, partialACKBitfields);
     389                        rv[i] = _builder.buildPacket(state, i, peer, remaining, newFullAckCount, partialACKBitfields);
    387390                    } catch (ArrayIndexOutOfBoundsException aioobe) {
    388391                        _log.log(Log.CRIT, "Corrupt trying to build a packet - please tell jrandom: " +
     
    391394                        continue;
    392395                    }
     396                    int after = remaining.size();
     397                    newFullAckCount = Math.max(0, newFullAckCount - (before - after));
    393398                    if (rv[i] == null) {
    394399                        sparseCount++;
  • router/java/src/net/i2p/router/transport/udp/PacketBuilder.java

    r3bd641a r258effc  
    139139    public static final int MIN_DATA_PACKET_OVERHEAD = IP_HEADER_SIZE + UDP_HEADER_SIZE + DATA_HEADER_SIZE;
    140140
     141    /** one byte field */
     142    public static final int ABSOLUTE_MAX_ACKS = 255;
     143
    141144    /**
    142145     *  Only for data packets. No limit in ack-only packets.
    143146     *  This directly affects data packet overhead.
    144147     */
    145     private static final int MAX_EXPLICIT_ACKS_LARGE = 9;
     148    private static final int MAX_RESEND_ACKS_LARGE = 9;
    146149
    147150    /**
     
    149152     *  This directly affects data packet overhead.
    150153     */
    151     private static final int MAX_EXPLICIT_ACKS_SMALL = 4;
     154    private static final int MAX_RESEND_ACKS_SMALL = 4;
    152155
    153156    public PacketBuilder(I2PAppContext ctx, UDPTransport transport) {
     
    203206     *                        non-null.
    204207     *
     208     * @param newAckCount the number of ackIdsRemaining entries that are new. These must be the first
     209     *                    ones in the list
     210     *
    205211     * @param partialACKsRemaining list of messageIds (ACKBitfield) that should be acked by this packet. 
    206212     *                        The list itself is passed by reference, and if a messageId is
     
    213219     */
    214220    public UDPPacket buildPacket(OutboundMessageState state, int fragment, PeerState peer,
    215                                  List<Long> ackIdsRemaining, List<ACKBitfield> partialACKsRemaining) {
     221                                 List<Long> ackIdsRemaining, int newAckCount,
     222                                 List<ACKBitfield> partialACKsRemaining) {
    216223        UDPPacket packet = buildPacketHeader((byte)(UDPPacket.PAYLOAD_TYPE_DATA << 4));
    217224        byte data[] = packet.getPacket().getData();
     
    246253        if (availableForExplicitAcks >= 6 && !partialACKsRemaining.isEmpty()) {
    247254            for (ACKBitfield bf : partialACKsRemaining) {
     255                if (partialAcksToSend >= ABSOLUTE_MAX_ACKS)
     256                    break;  // ack count
    248257                if (bf.receivedComplete())
    249258                    continue;
     
    273282            msg.append(" data: ").append(dataSize).append(" bytes, mtu: ")
    274283               .append(currentMTU).append(", ")
    275                .append(ackIdsRemaining.size()).append(" full acks requested, ")
     284               .append(newAckCount).append(" new full acks requested, ")
     285               .append(ackIdsRemaining.size() - newAckCount).append(" resend acks requested, ")
    276286               .append(partialACKsRemaining.size()).append(" partial acks requested, ")
    277287               .append(availableForAcks).append(" avail. for all acks, ")
     
    279289        }
    280290
    281         int explicitToSend = Math.min(currentMTU > PeerState.MIN_MTU ? MAX_EXPLICIT_ACKS_LARGE : MAX_EXPLICIT_ACKS_SMALL,
    282                                       Math.min((availableForExplicitAcks - 1) / 4, ackIdsRemaining.size()));
     291        // always send all the new acks if we have room
     292        int explicitToSend = Math.min(ABSOLUTE_MAX_ACKS,
     293                                      Math.min(newAckCount + (currentMTU > PeerState.MIN_MTU ? MAX_RESEND_ACKS_LARGE : MAX_RESEND_ACKS_SMALL),
     294                                               Math.min((availableForExplicitAcks - 1) / 4, ackIdsRemaining.size())));
    283295        if (explicitToSend > 0) {
    284296            if (msg != null)
     
    422434     *  See buildPacket() for format.
    423435     *
     436     *  TODO MTU not enforced.
     437     *  TODO handle huge number of acks better
     438     *
    424439     * @param ackBitfields list of ACKBitfield instances to either fully or partially ACK
    425440     */
     
    443458                partialACKCount++;
    444459        }
     460        // FIXME do better than this, we could still exceed MTU
     461        if (fullACKCount > ABSOLUTE_MAX_ACKS ||
     462            partialACKCount > ABSOLUTE_MAX_ACKS)
     463            throw new IllegalArgumentException("Too many acks full/partial " + fullACKCount +
     464                                               '/' + partialACKCount);
     465
    445466        // ok, now for the body...
    446467        if (fullACKCount > 0)
  • router/java/src/net/i2p/router/transport/udp/PeerState.java

    r3bd641a r258effc  
    715715     * removeACKMessage(Long) should be called.
    716716     *
    717      * The returned list contains acks not yet sent, followed by
     717     * The returned list contains acks not yet sent only.
     718     * The caller should NOT transmit all of them all the time,
     719     * even if there is room,
     720     * or the packets will have way too much overhead.
     721     *
     722     * @return a new list, do as you like with it
     723     */
     724    public List<Long> getCurrentFullACKs() {
     725            // no such element exception seen here
     726            List<Long> rv = new ArrayList(_currentACKs);
     727            if (_log.shouldLog(Log.DEBUG))
     728                _log.debug("Returning " + _currentACKs.size() + " current acks");
     729            return rv;
     730    }
     731
     732    /**
     733     * Grab a list of message ids (Long) that we want to send to the remote
     734     * peer, regardless of the packet size, but don't remove it from our
     735     * "want to send" list.
     736     *
     737     * The returned list contains
    718738     * a random assortment of acks already sent.
    719739     * The caller should NOT transmit all of them all the time,
     
    722742     *
    723743     * @return a new list, do as you like with it
    724      */
    725     public List<Long> getCurrentFullACKs() {
    726             // no such element exception seen here
    727             List<Long> rv = new ArrayList(_currentACKs);
    728             // include some for retransmission
     744     * @since 0.8.12 was included in getCurrentFullACKs()
     745     */
     746    public List<Long> getCurrentResendACKs() {
    729747            List<Long> randomResends = new ArrayList(_currentACKsResend);
    730748            Collections.shuffle(randomResends, _context.random());
    731             rv.addAll(randomResends);
    732             if (_log.shouldLog(Log.INFO))
    733                 _log.info("Returning " + _currentACKs.size() + " current and " + randomResends.size() + " resend acks");
    734             return rv;
     749            if (_log.shouldLog(Log.DEBUG))
     750                _log.debug("Returning " + randomResends.size() + " resend acks");
     751            return randomResends;
    735752    }
    736753
Note: See TracChangeset for help on using the changeset viewer.