• Florian Westphal's avatar
    netfilter: nf_tables: remove synchronize_rcu in commit phase · 0cbc06b3
    Florian Westphal authored
    synchronize_rcu() is expensive.
    
    The commit phase currently enforces an unconditional
    synchronize_rcu() after incrementing the generation counter.
    
    This is to make sure that a packet always sees a consistent chain, either
    nft_do_chain is still using old generation (it will skip the newly added
    rules), or the new one (it will skip old ones that might still be linked
    into the list).
    
    We could just remove the synchronize_rcu(), it would not cause a crash but
    it could cause us to evaluate a rule that was removed and new rule for the
    same packet, instead of either-or.
    
    To resolve this, add rule pointer array holding two generations, the
    current one and the future generation.
    
    In commit phase, allocate the rule blob and populate it with the rules that
    will be active in the new generation.
    
    Then, make this rule blob public, replacing the old generation pointer.
    
    Then the generation counter can be incremented.
    
    nft_do_chain() will either continue to use the current generation
    (in case loop was invoked right before increment), or the new one.
    Suggested-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
    Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    0cbc06b3
nf_tables_api.c 167 KB