Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit eaa35f5

Browse files
avagincrosbymichael
authored andcommitted
cr: add network support
We need to enumirate all veth devices on restore and handle {un,}lock-network notifications. Signed-off-by: Andrey Vagin <[email protected]>
1 parent 032aca3 commit eaa35f5

File tree

3 files changed

+116
-18
lines changed

3 files changed

+116
-18
lines changed

Diff for: container_linux.go

+52
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,18 @@ func (c *linuxContainer) Restore(process *Process, imagePath string) error {
417417
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
418418
}
419419
}
420+
for _, iface := range c.config.Networks {
421+
switch iface.Type {
422+
case "veth":
423+
veth := new(criurpc.CriuVethPair)
424+
veth.IfOut = proto.String(iface.HostInterfaceName)
425+
veth.IfIn = proto.String(iface.Name)
426+
req.Opts.Veths = append(req.Opts.Veths, veth)
427+
break
428+
case "loopback":
429+
break
430+
}
431+
}
420432
// Pipes that were previously set up for std{in,out,err}
421433
// were removed after checkpoint. Use the new ones.
422434
var i int32
@@ -555,6 +567,34 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, imageP
555567
return nil
556568
}
557569

570+
// block any external network activity
571+
func lockNetwork(config *configs.Config) error {
572+
for _, config := range config.Networks {
573+
strategy, err := getStrategy(config.Type)
574+
if err != nil {
575+
return err
576+
}
577+
578+
if err := strategy.detach(config); err != nil {
579+
return err
580+
}
581+
}
582+
return nil
583+
}
584+
585+
func unlockNetwork(config *configs.Config) error {
586+
for _, config := range config.Networks {
587+
strategy, err := getStrategy(config.Type)
588+
if err != nil {
589+
return err
590+
}
591+
if err = strategy.attach(config); err != nil {
592+
return err
593+
}
594+
}
595+
return nil
596+
}
597+
558598
func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Process, imagePath string) error {
559599
notify := resp.GetNotify()
560600
if notify == nil {
@@ -570,6 +610,18 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
570610
f.Close()
571611
break
572612

613+
case notify.GetScript() == "network-unlock":
614+
if err := unlockNetwork(c.config); err != nil {
615+
return err
616+
}
617+
break
618+
619+
case notify.GetScript() == "network-lock":
620+
if err := lockNetwork(c.config); err != nil {
621+
return err
622+
}
623+
break
624+
573625
case notify.GetScript() == "post-restore":
574626
pid := notify.GetPid()
575627
r, err := newRestoredProcess(int(pid))

Diff for: netlink/netlink_linux.go

+15-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const (
2727
SIOC_BRADDBR = 0x89a0
2828
SIOC_BRDELBR = 0x89a1
2929
SIOC_BRADDIF = 0x89a2
30+
SIOC_BRDELIF = 0x89a3
3031
)
3132

3233
const (
@@ -1191,9 +1192,7 @@ func DeleteBridge(name string) error {
11911192
return nil
11921193
}
11931194

1194-
// Add a slave to abridge device. This is more backward-compatible than
1195-
// netlink.NetworkSetMaster and works on RHEL 6.
1196-
func AddToBridge(iface, master *net.Interface) error {
1195+
func ifIoctBridge(iface, master *net.Interface, op uintptr) error {
11971196
if len(master.Name) >= IFNAMSIZ {
11981197
return fmt.Errorf("Interface name %s too long", master.Name)
11991198
}
@@ -1208,13 +1207,25 @@ func AddToBridge(iface, master *net.Interface) error {
12081207
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
12091208
ifr.IfruIndex = int32(iface.Index)
12101209

1211-
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDIF, uintptr(unsafe.Pointer(&ifr))); err != 0 {
1210+
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), op, uintptr(unsafe.Pointer(&ifr))); err != 0 {
12121211
return err
12131212
}
12141213

12151214
return nil
12161215
}
12171216

1217+
// Add a slave to a bridge device. This is more backward-compatible than
1218+
// netlink.NetworkSetMaster and works on RHEL 6.
1219+
func AddToBridge(iface, master *net.Interface) error {
1220+
return ifIoctBridge(iface, master, SIOC_BRADDIF)
1221+
}
1222+
1223+
// Detach a slave from a bridge device. This is more backward-compatible than
1224+
// netlink.NetworkSetMaster and works on RHEL 6.
1225+
func DelFromBridge(iface, master *net.Interface) error {
1226+
return ifIoctBridge(iface, master, SIOC_BRDELIF)
1227+
}
1228+
12181229
func randMacAddr() string {
12191230
hw := make(net.HardwareAddr, 6)
12201231
for i := 0; i < 6; i++ {

Diff for: network_linux.go

+49-14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strconv"
1111
"strings"
1212

13+
"github.com/docker/libcontainer/configs"
1314
"github.com/docker/libcontainer/netlink"
1415
"github.com/docker/libcontainer/utils"
1516
)
@@ -24,6 +25,8 @@ var strategies = map[string]networkStrategy{
2425
type networkStrategy interface {
2526
create(*network, int) error
2627
initialize(*network) error
28+
detach(*configs.Network) error
29+
attach(*configs.Network) error
2730
}
2831

2932
// getStrategy returns the specific network strategy for the
@@ -97,32 +100,39 @@ func (l *loopback) initialize(config *network) error {
97100
return netlink.NetworkLinkUp(iface)
98101
}
99102

103+
func (l *loopback) attach(n *configs.Network) (err error) {
104+
return nil
105+
}
106+
107+
func (l *loopback) detach(n *configs.Network) (err error) {
108+
return nil
109+
}
110+
100111
// veth is a network strategy that uses a bridge and creates
101112
// a veth pair, one that is attached to the bridge on the host and the other
102113
// is placed inside the container's namespace
103114
type veth struct {
104115
}
105116

106-
func (v *veth) create(n *network, nspid int) (err error) {
107-
tmpName, err := v.generateTempPeerName()
117+
func (v *veth) detach(n *configs.Network) (err error) {
118+
bridge, err := net.InterfaceByName(n.Bridge)
108119
if err != nil {
109120
return err
110121
}
111-
n.TempVethPeerName = tmpName
112-
defer func() {
113-
if err != nil {
114-
netlink.NetworkLinkDel(n.HostInterfaceName)
115-
netlink.NetworkLinkDel(n.TempVethPeerName)
116-
}
117-
}()
118-
if n.Bridge == "" {
119-
return fmt.Errorf("bridge is not specified")
120-
}
121-
bridge, err := net.InterfaceByName(n.Bridge)
122+
host, err := net.InterfaceByName(n.HostInterfaceName)
122123
if err != nil {
123124
return err
124125
}
125-
if err := netlink.NetworkCreateVethPair(n.HostInterfaceName, n.TempVethPeerName, n.TxQueueLen); err != nil {
126+
if err := netlink.DelFromBridge(host, bridge); err != nil {
127+
return err
128+
}
129+
return nil
130+
}
131+
132+
// attach a container network interface to an external network
133+
func (v *veth) attach(n *configs.Network) (err error) {
134+
bridge, err := net.InterfaceByName(n.Bridge)
135+
if err != nil {
126136
return err
127137
}
128138
host, err := net.InterfaceByName(n.HostInterfaceName)
@@ -143,6 +153,31 @@ func (v *veth) create(n *network, nspid int) (err error) {
143153
if err := netlink.NetworkLinkUp(host); err != nil {
144154
return err
145155
}
156+
157+
return nil
158+
}
159+
160+
func (v *veth) create(n *network, nspid int) (err error) {
161+
tmpName, err := v.generateTempPeerName()
162+
if err != nil {
163+
return err
164+
}
165+
n.TempVethPeerName = tmpName
166+
defer func() {
167+
if err != nil {
168+
netlink.NetworkLinkDel(n.HostInterfaceName)
169+
netlink.NetworkLinkDel(n.TempVethPeerName)
170+
}
171+
}()
172+
if n.Bridge == "" {
173+
return fmt.Errorf("bridge is not specified")
174+
}
175+
if err := netlink.NetworkCreateVethPair(n.HostInterfaceName, n.TempVethPeerName, n.TxQueueLen); err != nil {
176+
return err
177+
}
178+
if err := v.attach(&n.Network); err != nil {
179+
return err
180+
}
146181
child, err := net.InterfaceByName(n.TempVethPeerName)
147182
if err != nil {
148183
return err

0 commit comments

Comments
 (0)