github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/network/configure.go (about) 1 package network 2 3 import ( 4 "errors" 5 "net" 6 7 "code.cloudfoundry.org/lager" 8 ) 9 10 //go:generate counterfeiter . Configurer 11 type Configurer interface { 12 ConfigureContainer(*ContainerConfig) error 13 ConfigureHost(*HostConfig) error 14 } 15 16 //go:generate counterfeiter . Hostname 17 type Hostname interface { 18 SetHostname(hostName string) error 19 } 20 21 type NetworkConfigurer struct { 22 Hostname Hostname 23 24 Veth interface { 25 Create(hostIfcName, containerIfcName string) (*net.Interface, *net.Interface, error) 26 } 27 28 Link interface { 29 AddIP(intf *net.Interface, ip net.IP, subnet *net.IPNet) error 30 AddDefaultGW(intf *net.Interface, ip net.IP) error 31 SetUp(intf *net.Interface) error 32 SetMTU(intf *net.Interface, mtu int) error 33 SetNs(intf *net.Interface, pid int) error 34 InterfaceByName(name string) (*net.Interface, bool, error) 35 } 36 37 Bridge interface { 38 Create(bridgeName string, ip net.IP, subnet *net.IPNet) (*net.Interface, error) 39 Add(bridge, slave *net.Interface) error 40 } 41 42 Logger lager.Logger 43 } 44 45 type HostConfig struct { 46 HostIntf string 47 BridgeName string 48 BridgeIP net.IP 49 ContainerIntf string 50 ContainerPid int 51 Subnet *net.IPNet 52 Mtu int 53 } 54 55 func (c *NetworkConfigurer) ConfigureHost(config *HostConfig) error { 56 var ( 57 err error 58 host *net.Interface 59 container *net.Interface 60 bridge *net.Interface 61 ) 62 63 cLog := c.Logger.Session("configure-host", lager.Data{ 64 "bridgeName": config.BridgeName, 65 "bridgeIP": config.BridgeIP, 66 "subnet": config.Subnet, 67 "containerIface": config.ContainerIntf, 68 "hostIface": config.HostIntf, 69 "mtu": config.Mtu, 70 "pid": config.ContainerPid, 71 }) 72 73 cLog.Debug("configuring") 74 75 if bridge, err = c.configureBridgeIntf(cLog, config.BridgeName, config.BridgeIP, config.Subnet); err != nil { 76 return err 77 } 78 79 if host, container, err = c.configureVethPair(cLog, config.HostIntf, config.ContainerIntf); err != nil { 80 return err 81 } 82 83 if err = c.configureHostIntf(cLog, host, bridge, config.Mtu); err != nil { 84 return err 85 } 86 87 // move container end in to container 88 if err = c.Link.SetNs(container, config.ContainerPid); err != nil { 89 return &SetNsFailedError{err, container, config.ContainerPid} 90 } 91 92 return nil 93 } 94 95 func (c *NetworkConfigurer) configureBridgeIntf(log lager.Logger, name string, ip net.IP, subnet *net.IPNet) (*net.Interface, error) { 96 log = log.Session("bridge-interface") 97 98 log.Debug("find") 99 bridge, bridgeExists, err := c.Link.InterfaceByName(name) 100 if err != nil || !bridgeExists { 101 log.Error("find", err) 102 return nil, &BridgeDetectionError{errors.New("look up existing bridge"), name, ip, subnet} 103 } 104 105 log.Debug("bring-up") 106 if err = c.Link.SetUp(bridge); err != nil { 107 log.Error("bring-up", err) 108 return nil, &LinkUpError{err, bridge, "bridge"} 109 } 110 111 return bridge, nil 112 } 113 114 func (c *NetworkConfigurer) configureVethPair(log lager.Logger, hostName, containerName string) (*net.Interface, *net.Interface, error) { 115 log = log.Session("veth") 116 117 log.Debug("create") 118 if host, container, err := c.Veth.Create(hostName, containerName); err != nil { 119 log.Error("create", err) 120 return nil, nil, &VethPairCreationError{err, hostName, containerName} 121 } else { 122 return host, container, err 123 } 124 } 125 126 func (c *NetworkConfigurer) configureHostIntf(log lager.Logger, intf *net.Interface, bridge *net.Interface, mtu int) error { 127 log = log.Session("host-interface", lager.Data{ 128 "bridge-interface": bridge, 129 "host-interface": intf, 130 }) 131 132 log.Debug("set-mtu") 133 if err := c.Link.SetMTU(intf, mtu); err != nil { 134 log.Error("set-mtu", err) 135 return &MTUError{err, intf, mtu} 136 } 137 138 log.Debug("add-to-bridge") 139 if err := c.Bridge.Add(bridge, intf); err != nil { 140 log.Error("add-to-bridge", err) 141 return &AddToBridgeError{err, bridge, intf} 142 } 143 144 log.Debug("bring-link-up") 145 if err := c.Link.SetUp(intf); err != nil { 146 log.Error("bring-link-up", err) 147 return &LinkUpError{err, intf, "host"} 148 } 149 150 return nil 151 } 152 153 type ContainerConfig struct { 154 Hostname string 155 ContainerIntf string 156 ContainerIP net.IP 157 GatewayIP net.IP 158 Subnet *net.IPNet 159 Mtu int 160 } 161 162 func (c *NetworkConfigurer) ConfigureContainer(config *ContainerConfig) error { 163 if err := c.configureLoopbackIntf(); err != nil { 164 return err 165 } 166 167 if err := c.configureContainerIntf( 168 config.ContainerIntf, 169 config.ContainerIP, 170 config.GatewayIP, 171 config.Subnet, 172 config.Mtu, 173 ); err != nil { 174 return err 175 } 176 177 return c.Hostname.SetHostname(config.Hostname) 178 } 179 180 func (c *NetworkConfigurer) configureContainerIntf(name string, ip, gatewayIP net.IP, subnet *net.IPNet, mtu int) (err error) { 181 var found bool 182 var intf *net.Interface 183 if intf, found, err = c.Link.InterfaceByName(name); !found || err != nil { 184 return &FindLinkError{err, "container", name} 185 } 186 187 if err := c.Link.AddIP(intf, ip, subnet); err != nil { 188 return &ConfigureLinkError{err, "container", intf, ip, subnet} 189 } 190 191 if err := c.Link.SetUp(intf); err != nil { 192 return &LinkUpError{err, intf, "container"} 193 } 194 195 if err := c.Link.AddDefaultGW(intf, gatewayIP); err != nil { 196 return &ConfigureDefaultGWError{err, intf, gatewayIP} 197 } 198 199 if err := c.Link.SetMTU(intf, mtu); err != nil { 200 return &MTUError{err, intf, mtu} 201 } 202 203 return nil 204 } 205 206 func (c *NetworkConfigurer) configureLoopbackIntf() (err error) { 207 var found bool 208 var lo *net.Interface 209 if lo, found, err = c.Link.InterfaceByName("lo"); !found || err != nil { 210 return &FindLinkError{err, "loopback", "lo"} 211 } 212 213 ip, subnet, err := net.ParseCIDR("127.0.0.1/8") 214 if err != nil { 215 panic("can't parse 127.0.0.1/8 as a CIDR") // cant happen 216 } 217 218 if err := c.Link.AddIP(lo, ip, subnet); err != nil { 219 return &ConfigureLinkError{err, "loopback", lo, ip, subnet} 220 } 221 222 if err := c.Link.SetUp(lo); err != nil { 223 return &LinkUpError{err, lo, "loopback"} 224 } 225 226 return nil 227 }