Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 0235ecf

Browse files
authored
Merge pull request #616 from bergwolf/bridge
let runv create bridge
2 parents afa358f + 7ec7d7b commit 0235ecf

File tree

8 files changed

+127
-55
lines changed

8 files changed

+127
-55
lines changed

hypervisor/events.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type InterfaceCreated struct {
5252
Id string //user specified in (ref api.InterfaceDescription: a user identifier of interface, user may use this to specify a nic, normally you can use IPAddr as an Id.)
5353
Index int
5454
PCIAddr int
55+
TapFd int
5556
Bridge string
5657
HostDevice string
5758
DeviceName string
@@ -73,6 +74,7 @@ type NetDevInsertedEvent struct {
7374
Index int
7475
DeviceName string
7576
Address int
77+
TapFd int
7678
}
7779

7880
func (ne *NetDevInsertedEvent) ResultId() string {

hypervisor/network.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ func (nc *NetworkContext) addInterface(inf *api.InterfaceDescription, result cha
173173
result <- fe
174174
return
175175
} else if ni, ok := ev.(*NetDevInsertedEvent); ok {
176+
created := nc.idMap[inf.Id]
177+
created.TapFd = ni.TapFd
176178
nc.sandbox.Log(DEBUG, "nic insert success: %s", ni.Id)
177179
result <- ni
178180
return

hypervisor/qemu/network.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,58 @@ package qemu
44

55
import (
66
"fmt"
7+
"os"
78
"os/exec"
89
"strings"
910
"syscall"
11+
"unsafe"
1012

1113
"github.com/golang/glog"
1214
"github.com/hyperhq/runv/hypervisor/network"
13-
"github.com/vishvananda/netlink"
1415
)
1516

16-
func GetTapDevice(device, bridge, options string) error {
17-
la := netlink.NewLinkAttrs()
18-
la.Name = device
19-
tapdev := &netlink.Tuntap{LinkAttrs: la, Mode: syscall.IFF_TAP}
17+
const (
18+
IFNAMSIZ = 16
19+
CIFF_TAP = 0x0002
20+
CIFF_NO_PI = 0x1000
21+
CIFF_ONE_QUEUE = 0x2000
22+
)
23+
24+
type ifReq struct {
25+
Name [IFNAMSIZ]byte
26+
Flags uint16
27+
pad [0x28 - 0x10 - 2]byte
28+
}
2029

21-
if err := netlink.LinkAdd(tapdev); err != nil {
22-
glog.Errorf("fail to create tap device: %v, %v", device, err)
23-
return err
30+
func GetTapFd(device, bridge, options string) (int, error) {
31+
var (
32+
req ifReq
33+
errno syscall.Errno
34+
)
35+
36+
tapFile, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
37+
if err != nil {
38+
return -1, err
2439
}
2540

26-
if err := network.UpAndAddToBridge(device, bridge, options); err != nil {
41+
req.Flags = CIFF_TAP | CIFF_NO_PI | CIFF_ONE_QUEUE
42+
copy(req.Name[:len(req.Name)-1], []byte(device))
43+
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, tapFile.Fd(),
44+
uintptr(syscall.TUNSETIFF),
45+
uintptr(unsafe.Pointer(&req)))
46+
if errno != 0 {
47+
tapFile.Close()
48+
return -1, fmt.Errorf("create tap device failed\n")
49+
}
50+
51+
err = network.UpAndAddToBridge(device, bridge, options)
52+
if err != nil {
2753
glog.Errorf("Add to bridge failed %s %s", bridge, device)
28-
return err
54+
tapFile.Close()
55+
return -1, err
2956
}
3057

31-
return nil
58+
return int(tapFile.Fd()), nil
3259
}
3360

3461
func GetVhostUserPort(device, bridge, sockPath, option string) error {

hypervisor/qemu/qemu.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,16 @@ func (qc *QemuContext) RemoveDisk(ctx *hypervisor.VmContext, blockInfo *hypervis
260260
}
261261

262262
func (qc *QemuContext) AddNic(ctx *hypervisor.VmContext, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
263-
waitChan := make(chan hypervisor.VmEvent, 1)
264-
var err error = nil
263+
var (
264+
fd int = -1
265+
err error
266+
waitChan chan hypervisor.VmEvent = make(chan hypervisor.VmEvent, 1)
267+
)
265268

266269
if ctx.Boot.EnableVhostUser {
267270
err = GetVhostUserPort(host.Device, host.Bridge, ctx.HomeDir, host.Options)
268271
} else {
269-
err = GetTapDevice(host.Device, host.Bridge, host.Options)
272+
fd, err = GetTapFd(host.Device, host.Bridge, host.Options)
270273
}
271274

272275
if err != nil {
@@ -281,15 +284,20 @@ func (qc *QemuContext) AddNic(ctx *hypervisor.VmContext, host *hypervisor.HostNi
281284
// close tap file if necessary
282285
ev, ok := <-waitChan
283286
if !ok {
287+
syscall.Close(fd)
284288
close(result)
285289
} else {
290+
if _, ok := ev.(*hypervisor.DeviceFailed); ok {
291+
syscall.Close(fd)
292+
}
286293
result <- ev
287294
}
288295
}()
289-
newNetworkAddSession(ctx, qc, host, guest, waitChan)
296+
newNetworkAddSession(ctx, qc, fd, host, guest, waitChan)
290297
}
291298

292299
func (qc *QemuContext) RemoveNic(ctx *hypervisor.VmContext, n *hypervisor.InterfaceCreated, callback hypervisor.VmEvent, result chan<- hypervisor.VmEvent) {
300+
syscall.Close(n.TapFd)
293301
newNetworkDelSession(ctx, qc, n.NewName, callback, result)
294302
}
295303

hypervisor/qemu/qmp_wrapper_amd64.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ package qemu
44

55
import (
66
"fmt"
7+
"syscall"
78

9+
"github.com/golang/glog"
810
"github.com/hyperhq/runv/hypervisor"
911
)
1012

11-
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
13+
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, fd int, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
1214
busAddr := fmt.Sprintf("0x%x", guest.Busaddr)
1315
commands := []*QmpCommand{}
1416
if ctx.Boot.EnableVhostUser {
@@ -40,15 +42,26 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hype
4042
"vhostforce": true,
4143
},
4244
})
43-
} else {
45+
} else if fd > 0 {
46+
scm := syscall.UnixRights(fd)
47+
glog.V(1).Infof("send net to qemu at %d", fd)
48+
commands = append(commands, &QmpCommand{
49+
Execute: "getfd",
50+
Arguments: map[string]interface{}{
51+
"fdname": "fd" + guest.Device,
52+
},
53+
Scm: scm,
54+
}, &QmpCommand{
55+
Execute: "netdev_add",
56+
Arguments: map[string]interface{}{
57+
"type": "tap", "id": guest.Device, "fd": "fd" + guest.Device,
58+
},
59+
})
60+
} else if host.Device != "" {
4461
commands = append(commands, &QmpCommand{
4562
Execute: "netdev_add",
4663
Arguments: map[string]interface{}{
47-
"type": "tap",
48-
"script": "no",
49-
"id": guest.Device,
50-
"ifname": host.Device,
51-
"br": host.Bridge,
64+
"type": "tap", "id": guest.Device, "ifname": host.Device, "script": "no",
5265
},
5366
})
5467
}
@@ -71,6 +84,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hype
7184
Index: guest.Index,
7285
DeviceName: guest.Device,
7386
Address: guest.Busaddr,
87+
TapFd: fd,
7488
}),
7589
}
7690
}

