diff --git a/gossipd/routing.c b/gossipd/routing.c index 8ad62c8cf..8fde308ee 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -226,6 +227,7 @@ get_or_make_connection(struct routing_state *rstate, nc->dst = to; nc->channel_announcement = NULL; nc->channel_update = NULL; + nc->unroutable_until = 0; /* Hook it into in/out arrays. */ i = tal_count(to->in); @@ -342,9 +344,9 @@ static void bfg_one_edge(struct node *node, size_t edgenum, double riskfactor) } /* Determine if the given node_connection is routable */ -static bool nc_is_routable(const struct node_connection *nc) +static bool nc_is_routable(const struct node_connection *nc, time_t now) { - return nc->active; + return nc->active && nc->unroutable_until < now; } /* riskfactor is already scaled to per-block amount */ @@ -357,6 +359,10 @@ find_route(const tal_t *ctx, struct routing_state *rstate, struct node_map_iter it; struct node_connection *first_conn; int runs, i, best; + /* Call time_now() once at the start, so that our tight loop + * does not keep calling into operating system for the + * current time */ + time_t now = time_now().ts.tv_sec; /* Note: we map backwards, since we know the amount of satoshi we want * at the end, and need to derive how much we need to send. */ @@ -403,7 +409,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate, type_to_string(trc, struct pubkey, &n->id), i, num_edges); - if (!nc_is_routable(n->in[i])) { + if (!nc_is_routable(n->in[i], now)) { SUPERVERBOSE("...unroutable"); continue; } @@ -830,6 +836,7 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update) c->base_fee = fee_base_msat; c->proportional_fee = fee_proportional_millionths; c->active = (flags & ROUTING_FLAGS_DISABLED) == 0; + c->unroutable_until = 0; status_trace("Channel %s(%d) was updated.", type_to_string(trc, struct short_channel_id, &short_channel_id), @@ -1047,7 +1054,8 @@ get_out_node_connection_of(struct routing_state *rstate, */ static void routing_failure_on_nc(struct routing_state *rstate, enum onion_type failcode, - struct node_connection *nc) + struct node_connection *nc, + time_t now) { /* BOLT #4: * @@ -1055,7 +1063,8 @@ static void routing_failure_on_nc(struct routing_state *rstate, * - SHOULD restore the channels as it receives new `channel_update`s. */ if (!(failcode & PERM)) - nc->active = false; + /* Prevent it for 20 seconds. */ + nc->unroutable_until = now + 20; else delete_connection(rstate, nc); } @@ -1071,6 +1080,7 @@ void routing_failure(struct routing_state *rstate, struct node_connection *nc; int i; enum wire_type t; + time_t now = time_now().ts.tv_sec; status_trace("Received routing failure 0x%04x (%s), " "erring node %s, " @@ -1099,13 +1109,13 @@ void routing_failure(struct routing_state *rstate, */ if (failcode & NODE) { for (i = 0; i < tal_count(node->in); ++i) - routing_failure_on_nc(rstate, failcode, node->in[i]); + routing_failure_on_nc(rstate, failcode, node->in[i], now); for (i = 0; i < tal_count(node->out); ++i) - routing_failure_on_nc(rstate, failcode, node->out[i]); + routing_failure_on_nc(rstate, failcode, node->out[i], now); } else { nc = get_out_node_connection_of(rstate, node, scid); if (nc) - routing_failure_on_nc(rstate, failcode, nc); + routing_failure_on_nc(rstate, failcode, nc, now); else status_trace("UNUSUAL routing_failure: " "Channel %s not an out channel " diff --git a/gossipd/routing.h b/gossipd/routing.h index 68d590bfa..af8fe16cf 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -38,6 +38,10 @@ struct node_connection { /* Cached `channel_announcement` and `channel_update` we might forward to new peers*/ u8 *channel_announcement; u8 *channel_update; + + /* If greater than current time, this connection should not + * be used for routing. */ + time_t unroutable_until; }; struct node {