net: Move the code to collect available NIC models to a separate function

The code that collects the available NIC models is not really specific
to PCI anymore and will be required in the next patch, too, so let's
move this into a new separate function in net.c instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Thomas Huth 2022-11-10 13:52:22 +01:00 committed by Jason Wang
parent 6dffbe36af
commit c6941b3b9b
3 changed files with 49 additions and 28 deletions

View File

@ -1789,7 +1789,6 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
const char *default_devaddr)
{
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
GSList *list;
GPtrArray *pci_nic_models;
PCIBus *bus;
PCIDevice *pci_dev;
@ -1804,33 +1803,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
nd->model = g_strdup("virtio-net-pci");
}
list = object_class_get_list_sorted(TYPE_PCI_DEVICE, false);
pci_nic_models = g_ptr_array_new();
while (list) {
DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
TYPE_DEVICE);
GSList *next;
if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
dc->user_creatable) {
const char *name = object_class_get_name(list->data);
/*
* A network device might also be something else than a NIC, see
* e.g. the "rocker" device. Thus we have to look for the "netdev"
* property, too. Unfortunately, some devices like virtio-net only
* create this property during instance_init, so we have to create
* a temporary instance here to be able to check it.
*/
Object *obj = object_new_with_class(OBJECT_CLASS(dc));
if (object_property_find(obj, "netdev")) {
g_ptr_array_add(pci_nic_models, (gpointer)name);
}
object_unref(obj);
}
next = list->next;
g_slist_free_1(list);
list = next;
}
g_ptr_array_add(pci_nic_models, NULL);
pci_nic_models = qemu_get_nic_models(TYPE_PCI_DEVICE);
if (qemu_show_nic_models(nd->model, (const char **)pci_nic_models->pdata)) {
exit(0);

View File

@ -203,6 +203,20 @@ void net_socket_rs_init(SocketReadState *rs,
bool vnet_hdr);
NetClientState *qemu_get_peer(NetClientState *nc, int queue_index);
/**
* qemu_get_nic_models:
* @device_type: Defines which devices should be taken into consideration
* (e.g. TYPE_DEVICE for all devices, or TYPE_PCI_DEVICE for PCI)
*
* Get an array of pointers to names of NIC devices that are available in
* the QEMU binary. The array is terminated with a NULL pointer entry.
* The caller is responsible for freeing the memory when it is not required
* anymore, e.g. with g_ptr_array_free(..., true).
*
* Returns: Pointer to the array that contains the pointers to the names.
*/
GPtrArray *qemu_get_nic_models(const char *device_type);
/* NIC info */
#define MAX_NICS 8

View File

@ -899,6 +899,40 @@ static int nic_get_free_idx(void)
return -1;
}
GPtrArray *qemu_get_nic_models(const char *device_type)
{
GPtrArray *nic_models = g_ptr_array_new();
GSList *list = object_class_get_list_sorted(device_type, false);
while (list) {
DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
TYPE_DEVICE);
GSList *next;
if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
dc->user_creatable) {
const char *name = object_class_get_name(list->data);
/*
* A network device might also be something else than a NIC, see
* e.g. the "rocker" device. Thus we have to look for the "netdev"
* property, too. Unfortunately, some devices like virtio-net only
* create this property during instance_init, so we have to create
* a temporary instance here to be able to check it.
*/
Object *obj = object_new_with_class(OBJECT_CLASS(dc));
if (object_property_find(obj, "netdev")) {
g_ptr_array_add(nic_models, (gpointer)name);
}
object_unref(obj);
}
next = list->next;
g_slist_free_1(list);
list = next;
}
g_ptr_array_add(nic_models, NULL);
return nic_models;
}
int qemu_show_nic_models(const char *arg, const char *const *models)
{
int i;