This is needed so the destination vdpa device see the same state a the guest set in the source.
Signed-off-by: Eugenio Pérez <epere...@redhat.com> --- v5: * Rename s/start/load/ * Use independent NetClientInfo to only add load callback on cvq. --- net/vhost-vdpa.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 8d400f2dff..d489fcd91e 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -375,10 +375,60 @@ static virtio_net_ctrl_ack vhost_vdpa_net_cvq_add(VhostVDPAState *s, return VIRTIO_NET_OK; } +static int vhost_vdpa_net_load(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + struct vhost_vdpa *v = &s->vhost_vdpa; + 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 = v->dev->vdev->host_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, + }; + uint8_t mac[6]; + const struct iovec out[] = { + { + .iov_base = (void *)&ctrl, + .iov_len = sizeof(ctrl), + },{ + .iov_base = mac, + .iov_len = sizeof(mac), + }, + }; + size_t out_len; + bool ok; + virtio_net_ctrl_ack state; + + ok = vhost_vdpa_net_cvq_map_sg(s, out, ARRAY_SIZE(out), &out_len); + if (unlikely(!ok)) { + return -1; + } + + memcpy(mac, n->mac, sizeof(mac)); + state = vhost_vdpa_net_cvq_add(s, out_len); + vhost_vdpa_cvq_unmap_buf(v, s->cvq_cmd_out_buffer); + vhost_vdpa_cvq_unmap_buf(v, s->cvq_cmd_in_buffer); + return state == VIRTIO_NET_OK ? 0 : 1; + } + + return 0; +} + static NetClientInfo net_vhost_vdpa_cvq_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), .receive = vhost_vdpa_receive, + .load = vhost_vdpa_net_load, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, .has_ufo = vhost_vdpa_has_ufo, -- 2.31.1