On Wednesday 24 March 2010 17:42:12 Evan Daniel wrote:
> The current FNP protocol leaves a bit to be desired.  It has more
> overhead than we'd like, it can only pad packets with random data (not
> useful bulk transfers), it doesn't handle small MTUs, and its
> congestion avoidance isn't as TCP-compatible as we'd like.
> 
> The most immediate problem is probably that it would make a transport
> plugin infrastructure overly complicated.  For example, a lot of
> interesting steganographic transports (VoIP, chat, and video game
> imitators, for example) have a low MTU.  That means the plugins would
> need to support packet fragmenting and reassembly, or add another
> layer between FNP and the transport plugins.  Neither solution is
> particularly desirable.
> 
> Toad and I have talked about this some on IRC.  I've written up a
> partial draft proposal that draws heavily on the old "New protocol"
> proposal, but makes some improvements (I hope ;) ).  You can find it
> at http://new-wiki.freenetproject.org/User:Evanbd/New_Packet_Format_Proposal
> .  Comments are very welcome, especially from anyone well versed in
> network theory.

The MAC may need to be lengthened, or to scale depending on packet size. There 
is some doubt about hash-then-encrypt, I was told after much searching that an 
outer hash is better, but in any case, it needs to not be computable by a 
snooper. If a short MAC is not sufficient to guarantee that the message has not 
been tampered with then we need to consider alternatives for small packets such 
as MACing at a higher level. We need to research this before deploying small 
MACs.

We discussed this extensively on IRC, evanbd will be writing up a new proposal 
soon. Denial of service attacks are potentially a problem because fragmentation 
is initiated by the sender, and could use a significant amount of memory if the 
sender is malicious. We can avoid this by setting (and publishing to the other 
side) limits on both the number of message ID's in flight and the total bytes 
cached by the recipient. The latter should be no more than 128K per peer, for 
now, because we are not including block transfers (32KB) in this: They will be 
recipient-originated. Hence the size limit for sender-initiated messages can be 
very small, say 4KB. It may still be necessary to support an explicit NACK of a 
message causing it to be resent by the sender; certainly the sender should not 
forget the data in the message until the whole message has been acked. 

For the time being, we should keep the current DMT message format, although in 
the long term we can probably improve on it.

Re padding, IMHO we don't need an explicit padding message type - we either 
declare the number of messages at the beginning (which presumably costs us one 
byte), or we override the message length to indicate last message?? Dunno, if 
the message type is only one byte it would be feasible; we can do different 
changes at different times anyhow.

Ack timing is indeed a problem - we probably don't want to give timings for 
each packet. Although we could probably get away with 2 bytes or even 1 in many 
cases? If we are only using them to calculate the average ping time then we 
probably only need one ack timing for all the acks, being the average, which 
could be a part of the format?

We might also consider compressing the high-level 8-byte UID's that are sent in 
almost all messages - probably by the recipient telling the sender that it is 
allocating a short-ID for the long ID, and then the sender using the short-ID.

Packets, not message fragments, are acked, right? This will save a lot of space 
on the network level, although it means the sender will need to track exactly 
what was in each packet he sent. This could be a significant amount of memory 
on high bandwidth * latency connections; this might be significant relative to 
what we have to keep anyway for data in progress on connections with small 
packet sizes (e.g. mimicing skype). There is no "inner sequence number", and 
there is no way for the receiver to know whether a packet was resent; if the 
packet doesn't get acked, the sender resends *its contents*, and these are 
discarded or accepted based on message ID's and ranges; in any case the packet 
will be acked. As I have already mentioned IMHO sender-initiated streams should 
be limited to 4KB (whereas recipient-initiated can be big but will usually be 
<2^24-1).

Very late packets will be dropped because the recipient won't recognise them; 
they are outside of the window within which we recognise the precomputed 
encrypted message sequence numbers, I believe this is discussed on the old new 
packet format page? In any case, we don't have to change the crypto and the 
message packing at the same time; the principle that if a packet is severely 
delayed, it will be dropped, is reasonable; the sender will then resend it, if 
it hasn't been acked. There is only one resend per packet number, which 
simplifies life significantly and is the right choice; resending creates a new 
packet and a new packet number.

The new crypto design is clearly much better than the old one. In the new 
crypto design, we use the IV key to encrypt (ECB mode) the sequence number, 
creating the IV for the whole packet, then we simply put the packet sequence 
number at the beginning so it is the sequence number XORed with the IV's first 
four bytes (the packet being PCFB encrypted since it's variable length). In the 
old design, we have a full hash at the beginning of the packet, and within the 
rest of the packet we have a fixed 12 bytes of random data to randomise the 
hash!

As I see it, when the receiver drops a partially assembled message (a highly 
undesirable operation that should not happen in normal non-malicious use), 
because of either the fragment window ( == maximum number of partially 
assembled messages in flight ), or the buffer limit ( = bytes of partially 
assembled messages), we need an explicit NACK of that message (and the range we 
are dropping??). In any case the sender knows what has been acked and can thus 
keep on resending messages that are not ACKed, and refuse to allocate new 
message numbers while it has a window full of stuff that hasn't been ACKed yet.

IMHO reliable delivery is an essential building block of all the higher level 
stuff: We can't just drop messages.

And yes, clearly once we have assembled a fragmented message and passed it on, 
we can never accept that message again. Meaning until it falls out of the 
window we will need to remember the fact that we have accepted it. This can 
however be implemented very efficiently.

8192 seems arbitrary, I can see why it makes sense with the bit fields ...

With regards to congestion control, IMHO we should keep the current TCP-like 
peer-level congestion control for now. This seems to work, and should 
co-operate with TCP reasonably well i.e. not flood out TCP traffic nor be too 
easily flooded out by it.

Retransmission: TCP retransmits after 4 RTTs unconditionally and after 
receiving an ack for a later packet. IMHO this is a good model. Our current 
code does all sorts of wierd things with explicit retransmit requests and so 
on, which isn't a good model.

Given that we only have the message size on the first fragment, we can't 
allocate a buffer for the whole message if we receive the second fragment 
first. Not including the size on later fragments may be important for byte 
scavenging, so that determines the matter. However, especially on transports 
with small packets, the memory overhead of keeping each fragment in memory 
separately may be significant.

As you mentioned we probably need 3 classes. Each will need a separate message 
ID sequence, its own message window size, and its own size limits; 
sender-initiated fragmented messages can have a 4KB limit, block transfers may 
be a fixed size or may have a ~ 35K limit, bulk transfers can be huge. Each 
will presumably need its own length byte and sequence number in the packet; if 
we have a flags byte we can maybe avoid these in most cases.

I am uncertain about prioritising SSK inserts and transferring everything at 
once. It makes a certain amount of sense but there may be problems...

Agreed about fixed per-peer allocation.
> 
> We currently have two potential gsoc students who are interested in
> transport plugins.  We should improve FNP in parallel with that, imho.
>  It's also possible that one of them could work on FNP and the other
> on transport plugins, if there is interest.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part.
URL: 
<https://emu.freenetproject.org/pipermail/devl/attachments/20100401/6d552530/attachment.pgp>

Reply via email to