-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple simultaneous mDNS requests #21952
Support multiple simultaneous mDNS requests #21952
Conversation
All checks passed. checkpatch (informational only, not a failure)
Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages. |
As mDNS requests set DNS id to 0, we cannot use it to match the DNS response packet. In order to allow this functionality, create a hash from query name and type, and use that together with DNS id to match request and response. Fixes zephyrproject-rtos#21914 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Moving the code around and enhancing debug prints. No changes in functionality. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
184cb4e
to
d9f0b6a
Compare
Updated according to comments. |
ping @tbursztyka, can you recheck |
cc @lbise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the logic behind introducing hash usage here. Hash is needed to speed up comparisons in large search domain. For example, if you have a million entries, you definitely need a hash. How many in-flight requests we'd have here? A dozen? Then, hash has collisions. In other words, if hashes are equal, it doesn't mean that subject datums are equal, that's the purpose of hash - to quickly vet out inequalities, but if hashes are equal, you need to compare the strings themselves. Finally, here crc16 is used as a hash function. Our implementation is optimized for code size, and is thus slow (works on bit level). If we'd have optimization for runtime, it would ship a precomputed value table, which would be mean code size dependency.
So, that's what I see here: using slow hash function -> using it to compare within just a handful of choices -> while doing so, not handling hash collisions. You could instead compare query host name directly, which would be simpler code without additional dependencies, and would be only faster for the realistic cases we have in hand.
I'm sorry if I missed something here.
You missed the problem domain that this PR is trying to solve. So the patch tries to solve the issue of matching sent mDNS request to received reply. Previously we used DNS id for matching the reply but it cannot be used for that purpose in mDNS as the id is 0. So this PR calculates a "hash" which is a crc16 value in this case. I used crc16 as I did not want to re-invent a hash function for this and there was simple API for calculating the crc value. The 16-bit value was used in order not to bloat the dns_resolve_context struct too much. The mDNS resolving is not done many times in a row so speed is not an issue here. Currently crc functions are optimized for code size, when / if we get hw accelerated crc functions there is no possible speed issue.
That was one alternative, it is just that it would bloat things considerably in dns_resolve_context struct. We store pointer to sent query, but it is just a normal string. When receiving the mDNS response, the response is in DNS string format and we cannot easily compare these. We would need to allocate space somewhere etc. which would mean bigger memory consumption. |
Yes, and that's done by matching reply against array of outstanding requests, i.e. searching within the array of outstanding requests, so where's my missing of the problem domain?
That's understood, but my comment is that CRC is known not to be an ideal hash function. If you go as far as bringing in a hash function at all, could add one of well-known both-simple-and-fast functions, e.g. "DJB hash": http://www.cse.yorku.ca/~oz/hash.html .
My point still holds: hash function values collide, so when you get hash match, next step always should be comparing literal (unhashed) content. I don't see that being done, get_slot_by_id() https://github.com/zephyrproject-rtos/zephyr/pull/21952/files#diff-31ea32ed325f4d523a7f77df9b060689R345 is just extended to check hash value (perhaps its name should be changed then?), and it just stops on this match returning the slot index, and as far as I can tell, this return value is used as-is later. So, you would need to analyze what may happen in the case of hash collision with your solution. I'd say, this opens up a security issue, when request is made to resolve e.g. "foo.com", but reply is used for e.g. "bar.com". This could be done on purpose (collisions for CRC aren't hard to find), and could be used to redirect traffic for one site to another site. |
Indeed they do. I verified that we do not collide with IPv4 and IPv6 mDNS and DNS queries that we send at the same time (can be checked by samples/net/dns_resolve sample app). This is the most important test here, it is very unlikely that the application would do a query at the same time that would collide with currently pending DNS query. Hash collision is of course possible but IMHO for all the practical purposes the current code is good enough. |
I'll test the changes |
Tested looks good. Thank you |
Fixes #21914