CFR projects/pf: vnet awareness for pf_overloadqueue

Mikolaj Golub trociny at FreeBSD.org
Mon Mar 31 19:41:19 UTC 2014


On Sun, Mar 30, 2014 at 10:27:06AM +0200, Martin Matuska wrote:
> Hi,
> 
> with the pf_mtag_z patch applied, the second patch that fixes panics I
> experience is the overload queue patch.
> 
> I have looked into solving this via context (adding a "struct vnet"
> member to pf_overload_entry). This leaves unsolved problems - first, we
> have now vnet information on per-entry instead of per-queue.
> 
> There are two places in pf_overload_task() where we are not processing
> an entry but need vnet information:
> 
> 1. V_pf_idhash[i] in pf_overload_task():
> 
>         for (int i = 0; i <= pf_hashmask; i++) {
>                 struct pf_idhash *ih = &V_pf_idhash[i];
>                 struct pf_state_key *sk;
>                 struct pf_state *s;
> 
>                 PF_HASHROW_LOCK(ih);
>                 LIST_FOREACH(s, &ih->states, entry) {
> 
> 2. end of pf_overload_task() but that is only the debug tunable
> V_pf_status_debug:
> 
>         if (V_pf_status.debug >= PF_DEBUG_MISC)
>                 printf("%s: %u states killed", __func__, killed);
> 
> On the other hand, if we want to keep per-vnet overloadqueues than it
> makes sense to store vnet information on queue level.
> If we pack vnet information into each entry and the overloadqueue has
> global locks anyway, why not keeping a single global queue with entries
> from different vnets?
> 
> At the current state the code causes panics if pf_overload_task() is
> fired because vnet context is missing. It needs to be fixed in any of
> the ways. A patch for adding per-queue vnet information is attached.

Martin, I think you missed my point in the message to src at . You don't
need to embed vnet into pf_overloadqueue. What you need is a way to
access it in a right vnet context, i.e. by passing vnet as an argument
to pf_overload_task:

 pf_vnet_initialize():

-       TASK_INIT(&V_pf_overloadtask, 0, pf_overload_task, &V_pf_overloadqueue);
+       TASK_INIT(&V_pf_overloadtask, 0, pf_overload_task, curvnet);

 pf_overload_task(void *c, int pending):
 {
+       struct vnet *vnet;
        struct pf_overload_head queue;
        struct pfr_addr p;
        struct pf_overload_entry *pfoe, *pfoe1;
        uint32_t killed = 0;
 
+       vnet = (vnet *)c;
+       CURVNET_SET(vnet);
        PF_OVERLOADQ_LOCK();
-       queue = *(struct pf_overload_head *)c;
-       SLIST_INIT((struct pf_overload_head *)c);
+       queue = V_pf_overloadqueue;
+       SLIST_INIT(V_pf_overloadqueue);
        PF_OVERLOADQ_UNLOCK();

-- 
Mikolaj Golub


More information about the freebsd-pf mailing list