diff --git a/qemu/qmp.go b/qemu/qmp.go index 40e4781a69..ea6cb6454e 100644 --- a/qemu/qmp.go +++ b/qemu/qmp.go @@ -29,6 +29,7 @@ import ( "time" "context" + "strings" ) // QMPLog is a logging interface used by the qemu package to log various @@ -755,6 +756,23 @@ func (q *QMP) ExecuteNetdevAdd(ctx context.Context, netdevType, netdevID, ifname return q.executeCommand(ctx, "netdev_add", args, nil) } +// ExecuteNetdevAddByFds adds a Net device to a QEMU instance +// using the netdev_add command by fds and vhostfds. netdevID is the id of the device to add. +// Must be valid QMP identifier. +func (q *QMP) ExecuteNetdevAddByFds(ctx context.Context, netdevType, netdevID string, fdNames, vhostFdNames []string) error { + fdNameStr := strings.Join(fdNames, ":") + vhostFdNameStr := strings.Join(vhostFdNames, ":") + args := map[string]interface{}{ + "type": netdevType, + "id": netdevID, + "fds": fdNameStr, + "vhost": "on", + "vhostfds": vhostFdNameStr, + } + + return q.executeCommand(ctx, "netdev_add", args, nil) +} + // ExecuteNetdevDel deletes a Net device from a QEMU instance // using the netdev_del command. netdevID is the id of the device to delete. func (q *QMP) ExecuteNetdevDel(ctx context.Context, netdevID string) error { diff --git a/qemu/qmp_test.go b/qemu/qmp_test.go index c6c4ed4f00..fe3d0b5b72 100644 --- a/qemu/qmp_test.go +++ b/qemu/qmp_test.go @@ -387,6 +387,28 @@ func TestQMPNetdevAdd(t *testing.T) { <-disconnectedCh } +// Checks that the netdev_add command with fds is correctly sent. +// +// We start a QMPLoop, send the netdev_add command with fds and stop the loop. +// +// The netdev_add command with fds should be correctly sent and the QMP loop should +// exit gracefully. +func TestQMPNetdevAddByFds(t *testing.T) { + connectedCh := make(chan *QMPVersion) + disconnectedCh := make(chan struct{}) + buf := newQMPTestCommandBuffer(t) + buf.AddCommand("netdev_add", nil, "return", nil) + cfg := QMPConfig{Logger: qmpTestLogger{}} + q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh) + q.version = checkVersion(t, connectedCh) + err := q.ExecuteNetdevAddByFds(context.Background(), "tap", "br0", nil, nil) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + q.Shutdown() + <-disconnectedCh +} + // Checks that the netdev_del command is correctly sent. // // We start a QMPLoop, send the netdev_del command and stop the loop.