Closed espoal closed 3 months ago
Hi @espoal,
While I appreciate the enthusiasm behind the suggestion to implement a
getaddrinfo()
opcode in io_uring, I must say it's not only technically
nonsensical but also fundamentally at odds with the purpose and design
of io_uring.
Consider taking a look at the getaddrinfo()
source code:
https://elixir.bootlin.com/glibc/glibc-2.39.9000/source/nss/getaddrinfo.c
It involves a series of complex operations such as socket creation, network communication, reading system files, etc., all of which are firmly within the domain of userspace.
Furthermore, the functionality of getaddrinfo()
is deeply intertwined with
system configuration files like /etc/hosts
, /etc/resolv.conf
,
/etc/nsswitch.conf
, etc. These files dictate the behavior of name resolution,
including the order in which different sources (like DNS, hosts file, etc.) are
consulted. Trying to shoehorn this functionality into the kernel-space io_uring
would be impractical and disregard the established conventions of system
configuration.
While it's always commendable to think outside the box, this particular request seems to miss the mark by a wide margin.
You should consider implementing io_uring in your own getaddrinfo()
, not the
other way around.
The relevant library for async DNS resolution is c-ares: https://github.com/c-ares/c-ares (it's not using io_uring, though).
Hey @ammarfaizi2 I agree with you on the pickiness of using getaddrinfo
, and I was thinking about the same objections you just raised, BUT:
1) I'm implementing a thread per core architecture, without a traditional reactor
or executor
, simply having a loop and waiting for io_uring events. Performance has been AMAZING, except for the DNS and crypto parts.
2) With the raise of protocols like QUIC these will become a more and more common requirements
3) I see other big projects, like node.js
, have my same issue and are migrating to liburing
(pending libuv
implementation). In node they spawn a thread for DNS and one for crypto
So resolving a DNS request will become a common requirements of io_uring
based projects and I feel we should document somehow best approaches, even if it's not an opcode. I will spend some time to think about this and will comment on this issue, looking for further comments. Using something like c-ares
might seems like a straightforward approach but it will have severe performance penalties due to the lack of an executor
and reactor
, very much like spawning a thread and waiting for a response in a blocking fashion.
On the other hand, wdyt of adding crypto opcodes, for example for gathering entropy?
Talked about this many years ago https://github.com/axboe/liburing/issues/234 even though getaddrinfo
has a lot of function / parser within it, the fact that DNS lookup part is in blocking state is still true.
For getaddrinfo, what @ammarfaizi2 says is spot on - this isn't really something io_uring can help you with, as it's not something that's done in the kernel to begin with.
For entropy, you can most certainly use io_uring to read eg /dev/random or /dev/urandom, for example.
Thanks @axboe , I was actually playing with /dev/random
atm. How would you deal with the time
syscall? It's needed for TLS and QUIC
Can you use clock_gettime()
? That's generally a VDSO and hence won't even incur a syscall.
It seems like I can... thanks @axboe I really appreciate your help!
I will update this ticket with some comments on some technical corners I found, and eventually with a link to my example code.
For now this ticket can be closed.
With all that said, it'd be really great if someone implements a simple getaddrinfo() with io_uring. Perhaps, standalone at first with a separate ring, which could then evolve into a helper library to be used in frameworks and that would share a ring with them.
@isilence I'm implementing it as a state machine in Rust. I have a demo, I need to find a suitable library for parsing DNS responses, and I need to implement RustTLS on top of io_uring
first.
I agree with you that even for a simple demo like mine there are a lot of consideration to take, I will make sure to document everything and ask the community for a review.
With all that said, it'd be really great if someone implements a simple getaddrinfo() with io_uring. Perhaps, standalone at first with a separate ring, which could then evolve into a helper library to be used in frameworks and that would share a ring with them.
Yeah for sure. There's no reason why liburing can't expand from basically just being an easier to use wrapper around io_uring to providing actual functionality as well.
ok so @ammarfaizi2 objection was against adding stuff like this to io_uring
the kernel module, not to liburing
the library used to interface with it. Good to know.
io_uring
is designed also for high performance networking applications, and DNS and crypto are fundamental part of networking applications, especially modern ones, hence I think we should add some opcodes to consume DNS and crypto sources asynchronously.Lately I've been playing with a QUIC implementation on top of
io_uring
, and currently there are only two parts of my code that are blocking:I see entropy gathering can be easily solved by multiple syscalls (
getrandom
,getentropy
,geturandom
, ...), while for DNS we could use something likegetaddrinfo
.Update:
To fully support modern protocol like QUIC we would also need an opcode for the
time
syscall@axboe wdyt?