Data Flow
SLIRP User Networking
When the config specifies driver: "user", TinyEMU uses the bundled SLIRP library. SLIRP performs NAT-like translation: the guest sees a virtual network, and outbound traffic is translated to the host's IP stack. No root privileges or tap interface are required.
EthernetDevice *slirp_open(void)
{
/* initialize SLIRP state */
...
eth->write_packet = slirp_write_packet;
eth->select_fill = slirp_select_fill1;
eth->select_poll = slirp_select_poll1;
return eth;
}TUN/TAP Backend
For bridged networking, TinyEMU supports a TUN/TAP backend. The netinit.sh script sets up the tap interface and NAT rules. The emulator opens /dev/net/tun and forwards raw Ethernet frames.
EthernetDevice *tun_open(const char *ifname)
{
int fd = open("/dev/net/tun", O_RDWR);
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
ioctl(fd, TUNSETIFF, &ifr);
/* wrap fd in EthernetDevice */
}HTTP Block Device
block_device_init_http() creates a block device backed by remote HTTP resources. The disk image is split into small files (via splitimg). The driver caches blocks locally and prefetches adjacent blocks to improve performance.
BlockDevice *block_device_init_http(const char *url,
int max_cache_size_kb,
void (*start_cb)(void *opaque),
void *start_opaque)
{
BlockDeviceHTTP *s = mallocz(sizeof(*s));
s->max_cache_size_kb = max_cache_size_kb;
strncpy(s->url, url, sizeof(s->url));
s->bs->get_sector_count = bf_http_get_sector_count;
s->bs->read_async = bf_http_read_async;
s->bs->write_async = bf_http_write_async;
return s->bs;
}HTTP 9P Filesystem
fs_net.c implements a 9P filesystem over HTTP. It downloads files on demand, caches inodes, and supports preloading via a .preload file list. This allows running a full Linux rootfs without downloading the entire image upfront.
FSDevice *fs_net_init(const char *url,
void (*start_cb)(void *opaque),
void *opaque)
{
FSNetState *s = mallocz(sizeof(*s));
s->base_url = strdup(url);
s->fs_dev.fs_walk = fs_net_walk;
s->fs_dev.fs_read = fs_net_read;
s->fs_dev.fs_write = fs_net_write;
/* ... */
return &s->fs_dev;
}