hypervisor/qemu/qmp_wrapper_arm64.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,31 @@ package qemu
44

55
import (
66
"fmt"
7+
"syscall"
78

9+
"github.com/golang/glog"
810
"github.com/hyperhq/runv/hypervisor"
911
)
1012

11-
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
13+
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, fd int, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
1214
busAddr := fmt.Sprintf("0x%x", guest.Busaddr)
13-
commands := []*QmpCommand{}
14-
commands = append(commands, &QmpCommand{
15+
commands := make([]*QmpCommand, 3)
16+
scm := syscall.UnixRights(fd)
17+
glog.V(1).Infof("send net to qemu at %d", fd)
18+
commands[0] = &QmpCommand{
19+
Execute: "getfd",
20+
Arguments: map[string]interface{}{
21+
"fdname": "fd" + guest.Device,
22+
},
23+
Scm: scm,
24+
}
25+
commands[1] = &QmpCommand{
1526
Execute: "netdev_add",
1627
Arguments: map[string]interface{}{
17-
"type": "tap",
18-
"script": "no",
19-
"id": guest.Device,
20-
"ifname": host.Device,
21-
"br": host.Bridge,
28+
"type": "tap", "id": guest.Device, "fd": "fd" + guest.Device,
2229
},
23-
})
24-
commands = append(commands, &QmpCommand{
30+
}
31+
commands[2] = &QmpCommand{
2532
Execute: "device_add",
2633
Arguments: map[string]interface{}{
2734
"netdev": guest.Device,
@@ -33,7 +40,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hype
3340
"mac": host.Mac,
3441
"id": guest.Device,
3542
},
36-
})
43+
}
3744

