diff options
author | Eric Garver <eric@garver.life> | 2019-05-22 21:44:04 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2019-05-24 21:14:30 +0200 |
commit | eeda228c2d1719f5b6276b40ad14a5b3c3e88536 (patch) | |
tree | 1f4db86616df6eeb13ad92c94447766dbea73f45 /src/rule.c | |
parent | 7e71e06b7b724006c84e789aa7bcb7faadd21c48 (diff) |
src: update cache if cmd is more specific
If we've done a partial fetch of the cache and the genid is the same the
cache update will be skipped without fetching the needed items. This
change flushes the cache if the new request is more specific than the
current cache - forcing a cache update which includes the needed items.
Introduces a simple scoring system which reflects how
cache_init_objects() looks at the current command to decide if it is
finished already or not. Then use that in cache_needs_more(): If current
command's score is higher than old command's, cache needs an update.
Fixes: 816d8c7659c1 ("Support 'add/insert rule index <IDX>'")
Signed-off-by: Eric Garver <eric@garver.life>
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/rule.c')
-rw-r--r-- | src/rule.c | 20 |
1 files changed, 20 insertions, 0 deletions
@@ -220,6 +220,23 @@ static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd) return 0; } +/* Return a "score" of how complete local cache will be if + * cache_init_objects() ran for given cmd. Higher value + * means more complete. */ +static int cache_completeness(enum cmd_ops cmd) +{ + if (cmd == CMD_LIST) + return 3; + if (cmd != CMD_RESET) + return 2; + return 1; +} + +static bool cache_needs_more(enum cmd_ops old_cmd, enum cmd_ops cmd) +{ + return cache_completeness(old_cmd) < cache_completeness(cmd); +} + int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) { uint16_t genid; @@ -235,6 +252,8 @@ int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) replay: ctx.seqnum = cache->seqnum++; genid = mnl_genid_get(&ctx); + if (cache->genid && cache_needs_more(cache->cmd, cmd)) + cache_release(cache); if (genid && genid == cache->genid) return 0; if (cache->genid) @@ -250,6 +269,7 @@ replay: return -1; } cache->genid = genid; + cache->cmd = cmd; return 0; } |