Hi Florian,

thanks for the feedback! Just a note that I didn't forget - I caught a
flu or something, but now I'm getting back on track and will get to
these shortly.

Cheers,
Marek

--
Marek Vavruša                      Knot DNS
CZ.NIC Labs          http://www.knot-dns.cz
-------------------------------------------
Americká 23, 120 00 Praha 2, Czech Republic
WWW: http://labs.nic.cz   http://www.nic.cz

On 6 November 2015 at 16:02, Florian Maury <[email protected]> wrote:
> Hi everyone,
>
> While working on my Knot-Resolver (kr) module, I came to think that the
> current YIELD mechanism for layers will not work properly, if multiple
> YIELD-enabled modules are loaded simultaneously.
>
> My understanding of how the current YIELD system works is as follows.
> A layer receives the current state through ((knot_layer_t*) ctx)->state.
> The current state can be modified by previous layers returned value.
> When a layer returns a YIELD state, the chain of responsability,
> maintained by the lib/resolve.c:ITERATE_LAYERS macro is broken (break;)
> and the resolution plan is evaluated once more to handle the tail
> element of the rplan.
>
> Once the rplan popped up all rplan_pushed queries, then the query that
> yielded is once more the last element of the rplan stack. This element
> is then evaluated, calling once more all layers, starting with the
> first layer. This time, the state that is provided to the layers is
> YIELD, except if a layer returns another value instead of returning the
> state as is.
> A layer could behave differently, based on whether it receives a YIELD
> state or not as "input state". This is, in fact, what is provided as
> example in the documentation:
>
>>>>
> consume = function (state, req, answer)
>         answer = kres.pkt_t(answer)
>         if state == kres.YIELD then
>                 print('continuing yielded layer')
>                 return kres.DONE
>         else
>                 if answer:qtype() == kres.type.NS then
>                         req = kres.request_t(req)
>                         local qry = req:push(answer:qname(),
> kres.type.SOA, kres.class.IN)
>                         qry.flags = kres.query.AWAIT_CUT
>                         print('planned SOA query, yielding')
>                         return kres.YIELD
>                 end
>                 return state
>         end
> end
> <<<
>
> The issue, I think, is that a module has no way of knowing whether it is
> the one that yielded or not.
> Let's say I have three module, A, B, and C. B and C can yield, and A
> only returns YIELD, when it receives YIELD as input state.
> On the first evaluation, A and B returns DONE. C yields. Then on the
> second evaluation, A returns YIELD, because it does not handle this
> state and only passes it along. B receives the YIELD from A. B, as said
> above, may yield in some cases. B will therefore handle the YIELD, and
> do his "YIELD" actions, ignoring the fact that the module that actually
> yielded was C.
>
> I suppose B and C could define flags to be capable of remembering
> whether they yielded on this query or not. Unfortunately, there is
> currently no framework to ensure uniqueness of these flags.
>
> Sadly, this email does not come up with a proposed solution. I'm only
> sharing a thought about what I think could be an issue.
>
> What is your take on this? Have I missed something or misunderstood how
> the yield state works?
>
> Thank you.
>
> Cheers,
> Florian
>
> _______________________________________________
> knot-dns-users mailing list
> [email protected]
> https://lists.nic.cz/cgi-bin/mailman/listinfo/knot-dns-users
_______________________________________________
knot-dns-users mailing list
[email protected]
https://lists.nic.cz/cgi-bin/mailman/listinfo/knot-dns-users

Reply via email to