you can find this code at 4119 line of vl.c

   if (net_init_clients() < 0) {

        exit(1);

    }

and also can find this code  at 188 line of qemu/hw/i386/pc_piix.c

    pc_nic_init(isa_bus, pci_bus); // network card initialization


Those two parts are key function to start initializing Network of Guest and Hypervisor.

Then, let's follow those functions.

First, we are starting with net_init_clients() function.

int net_init_clients(void)

{

    QemuOptsList *net = qemu_find_opts("net");


    if (default_net) {

        /* if no clients, we use a default config */

        qemu_opts_set(net, NULL, "type", "nic");

#ifdef CONFIG_SLIRP

        qemu_opts_set(net, NULL, "type", "user");

#endif

    }


    QTAILQ_INIT(&net_clients);


    if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)

        return -1;


    if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {

        return -1;

    }


    return 0;

}

those function both net_init_netdev and net_init_client are doing same thing, so we follow net_init_netdev function.( finally both will call net_client_init function.

static int net_init_netdev(QemuOpts *opts, void *dummy)

{

    Error *local_err = NULL;

    int ret;


    ret = net_client_init(opts, 1, &local_err);

    if (error_is_set(&local_err)) {

        qerror_report_err(local_err);

        error_free(local_err);

        return -1;

    }

    return ret;

}

int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)

{

    void *object = NULL;

    Error *err = NULL;

    int ret = -1;


    {

        OptsVisitor *ov = opts_visitor_new(opts);


        net_visit(opts_get_visitor(ov), is_netdev, &object, &err);

        opts_visitor_cleanup(ov);

    }


    if (!err) {

        ret = net_client_init1(object, is_netdev, &err);

    }


    if (object) {

        QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();


        net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);

        qapi_dealloc_visitor_cleanup(dv);

    }


    error_propagate(errp, err);

    return ret;

}


static int net_client_init1(const void *object, int is_netdev, Error **errp)

{

    union {

        const Netdev    *netdev;

        const NetLegacy *net;

    } u;

    const NetClientOptions *opts;

    const char *name;


    if (is_netdev) {

        u.netdev = object;

        opts = u.netdev->opts;

        name = u.netdev->id;


        switch (opts->kind) {

#ifdef CONFIG_SLIRP

        case NET_CLIENT_OPTIONS_KIND_USER:

#endif

        case NET_CLIENT_OPTIONS_KIND_TAP:

        case NET_CLIENT_OPTIONS_KIND_SOCKET:

#ifdef CONFIG_VDE

        case NET_CLIENT_OPTIONS_KIND_VDE:

#endif

#ifdef CONFIG_NET_BRIDGE

        case NET_CLIENT_OPTIONS_KIND_BRIDGE:

#endif

        case NET_CLIENT_OPTIONS_KIND_HUBPORT:

            break;


        default:

            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",

                      "a netdev backend type");

            return -1;

        }

    } else {

        u.net = object;

        opts = u.net->opts;

        /* missing optional values have been initialized to "all bits zero" */

        name = u.net->has_id ? u.net->id : u.net->name;

    }


    if (net_client_init_fun[opts->kind]) {

        NetClientState *peer = NULL;


        /* Do not add to a vlan if it's a -netdev or a nic with a netdev=

         * parameter. */

        if (!is_netdev &&

            (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC ||

             !opts->nic->has_netdev)) {

            peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);

        }


        if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {

            /* TODO push error reporting into init() methods */

            error_set(errp, QERR_DEVICE_INIT_FAILED,

                      NetClientOptionsKind_lookup[opts->kind]);

            return -1;

        }

    }

    return 0;

}

finally we found function pointers, here are functions for that pointer structure.

static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(

    const NetClientOptions *opts,

    const char *name,

    NetClientState *peer) = {

        [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,

#ifdef CONFIG_SLIRP

        [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,

#endif

        [NET_CLIENT_OPTIONS_KIND_TAP]       = net_init_tap,

        [NET_CLIENT_OPTIONS_KIND_SOCKET]    = net_init_socket,

#ifdef CONFIG_VDE

        [NET_CLIENT_OPTIONS_KIND_VDE]       = net_init_vde,

#endif

        [NET_CLIENT_OPTIONS_KIND_DUMP]      = net_init_dump,

#ifdef CONFIG_NET_BRIDGE

        [NET_CLIENT_OPTIONS_KIND_BRIDGE]    = net_init_bridge,

#endif

        [NET_CLIENT_OPTIONS_KIND_HUBPORT]   = net_init_hubport,

};


Posted by MeatNBrew
l