3845
qc.qmp <- &QmpSession{
3946
commands: commands,
@@ -42,6 +49,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, host *hype
4249
Index: guest.Index,
4350
DeviceName: guest.Device,
4451
Address: guest.Busaddr,
52+
TapFd: fd,
4553
}),
4654
}
4755
}

hypervisor/qemu/qmp_wrapper_ppc64le.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,25 @@ import (
1010
"github.com/hyperhq/runv/hypervisor"
1111
)
1212

13-
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, qc *QemuContext, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
13+
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, fd int, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
1414
busAddr := fmt.Sprintf("0x%x", guest.Busaddr)
15-
commands := []*QmpCommand{}
16-
commands = append(commands, &QmpCommand{
15+
commands := make([]*QmpCommand, 3)
16+
scm := syscall.UnixRights(fd)
17+
glog.V(1).Infof("send net to qemu at %d", fd)
18+
commands[0] = &QmpCommand{
19+
Execute: "getfd",
20+
Arguments: map[string]interface{}{
21+
"fdname": "fd" + guest.Device,
22+
},
23+
Scm: scm,
24+
}
25+
commands[1] = &QmpCommand{
1726
Execute: "netdev_add",
1827
Arguments: map[string]interface{}{
19-
"type": "tap",
20-
"script": "no",
21-
"id": guest.Device,
22-
"ifname": host.Device,
23-
"br": host.Bridge,
28+
"type": "tap", "id": guest.Device, "fd": "fd" + guest.Device,
2429
},
25-
})
26-
commands = append(commands, &QmpCommand{
30+
}
31+
commands[2] = &QmpCommand{
2732
Execute: "device_add",
2833
Arguments: map[string]interface{}{
2934
"driver": "virtio-net-pci",
@@ -33,7 +38,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, qc *QemuCo
3338
"addr": busAddr,
3439
"id": guest.Device,
3540
},
36-
})
41+
}
3742

3843
qc.qmp <- &QmpSession{
3944
commands: commands,
@@ -42,6 +47,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, qc *QemuCo
4247
Index: guest.Index,
4348
DeviceName: guest.Device,
4449
Address: guest.Busaddr,
50+
TapFd: fd,
4551
}),
4652
}
4753
}

hypervisor/qemu/qmp_wrapper_s390x.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,32 @@ import (
99
"github.com/hyperhq/runv/hypervisor"
1010
)
1111

12-
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, id string, fd int, device, mac string, index, addr int, result chan<- hypervisor.VmEvent) {
13-
commands := []*QmpCommand{}
12+
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, fd int, host *hypervisor.HostNicInfo, guest *hypervisor.GuestNicInfo, result chan<- hypervisor.VmEvent) {
13+
commands := make([]*QmpCommand, 3)
1414
scm := syscall.UnixRights(fd)
15-
commands = appends(commands, &QmpCommand{
15+
glog.V(1).Infof("send net to qemu at %d", fd)
16+
commands[0] = &QmpCommand{
17+
Execute: "getfd",
18+
Arguments: map[string]interface{}{
19+
"fdname": "fd" + guest.Device,
20+
},
21+
Scm: scm,
22+
}
23+
commands[1] = &QmpCommand{
1624
Execute: "netdev_add",
1725
Arguments: map[string]interface{}{
18-
"type": "tap",
19-
"script": "no",
20-
"id": guest.Device,
21-
"ifname": host.Device,
22-
"br": host.Bridge,
26+
"type": "tap", "id": guest.Device, "fd": "fd" + guest.Device,
2327
},
24-
})
25-
commands = append(commands, &QmpCommand{
28+
}
29+
commands[2] = &QmpCommand{
2630
Execute: "device_add",
2731
Arguments: map[string]interface{}{
2832
"driver": "virtio-net-ccw",
2933
"netdev": guest.Device,
3034
"mac": host.Mac,
3135
"id": guest.Device,
3236
},
33-
})
37+
}
3438

3539
qc.qmp <- &QmpSession{
3640
commands: commands,
@@ -39,6 +43,7 @@ func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, id string,
3943
Index: guest.Index,
4044
DeviceName: guest.Device,
4145
Address: guest.Busaddr,
46+
TapFd: fd,
4247
}),
4348
}
4449
}

0 commit comments

Comments
 (0)