[PATCH 05/31] site: transport peers: Delete or demote unsuitable peers addresses
Ian Jackson
ijackson at chiark.greenend.org.uk
Sat Sep 20 01:32:00 BST 2014
If comm signals that the address is unuseable (ie we have no IPv4 or
IPv6 interface or routing), delete the address. Or, if we are mobile,
demote it to the end of the list (since we might gain appropriate
routing in the future).
Signed-off-by: Ian Jackson <ijackson at chiark.greenend.org.uk>
---
site.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/site.c b/site.c
index 1572a29..aadb558 100644
--- a/site.c
+++ b/site.c
@@ -2209,15 +2209,62 @@ static void transport_resolve_complete_tardy(struct site *st,
transport_record_peer(st,&st->peers,ca_use,"resolved tardily");
}
+static void transport_peers__copy_by_mask(transport_peer *out, int *nout_io,
+ unsigned mask,
+ const transport_peers *in) {
+ /* out and in->peers may be the same region, or nonoverlapping */
+ int slot;
+ for (slot=0; slot<in->npeers; slot++) {
+ if (!(mask & (1U << slot)))
+ continue;
+ if (!(out==in->peers && slot==*nout_io))
+ memcpy(&out[*nout_io], &in[slot], sizeof(out[0]));
+ (*nout_io)++;
+ }
+}
+
void transport_xmit(struct site *st, transport_peers *peers,
struct buffer_if *buf, bool_t candebug) {
int slot;
transport_peers_expire(st, peers);
+ unsigned failed=0; /* bitmask */
+ assert(MAX_MOBILE_PEERS_MAX < sizeof(unsigned)*CHAR_BIT);
+
+ int nfailed=0;
for (slot=0; slot<peers->npeers; slot++) {
transport_peer *peer=&peers->peers[slot];
if (candebug)
dump_packet(st, buf, &peer->addr, False);
- peer->addr.comm->sendmsg(peer->addr.comm->st, buf, &peer->addr);
+ bool_t ok =
+ peer->addr.comm->sendmsg(peer->addr.comm->st, buf, &peer->addr);
+ if (!ok) {
+ failed |= 1U << slot;
+ nfailed++;
+ }
+ if (ok && !st->peer_mobile)
+ break;
+ }
+ /* Now we need to demote/delete failing addrs: if we are mobile we
+ * merely demote them; otherwise we delete them. */
+ if (st->local_mobile) {
+ unsigned expected = ((1U << nfailed)-1) << peers->npeers;
+ /* `expected' has all the failures at the end already */
+ if (failed != expected) {
+ int fslot=0;
+ transport_peer failedpeers[nfailed];
+ transport_peers__copy_by_mask(failedpeers, &fslot, failed,peers);
+ assert(fslot == nfailed);
+ int wslot=0;
+ transport_peers__copy_by_mask(peers->peers,&wslot,~failed,peers);
+ assert(wslot+nfailed == peers->npeers);
+ memcpy(peers->peers+wslot,failedpeers,sizeof(failedpeers));
+ }
+ } else {
+ if (failed && peers->npeers > 1) {
+ int wslot=0;
+ transport_peers__copy_by_mask(peers->peers,&wslot,~failed,peers);
+ peers->npeers=wslot;
+ }
}
}
--
1.7.10.4
More information about the sgo-software-discuss
mailing list