diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 3575bf64ee..640434d1ea 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -363,11 +363,51 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, return vhost_svq_poll(svq); } +static int vhost_vdpa_net_load(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + const struct vhost_vdpa *v = &s->vhost_vdpa; + const VirtIONet *n; + uint64_t features; + + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + if (!v->shadow_vqs_enabled) { + return 0; + } + + n = VIRTIO_NET(v->dev->vdev); + features = n->parent_obj.guest_features; + if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { + const struct virtio_net_ctrl_hdr ctrl = { + .class = VIRTIO_NET_CTRL_MAC, + .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET, + }; + char *cursor = s->cvq_cmd_out_buffer; + ssize_t dev_written; + + memcpy(cursor, &ctrl, sizeof(ctrl)); + cursor += sizeof(ctrl); + memcpy(cursor, n->mac, sizeof(n->mac)); + + dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac), + sizeof(virtio_net_ctrl_ack)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK; + } + + return 0; +} + static NetClientInfo net_vhost_vdpa_cvq_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), .receive = vhost_vdpa_receive, .start = vhost_vdpa_net_cvq_start, + .load = vhost_vdpa_net_load, .stop = vhost_vdpa_net_cvq_stop, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,