The kernel processes vport deletion asynchronously, meaning that we can
sometimes fail to recreate vxlan vports on startup with an EADDRINUSE
error. We compensate by retrying a small number of times with a short
sleep on encountering this error, failing as before on a different error
or exhaustion of retries.
If overlay encryption is required between peers, the fast datapath
forwarder returns an error rather than aborting the process, allowing
the overlay switch to fall back gracefully to an encrypted sleeve
overlay connection.
Forward can return nil if the remote peer has HasShortID false. That
can happen if we learn about a 1.2 peer from a 1.1 peer and attempt to
connect to it.
This change just fixes the panic. HasShortID will never be set, so we'll
fall back to sleeve. But if that occurs, if can be fixed by a restart of
the affected routers.
This is mostly a matter of moving some files, changing package names,
changing some imports, and changing some type references.
We duplicate the odd constant & global var, and the intmac/macint
functions, since neither 'router' or 'mesh' nor, really,' common' are
a natural home for them.
...since the main connections only need to know about the former.
We make LocalConnection.Overlay (formerly '.forwarder') public since
the router needs access to it, and it shouldn't be doing that via a
private field.
Previously when a peer restarted, information about the new
incarnation (i.e. with a different UID) was not accepted by other
peers (and connections would be dropped) unless all knowledge of the
previous incarnation had been purged. This could result in a lot of
connection churn and hence connectivity disruption, and, in some
pathological cases, very slow convergence and hence acceptance of the
new incarnation into the network.
We now no longer drop connections when encountering different
incarnations of a peer. There are two situations when that can happen:
1) on connection establishment
we simply proceed
2) on receipt of gossip
to ensure convergence we
a) treat the UID as an additional discriminator when deciding whether
we should update our information about a peer with that which was
gossiped. Specifically, we update the information we hold when a) the
gossiped version is greater, or b) is the same and the UID is
greater.
b) include the UID in the information we update
c) move our own version number beyond any we receive for ourselves, if
the received UID differs from ours.
With (a) we establishes a total order of peer information across
several incarnations of the same peer. i.e. we consider information to
be fresher if it has a higher version, or the same version and higher
UID. This may seem somewhat counter intutive, since it will generally
treat information about new incarnations as older than old
incarnations, since incarnations always start life with version 1. But
to do better we'd need to establish a total order of incarnations that
matches their temporal occurrence. Which requires some sort of durable
state.
So instead we have (c). Through that we learn the highest version
number of any old incarnation of ourselves that other peers still
hold, and then make sure that our version is greater than
that. Essentially we continue where the old incarnations left
off. It's as if instead of restarting we had simply changed UIDs. And
due to (a) and (b) the information about the new incarnation of
ourselves, now with a higher version, will supersede that of the old
incarnations.
Fixes#1554.
Previously it was set by the script only in fastdp mode; and in the
router's main.go otherwise. Yet every interaction of the script with
weave assumes the port is the script's HTTP_PORT=6784. By always
starting the router with options to listen on that port we ensure that
the router is in fact listening where the script expects it to.
In doing this get rid of router.HTTPPort. We do need to hard-code the
port in the proxy instead, but relying on router.HTTPPort was flawed
anyway, for the above reasons.
It's possible to build that kernel with openvswitch, and vxlan, but
without the vport_vxlan module that glues them together. And at
least one distro has actually done this.
If the local peer's short ID was updated, we broadcastPeerUpdate at
the end (in unlockAndNotify), so there is no need to include the local
peer in the current update.
Also, reading peers.ourself.Version is bad here - we don't take a lock
and it's written by other goroutines. Doesn't actually break anything
though since it's a uint64 and hence atomic.
When we get a forwarded packet, we put its source MAC into the MAC cache,
overriding any existing entry. But we could have a flow which says
to forward packets destined to that MAC based on the old entry. Such
a flow could be prolonged indefinitely by attempts to send to the MAC.
This is obviously bad, so do InvalidateRoutes in such cases.