Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

qemu/qmp: implement function for hotplug network #24

Merged
merged 1 commit into from
Jul 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions qemu/qmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,51 @@ func (q *QMP) ExecuteBlockdevDel(ctx context.Context, blockdevID string) error {
return q.executeCommand(ctx, "x-blockdev-del", args, nil)
}

// ExecuteNetdevAdd adds a Net device to a QEMU instance
// using the netdev_add command. netdevID is the id of the device to add.
// Must be valid QMP identifier.
func (q *QMP) ExecuteNetdevAdd(ctx context.Context, netdevType, netdevID, ifname, downscript, script string, queues int) error {
args := map[string]interface{}{
"type": netdevType,
"id": netdevID,
"ifname": ifname,
"downscript": downscript,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason script is not exposed but downscript is? In kata containers, I think we will always set them to "no" but if we expose one of them, we'd better expose the other too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"script" is in the next line 739

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I thought I deleted that line of comment but somehow it still appeared there...

"script": script,
}
if queues > 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment comes a little late but I just wanted to confirm that there's no need to ever explicitly set

args["queues"] = 1

and that this is essentially the default. I had a quick check of the qemu manual but I was unable to confirm this for netdev.

args["queues"] = queues
}

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 {
args := map[string]interface{}{
"id": netdevID,
}
return q.executeCommand(ctx, "netdev_del", args, nil)
}

// ExecuteNetPCIDeviceAdd adds a Net PCI device to a QEMU instance
// using the device_add command. devID is the id of the device to add.
// Must be valid QMP identifier. netdevID is the id of nic added by previous netdev_add.
func (q *QMP) ExecuteNetPCIDeviceAdd(ctx context.Context, netdevID, devID, macAddr, addr, bus string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you please add UT for ExecuteNetPCIDeviceAdd() as well? So that we can get rid of the codecov drop.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check is passed. I will add it.

args := map[string]interface{}{
"id": devID,
"driver": VirtioNetPCI,
"netdev": netdevID,
"mac": macAddr,
"addr": addr,
}

if bus != "" {
args["bus"] = bus
}
return q.executeCommand(ctx, "device_add", args, nil)
}

// ExecuteDeviceDel deletes guest portion of a QEMU device by sending a
// device_del command. devId is the identifier of the device to delete.
// Typically it would match the devID parameter passed to an earlier call
Expand Down
60 changes: 60 additions & 0 deletions qemu/qmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,66 @@ func TestQMPBlockdevAdd(t *testing.T) {
<-disconnectedCh
}

// Checks that the netdev_add command is correctly sent.
//
// We start a QMPLoop, send the netdev_add command and stop the loop.
//
// The netdev_add command should be correctly sent and the QMP loop should
// exit gracefully.
func TestQMPNetdevAdd(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.ExecuteNetdevAdd(context.Background(), "tap", "br0", "tap0", "no", "no", 8)
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.
//
// The netdev_del command should be correctly sent and the QMP loop should
// exit gracefully.
func TestQMPNetdevDel(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
buf.AddCommand("netdev_del", nil, "return", nil)
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
q.version = checkVersion(t, connectedCh)
err := q.ExecuteNetdevDel(context.Background(), "br0")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
q.Shutdown()
<-disconnectedCh
}

func TestQMPNetPCIDeviceAdd(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
buf.AddCommand("device_add", nil, "return", nil)
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh)
err := q.ExecuteNetPCIDeviceAdd(context.Background(), "br0", "virtio-0", "02:42:ac:11:00:02", "0x7", "")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
q.Shutdown()
<-disconnectedCh
}

// Checks that the device_add command is correctly sent.
//
// We start a QMPLoop, send the device_add command and stop the loop.
Expand Down