pf: Fix vnet purging
pf_purge_thread() breaks up the work of iterating all states (in pf_purge_expired_states()) and tracks progress in the idx variable. If multiple vnets exist this results in pf_purge_thread() only calling pf_purge_expired_states() for part of the states (the first part of the first vnet, second part of the second vnet and so on). Combined with the mark-and-sweep approach to cleaning up old rules (in V_pf_unlinked_rules) that resulted in pf freeing rules that were still referenced by states. This in turn caused panics when pf_state_expires() encounters that state and attempts to access the rule. We need to track the progress per vnet, not globally, so idx is moved into a per-vnet V_pf_purge_idx. PR: 219251 Sponsored by: Hackathon Essen 2017
This commit is contained in:
parent
14bcf3e185
commit
b7ae43552b
@ -132,6 +132,9 @@ VNET_DEFINE(int, pf_tcp_iss_off);
|
||||
VNET_DECLARE(int, pf_vnet_active);
|
||||
#define V_pf_vnet_active VNET(pf_vnet_active)
|
||||
|
||||
static VNET_DEFINE(uint32_t, pf_purge_idx);
|
||||
#define V_pf_purge_idx VNET(pf_purge_idx)
|
||||
|
||||
/*
|
||||
* Queue for pf_intr() sends.
|
||||
*/
|
||||
@ -1427,7 +1430,6 @@ void
|
||||
pf_purge_thread(void *unused __unused)
|
||||
{
|
||||
VNET_ITERATOR_DECL(vnet_iter);
|
||||
u_int idx = 0;
|
||||
|
||||
sx_xlock(&pf_end_lock);
|
||||
while (pf_end_threads == 0) {
|
||||
@ -1448,14 +1450,15 @@ pf_purge_thread(void *unused __unused)
|
||||
* Process 1/interval fraction of the state
|
||||
* table every run.
|
||||
*/
|
||||
idx = pf_purge_expired_states(idx, pf_hashmask /
|
||||
V_pf_purge_idx =
|
||||
pf_purge_expired_states(V_pf_purge_idx, pf_hashmask /
|
||||
(V_pf_default_rule.timeout[PFTM_INTERVAL] * 10));
|
||||
|
||||
/*
|
||||
* Purge other expired types every
|
||||
* PFTM_INTERVAL seconds.
|
||||
*/
|
||||
if (idx == 0) {
|
||||
if (V_pf_purge_idx == 0) {
|
||||
/*
|
||||
* Order is important:
|
||||
* - states and src nodes reference rules
|
||||
|
Loading…
x
Reference in New Issue
Block a user