This introduces interfaces to represent the packet forwarding
mechanism, and brings all the scattered UDP-related code together into
a single implementation.
This is not a pure refactoring, although much of the code in sleeve.go
has been copied from pre-existing code, and the UDP protocol remains
the same in spirit. The biggest change is the organization of the
forwarder goroutines (there is now one instead of two, and that
goroutine does a lot of auxiliary work as well as forwarding).
Performance testing between VMs on my laptop suggests that packet
throughput has not gone down, and may even have improved slightly.
The delay d(n) for the nth retry was
d(1) = rand(initial_interval)
d(n+1) = d(n) + rand(d(n))
There are two problem with this:
1) The entire sequence is dominated by the random value for d(1). If
this is a small value, lots of retries at short interval ensue. In
extremis, if d(1) is 0, indefinite immediate retries would ensue.
2) The delay is not a true exponential backoff; the upper bound only
increases exponentially *probabilistically*.
The new algorithm calculates
d(n) = random_value in range [i-i/2,i+i/2],
where i = initial_interval * 1.5^(n-1).
Thus d(1) is at least initial_interval/2, and successive values are
independent of previous values, forming a true exponential sequence of
intervals bounds between which the retry delay is chosen randomly.
Due to the change in algorithm we reduce...
- the initial interval from 5s to 2s. Recall that previously d(1) was
in the range [0,initial_interval=5s]. It is now [2-2/2=1s,2+2/2=3s].
- the max interval from 10 minutes to 6. Previously, once that was
reached, it would stay exactly there. It is now randomly chosen in
the range [6-6/2=3m,6+6/2=9min].
Thus previously delays would range from 0 to 10 minutes, now they
range from 1s to 9 minutes.
Fixes#412.
Using the Ring CRDT and Weave gossip, provides an interface
for the weave script to allocate IP addresses in `weave run`,
`weave start` and `weave expose`.
See docs/ipam.md for implementation details, and site/features.md
for user-visible changes.
...by moving the logic into the connection actor goroutine.
The heartbeater goroutine was doing a lot more than just heartbeating;
namely it also had tickers for triggering a ProtocolFetchAll and
initiating a fragmentation test. Furhermore, ensureHeartbeats also
spawned the forwarders.
So this was quite a mix of functionality, and, furthermore, most of it
related quite closely to the connection actor. So moving the
functionality into that simplifies the code.
In the process we also fix#294.