netfilter: flowtable: Add pending bit for offload work

Gc step can queue offloaded flow del work or stats work.
Those work items can race each other and a flow could be freed
before the stats work is executed and querying it.
To avoid that, add a pending bit that if a work exists for a flow
don't queue another work for it.
This will also avoid adding multiple stats works in case stats work
didn't complete but gc step started again.

Signed-off-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Paul Blakey 2020-05-06 14:24:39 +03:00 коммит произвёл Pablo Neira Ayuso
Родитель 2c407aca64
Коммит 2c8897953f
2 изменённых файлов: 9 добавлений и 2 удалений

Просмотреть файл

@ -127,6 +127,7 @@ enum nf_flow_flags {
NF_FLOW_HW_DYING,
NF_FLOW_HW_DEAD,
NF_FLOW_HW_REFRESH,
NF_FLOW_HW_PENDING,
};
enum flow_offload_type {

Просмотреть файл

@ -817,6 +817,7 @@ static void flow_offload_work_handler(struct work_struct *work)
WARN_ON_ONCE(1);
}
clear_bit(NF_FLOW_HW_PENDING, &offload->flow->flags);
kfree(offload);
}
@ -831,10 +832,15 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable,
{
struct flow_offload_work *offload;
offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC);
if (!offload)
if (test_and_set_bit(NF_FLOW_HW_PENDING, &flow->flags))
return NULL;
offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC);
if (!offload) {
clear_bit(NF_FLOW_HW_PENDING, &flow->flags);
return NULL;
}
offload->cmd = cmd;
offload->flow = flow;
offload->priority = flowtable->priority;