Browse Source

gossipd: don't request channel_updates if we're being spammed.

It's simple: if we wouldn't accept the timestamp we see, don't put
the channel in the stale_scid_map.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
committed by neil saitug
parent
commit
877d1eaab3
  1. 27
      gossipd/routing.c
  2. 5
      gossipd/routing.h
  3. 14
      gossipd/seeker.c
  4. 5
      gossipd/test/run-next_block_range.c

27
gossipd/routing.c

@ -45,19 +45,24 @@ struct pending_node_announce {
#define TOKENS_PER_MSG 24 #define TOKENS_PER_MSG 24
#define TOKEN_MAX (24 * 4) #define TOKEN_MAX (24 * 4)
static bool ratelimit(const struct routing_state *rstate, static u8 update_tokens(const struct routing_state *rstate,
u8 *tokens, u32 prev_timestamp, u32 new_timestamp) u8 tokens, u32 prev_timestamp, u32 new_timestamp)
{ {
u64 num_tokens; u64 num_tokens = tokens;
assert(new_timestamp >= prev_timestamp); assert(new_timestamp >= prev_timestamp);
/* First, top up tokens, avoiding overflow. */ num_tokens += ((new_timestamp - prev_timestamp)
num_tokens = *tokens + ((new_timestamp - prev_timestamp) / GOSSIP_TOKEN_TIME(rstate->dev_fast_gossip));
/ GOSSIP_TOKEN_TIME(rstate->dev_fast_gossip));
if (num_tokens > TOKEN_MAX) if (num_tokens > TOKEN_MAX)
num_tokens = TOKEN_MAX; num_tokens = TOKEN_MAX;
*tokens = num_tokens; return num_tokens;
}
static bool ratelimit(const struct routing_state *rstate,
u8 *tokens, u32 prev_timestamp, u32 new_timestamp)
{
*tokens = update_tokens(rstate, *tokens, prev_timestamp, new_timestamp);
/* Now, if we can afford it, pass this message. */ /* Now, if we can afford it, pass this message. */
if (*tokens >= TOKENS_PER_MSG) { if (*tokens >= TOKENS_PER_MSG) {
@ -2191,6 +2196,14 @@ bool routing_add_channel_update(struct routing_state *rstate,
return true; return true;
} }
bool would_ratelimit_cupdate(struct routing_state *rstate,
const struct half_chan *hc,
u32 timestamp)
{
return update_tokens(rstate, hc->tokens, hc->bcast.timestamp, timestamp)
>= TOKENS_PER_MSG;
}
static const struct node_id *get_channel_owner(struct routing_state *rstate, static const struct node_id *get_channel_owner(struct routing_state *rstate,
const struct short_channel_id *scid, const struct short_channel_id *scid,
int direction) int direction)

5
gossipd/routing.h

@ -483,6 +483,11 @@ static inline struct local_chan *is_local_chan(struct routing_state *rstate,
return local_chan_map_get(&rstate->local_chan_map, &chan->scid); return local_chan_map_get(&rstate->local_chan_map, &chan->scid);
} }
/* Would we ratelimit a channel_update with this timestamp? */
bool would_ratelimit_cupdate(struct routing_state *rstate,
const struct half_chan *hc,
u32 timestamp);
/* Because we can have millions of channels, and we only want a local_disable /* Because we can have millions of channels, and we only want a local_disable
* flag on ones connected to us, we keep a separate hashtable for that flag. * flag on ones connected to us, we keep a separate hashtable for that flag.
*/ */

14
gossipd/seeker.c

@ -528,15 +528,19 @@ static void peer_gossip_probe_nannounces(struct seeker *seeker)
} }
/* They have update with this timestamp: do we want it? */ /* They have update with this timestamp: do we want it? */
static bool want_update(u32 timestamp, const struct half_chan *hc) static bool want_update(struct seeker *seeker,
u32 timestamp, const struct half_chan *hc)
{ {
if (!is_halfchan_defined(hc)) if (!is_halfchan_defined(hc))
return timestamp != 0; return timestamp != 0;
return timestamp > hc->bcast.timestamp; if (timestamp <= hc->bcast.timestamp)
return false;
return !would_ratelimit_cupdate(seeker->daemon->rstate, hc, timestamp);
} }
/* They gave us timestamps. Do we need updated versions? */ /* They gave us timestamps. Do we want updated versions? */
static void check_timestamps(struct seeker *seeker, static void check_timestamps(struct seeker *seeker,
struct chan *c, struct chan *c,
const struct channel_update_timestamps *ts) const struct channel_update_timestamps *ts)
@ -552,9 +556,9 @@ static void check_timestamps(struct seeker *seeker,
* for `node_id_2`, or 0 if there was no `channel_update` from that * for `node_id_2`, or 0 if there was no `channel_update` from that
* node. * node.
*/ */
if (want_update(ts->timestamp_node_id_1, &c->half[0])) if (want_update(seeker, ts->timestamp_node_id_1, &c->half[0]))
query_flag |= SCID_QF_UPDATE1; query_flag |= SCID_QF_UPDATE1;
if (want_update(ts->timestamp_node_id_2, &c->half[1])) if (want_update(seeker, ts->timestamp_node_id_2, &c->half[1]))
query_flag |= SCID_QF_UPDATE2; query_flag |= SCID_QF_UPDATE2;
if (!query_flag) if (!query_flag)

5
gossipd/test/run-next_block_range.c

@ -52,6 +52,11 @@ void status_failed(enum status_failreason code UNNEEDED,
void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "status_fmt called!\n"); abort(); } { fprintf(stderr, "status_fmt called!\n"); abort(); }
/* Generated stub for would_ratelimit_cupdate */
bool would_ratelimit_cupdate(struct routing_state *rstate UNNEEDED,
const struct half_chan *hc UNNEEDED,
u32 timestamp UNNEEDED)
{ fprintf(stderr, "would_ratelimit_cupdate called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */ /* AUTOGENERATED MOCKS END */
static void test_block_range(struct seeker *seeker, static void test_block_range(struct seeker *seeker,

Loading…
Cancel
Save