QEMU Slirp Network Backend¶
Slirp
APIs in libslirp.h
slirp_input()
: slirp 透過硬體來 send packetslirp_output()
: 把 packet 送回 guest, 透過 peer 的receive()
function (qemu_send_packet()
)
struct Slirp
- void* opaque = (SlirpState*) s; // net_slirp_init()
- libslirp.h
- functions
- slirp_init()
- slirp_input()
- slirp_pollfds_poll(), slirp_pollfds_fill()
- slirp_add_hostfwd(): socreate() Slirp's socket
- library user should provide some functions (like callback?)
- slirp_output(): [net/slirp.c] qemu_send_packet(SlirpState->nc)
SlirpState
wraps Slirp
API, and provide NetClientInfo
interface for QEMU Network architecture.
struct SlirpState
- Slirp* slirp: slirp wrapper in qemu net framework
- slirp_hostfwd() => Slirp::slirp_add_hostfwd()
- slirp_guestfwd() => Slirp::slirp_add_guestfwd()
- slirp_smb() => Slirp::slirp_add_exec()
- NetClientState nc: interface NetClientState
- nc = qemu_new_net_client(&net_slirp_info, ... )
- nc->incoming_queue->deliver = qemu_deliver_packet_iov() [1.]
- nc->info = net_slirp_info; [2.]
- nc->peer = peer; // external parameter [3.]
- nc source
1. qemu_new_net_client() default
2. struct NetClientInfo net_slirp_info; (slirp provide NetClientInfo interface)
- .receive = net_slirp_receive; net_slirp_receive() calls Slirp::slirp_input();
- .cleanup = net_slirp_cleanup; net_slirp_cleanup() calls SlirpState::slirp_smb_cleanup();
3. from net_slirp_init() function parameters: peer is customizable by function caller.
socket address mapping(NAPT) and host socket API abstraction
struct socket (Slirp socket)
- struct socket *so_next, *so_prev: linked list of sockets
- int s: actual socket fd number
- Slirp* slirp: managing Slirp instance
- struct sbuf so_rcv, so_snd: Recv/Send buffer
- socreate(Slirp* slirp):
- so->slirp = slirp
- so->s = socket() syscall
- callers of send() and recv() syscall
- soread(), sowrite()
- sosendoob(), sorecvoob()
- sosendto(), sorecvfrom()
- slirp_send(struct socket *so, const void *buf, size_t len, int flags): send(so->s, buf, len, flags);
slirp_input()¶
slirp_input()
use system call to send packet to remote OS.
for loopback network, slirp_input() may send packet back to peer network.
at least 4 path of slirp_input()
:
1. __libc_send()
=> slirp_input() => slirp_send() => __libc_send()
2. sosendto(): call sendto() syscall, only udp.c & udp6.c use it.
=> slirp_input() => sosendto() => sendto() # syscall
3. slirp_output()
=> slirp_input() => tcp_input() => tcp_output() => slirp_output()
=> qemu_send_packet() => e1000_receive_iov()
4. slirp_output() by arp?
=> slirp_input() => arp_input() => slirp_output()
slirp_send() callers
sosendoob()
sowrite()
sbappend()
slirp/socket.c
andslirp/sbuf.c
Misc¶
struct: NICState, NICInfo, NICPeers
caller of
slirp_output()
slirp_pollfds_poll() => tcp_output() => slirp_output()
ra_timer_handler() => ndp_send_ra() => slirp_output()