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
