On 02/13/2013 05:21 AM, Alexander Graf wrote: > On 01.02.2013, at 08:39, Jason Wang wrote: > >> This patch adds basic multiqueue support for qemu. The idea is simple, an array >> of NetClientStates were introduced in NICState, parse_netdev() were extended to >> find and match all NetClientStates belongs to the backend and place their >> pointers in NICConf. Then qemu_new_nic can setup a N:N mapping between NICStates >> that belongs to a nic and NICStates belongs to the netdev. And a queue_index >> were introduced in NetClientState to track its index. After this, each peers of >> a NICState were abstracted as a queue. >> >> After this change, all NetClientState that belongs to the same backend/nic has >> the same id. When use want to change the link status, all NetClientStates that >> belongs to the same backend/nic will be also changed. When user want to delete >> a device or netdev, all NetClientStates that belongs to the same backend/nic >> will be deleted also. Changing or deleting an specific queue is not allowed. >> >> Signed-off-by: Jason Wang <jasowang@xxxxxxxxxx> >> Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx> >> --- >> hw/dp8393x.c | 2 +- >> hw/mcf_fec.c | 2 +- >> hw/qdev-properties-system.c | 46 +++++++++++++++--- >> hw/qdev-properties.h | 6 +- >> include/net/net.h | 18 +++++-- >> net/net.c | 113 +++++++++++++++++++++++++++++++------------ >> 6 files changed, 139 insertions(+), 48 deletions(-) >> >> diff --git a/hw/dp8393x.c b/hw/dp8393x.c >> index 0273fad..808157b 100644 >> --- a/hw/dp8393x.c >> +++ b/hw/dp8393x.c >> @@ -900,7 +900,7 @@ void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, >> s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ >> >> s->conf.macaddr = nd->macaddr; >> - s->conf.peer = nd->netdev; >> + s->conf.peers.ncs[0] = nd->netdev; >> >> s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); >> >> diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c >> index 909e32b..8e60f09 100644 >> --- a/hw/mcf_fec.c >> +++ b/hw/mcf_fec.c >> @@ -472,7 +472,7 @@ void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, >> memory_region_add_subregion(sysmem, base, &s->iomem); >> >> s->conf.macaddr = nd->macaddr; >> - s->conf.peer = nd->netdev; >> + s->conf.peers.ncs[0] = nd->netdev; >> >> s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, nd->model, nd->name, s); >> >> diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c >> index ce0f793..ce3af22 100644 >> --- a/hw/qdev-properties-system.c >> +++ b/hw/qdev-properties-system.c >> @@ -173,16 +173,47 @@ PropertyInfo qdev_prop_chr = { >> >> static int parse_netdev(DeviceState *dev, const char *str, void **ptr) >> { >> - NetClientState *netdev = qemu_find_netdev(str); >> + NICPeers *peers_ptr = (NICPeers *)ptr; >> + NICConf *conf = container_of(peers_ptr, NICConf, peers); >> + NetClientState **ncs = peers_ptr->ncs; >> + NetClientState *peers[MAX_QUEUE_NUM]; >> + int queues, i = 0; >> + int ret; >> >> - if (netdev == NULL) { >> - return -ENOENT; >> + queues = qemu_find_net_clients_except(str, peers, >> + NET_CLIENT_OPTIONS_KIND_NIC, >> + MAX_QUEUE_NUM); >> + if (queues == 0) { >> + ret = -ENOENT; >> + goto err; >> } >> - if (netdev->peer) { >> - return -EEXIST; >> + >> + if (queues > MAX_QUEUE_NUM) { >> + ret = -E2BIG; >> + goto err; >> + } >> + >> + for (i = 0; i < queues; i++) { >> + if (peers[i] == NULL) { >> + ret = -ENOENT; >> + goto err; >> + } >> + >> + if (peers[i]->peer) { >> + ret = -EEXIST; >> + goto err; >> + } >> + >> + ncs[i] = peers[i]; >> + ncs[i]->queue_index = i; >> } >> - *ptr = netdev; >> + >> + conf->queues = queues; >> + >> return 0; >> + >> +err: >> + return ret; >> } >> >> static const char *print_netdev(void *ptr) >> @@ -249,7 +280,8 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, >> { >> DeviceState *dev = DEVICE(obj); >> Property *prop = opaque; >> - NetClientState **ptr = qdev_get_prop_ptr(dev, prop); >> + NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop); >> + NetClientState **ptr = &peers_ptr->ncs[0]; >> Error *local_err = NULL; >> int32_t id; >> NetClientState *hubport; >> diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h >> index ddcf774..20c67f3 100644 >> --- a/hw/qdev-properties.h >> +++ b/hw/qdev-properties.h >> @@ -31,7 +31,7 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; >> .name = (_name), \ >> .info = &(_prop), \ >> .offset = offsetof(_state, _field) \ >> - + type_check(_type,typeof_field(_state, _field)), \ >> + + type_check(_type, typeof_field(_state, _field)), \ >> } >> #define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \ >> .name = (_name), \ >> @@ -77,9 +77,9 @@ extern PropertyInfo qdev_prop_pci_host_devaddr; >> #define DEFINE_PROP_STRING(_n, _s, _f) \ >> DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) >> #define DEFINE_PROP_NETDEV(_n, _s, _f) \ >> - DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NetClientState*) >> + DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) >> #define DEFINE_PROP_VLAN(_n, _s, _f) \ >> - DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NetClientState*) >> + DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers) >> #define DEFINE_PROP_DRIVE(_n, _s, _f) \ >> DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *) >> #define DEFINE_PROP_MACADDR(_n, _s, _f) \ >> diff --git a/include/net/net.h b/include/net/net.h >> index 22adc99..43a045e 100644 >> --- a/include/net/net.h >> +++ b/include/net/net.h >> @@ -9,24 +9,32 @@ >> #include "migration/vmstate.h" >> #include "qapi-types.h" >> >> +#define MAX_QUEUE_NUM 1024 >> + >> struct MACAddr { >> uint8_t a[6]; >> }; >> >> /* qdev nic properties */ >> >> +typedef struct NICPeers { >> + NetClientState *ncs[MAX_QUEUE_NUM]; >> +} NICPeers; >> + >> typedef struct NICConf { >> MACAddr macaddr; >> - NetClientState *peer; >> + NICPeers peers; >> int32_t bootindex; >> + int32_t queues; >> } NICConf; >> >> #define DEFINE_NIC_PROPERTIES(_state, _conf) \ >> DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \ >> - DEFINE_PROP_VLAN("vlan", _state, _conf.peer), \ >> - DEFINE_PROP_NETDEV("netdev", _state, _conf.peer), \ >> + DEFINE_PROP_VLAN("vlan", _state, _conf.peers), \ >> + DEFINE_PROP_NETDEV("netdev", _state, _conf.peers), \ >> DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1) >> >> + >> /* Net clients */ >> >> typedef void (NetPoll)(NetClientState *, bool enable); >> @@ -60,10 +68,11 @@ struct NetClientState { >> char info_str[256]; >> unsigned receive_disabled : 1; >> NetClientDestructor *destructor; >> + unsigned int queue_index; >> }; >> >> typedef struct NICState { >> - NetClientState nc; >> + NetClientState ncs[MAX_QUEUE_NUM]; >> NICConf *conf; >> void *opaque; >> bool peer_deleted; >> @@ -82,6 +91,7 @@ NICState *qemu_new_nic(NetClientInfo *info, >> const char *name, >> void *opaque); >> void qemu_del_nic(NICState *nic); >> +NetClientState *qemu_get_subqueue(NICState *nic, int queue_index); >> NetClientState *qemu_get_queue(NICState *nic); >> NICState *qemu_get_nic(NetClientState *nc); >> void *qemu_get_nic_opaque(NetClientState *nc); >> diff --git a/net/net.c b/net/net.c >> index 98a1934..9806862 100644 >> --- a/net/net.c >> +++ b/net/net.c >> @@ -236,28 +236,44 @@ NICState *qemu_new_nic(NetClientInfo *info, >> void *opaque) >> { >> NetClientState *nc; >> + NetClientState **peers = conf->peers.ncs; >> NICState *nic; >> + int i; >> >> assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); >> assert(info->size >= sizeof(NICState)); >> >> - nc = qemu_new_net_client(info, conf->peer, model, name); >> + nc = qemu_new_net_client(info, peers[0], model, name); >> + nc->queue_index = 0; >> >> nic = qemu_get_nic(nc); >> nic->conf = conf; >> nic->opaque = opaque; >> >> + for (i = 1; i < conf->queues; i++) { >> + qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name, >> + NULL); >> + nic->ncs[i].queue_index = i; >> + } >> + >> return nic; >> } >> >> +NetClientState *qemu_get_subqueue(NICState *nic, int queue_index) >> +{ >> + return &nic->ncs[queue_index]; >> +} >> + >> NetClientState *qemu_get_queue(NICState *nic) >> { >> - return &nic->nc; >> + return qemu_get_subqueue(nic, 0); >> } >> >> NICState *qemu_get_nic(NetClientState *nc) >> { >> - return DO_UPCAST(NICState, nc, nc); >> + NetClientState *nc0 = nc - nc->queue_index; >> + >> + return DO_UPCAST(NICState, ncs[0], nc0); >> } >> >> void *qemu_get_nic_opaque(NetClientState *nc) >> @@ -271,9 +287,7 @@ static void qemu_cleanup_net_client(NetClientState *nc) >> { >> QTAILQ_REMOVE(&net_clients, nc, next); >> >> - if (nc->info->cleanup) { >> - nc->info->cleanup(nc); >> - } >> + nc->info->cleanup(nc); > This breaks the following backends: > > hw/pcnet.c > hw/spapr_llan.c > hw/xen_nic.c > > Is this change on purpose? If so, please provide empty cleanup function callbacks for the above targets. > Not on purpose, a guard is needed but empty cleanup function is also ok. Thanks > Alex > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html