diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-07-03 19:21:42 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-07-03 19:21:59 +0200 |
commit | cbfdf6ed057b993d7e107b4c39b8a5b81c081eee (patch) | |
tree | 0c6255bb81f037ceff0dfa9409a5829069ea24e1 /proto | |
parent | 822a7ee6d5cd9bf38548026e0dd52fbc4634030d (diff) |
Nest: Fix race condition during reconfiguration
If export filter is changed during reconfiguration and a route disappears
between reconfiguration and refeed (e.g., if the route is a static route
also removed during the reconfiguration), the route is not withdrawn.
The patch fixes that by adding tx reconfiguration timestamp.
Diffstat (limited to 'proto')
-rw-r--r-- | proto/pipe/pipe.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 6ef80322..5d0e3c76 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -230,12 +230,18 @@ pipe_reconfigure(struct proto *P, struct proto_config *new) if ((oc->peer->table != nc->peer->table) || (oc->mode != nc->mode)) return 0; + int import_changed = ! filter_same(new->in_filter, old->in_filter); + int export_changed = ! filter_same(new->out_filter, old->out_filter); + /* Update output filters in ahooks */ if (P->main_ahook) { P->main_ahook->out_filter = new->out_filter; P->main_ahook->in_limit = new->in_limit; proto_verify_limits(P->main_ahook); + + if (export_changed) + P->main_ahook->last_out_filter_change = now; } if (p->peer_ahook) @@ -243,14 +249,15 @@ pipe_reconfigure(struct proto *P, struct proto_config *new) p->peer_ahook->out_filter = new->in_filter; p->peer_ahook->in_limit = new->out_limit; proto_verify_limits(p->peer_ahook); + + if (import_changed) + p->peer_ahook->last_out_filter_change = now; } if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT)) return 1; - if ((new->preference != old->preference) - || ! filter_same(new->in_filter, old->in_filter) - || ! filter_same(new->out_filter, old->out_filter)) + if (import_changed || export_changed || (new->preference != old->preference)) proto_request_feeding(P); return 1; |