Vendoring libnetwork v0.7.0-dev.5
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
0771230daa
commit
5a65408941
47 changed files with 1215 additions and 273 deletions
|
@ -29,14 +29,14 @@ clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
|
|||
clone git github.com/imdario/mergo 0.2.1
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork v0.7.0-dev.3
|
||||
clone git github.com/docker/libnetwork v0.7.0-dev.5
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||
clone git github.com/hashicorp/serf 7151adcef72687bf95f451a2e0ba15cb19412bf2
|
||||
clone git github.com/docker/libkv c2aac5dbbaa5c872211edea7c0f32b3bd67e7410
|
||||
clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
|
||||
clone git github.com/vishvananda/netlink bfd70f556483c008636b920dda142fdaa0d59ef9
|
||||
clone git github.com/vishvananda/netlink 631962935bff4f3d20ff32a72e8944f6d2836a26
|
||||
clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
|
||||
clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
|
||||
clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
|
||||
|
|
|
@ -1432,7 +1432,7 @@ func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
|
|||
c.Assert(waitRun("second"), check.IsNil)
|
||||
out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "www.google.com")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(out, checker.Contains, "100% packet loss")
|
||||
c.Assert(out, checker.Contains, "ping: bad address")
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
# Changelog
|
||||
|
||||
## 0.7.0-dev.5 (2016-03-08)
|
||||
- Fixes https://github.com/docker/docker/issues/20847
|
||||
- Fixes https://github.com/docker/docker/issues/20997
|
||||
- Fixes issues unveiled by docker integ test over 0.7.0-dev.4
|
||||
|
||||
## 0.7.0-dev.4 (2016-03-07)
|
||||
- Changed ownership of exposed ports and port-mapping options from Endpoint to Sandbox
|
||||
- Implement DNS RR in the Docker embedded DNS server
|
||||
- Fixes https://github.com/docker/libnetwork/issues/984 (multi container overlay veth leak)
|
||||
- Libnetwork to program container's interface MAC address
|
||||
- Fixed bug in iptables.Exists() logic
|
||||
- Fixes https://github.com/docker/docker/issues/20694
|
||||
- Source external DNS queries from container namespace
|
||||
- Added inbuilt nil IPAM driver
|
||||
- Windows drivers integration fixes
|
||||
- Extract hostname from (hostname.domainname). Related to https://github.com/docker/docker/issues/14282
|
||||
- Fixed race in sandbox statistics read
|
||||
- Fixes https://github.com/docker/libnetwork/issues/892 (docker start fails when ipv6.disable=1)
|
||||
- Fixed error message on bridge network creation conflict
|
||||
|
||||
## 0.7.0-dev.3 (2016-02-17)
|
||||
- Fixes https://github.com/docker/docker/issues/20350
|
||||
- Fixes https://github.com/docker/docker/issues/20145
|
||||
|
@ -90,7 +110,7 @@
|
|||
- DEPRECATE service discovery from default bridge network
|
||||
- Introduced new network UX
|
||||
- Support for multiple networks in bridge driver
|
||||
- Local persistance with boltdb
|
||||
- Local persistence with boltdb
|
||||
|
||||
## 0.4.0 (2015-07-24)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"mrjana",
|
||||
"mavenugo",
|
||||
"sanimej",
|
||||
"chenchun",
|
||||
]
|
||||
|
||||
[people]
|
||||
|
@ -37,6 +38,11 @@
|
|||
Email = "lk4d4@docker.com"
|
||||
GitHub = "LK4D4"
|
||||
|
||||
[people.chenchun]
|
||||
Name = "Chun Chen"
|
||||
Email = "ramichen@tencent.com"
|
||||
GitHub = "chenchun"
|
||||
|
||||
[people.icecrime]
|
||||
Name = "Arnaud Porterie"
|
||||
Email = "arnaud@docker.com"
|
||||
|
|
|
@ -163,7 +163,7 @@ func (s *sequence) toByteArray() ([]byte, error) {
|
|||
func (s *sequence) fromByteArray(data []byte) error {
|
||||
l := len(data)
|
||||
if l%12 != 0 {
|
||||
return fmt.Errorf("cannot deserialize byte sequence of lenght %d (%v)", l, data)
|
||||
return fmt.Errorf("cannot deserialize byte sequence of length %d (%v)", l, data)
|
||||
}
|
||||
|
||||
p := s
|
||||
|
|
|
@ -170,7 +170,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||
|
||||
if c.cfg != nil && c.cfg.Cluster.Watcher != nil {
|
||||
if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil {
|
||||
// Failing to initalize discovery is a bad situation to be in.
|
||||
// Failing to initialize discovery is a bad situation to be in.
|
||||
// But it cannot fail creating the Controller
|
||||
log.Errorf("Failed to Initialize Discovery : %v", err)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ type DataStore interface {
|
|||
DeleteObjectAtomic(kvObject KVObject) error
|
||||
// DeleteTree deletes a record
|
||||
DeleteTree(kvObject KVObject) error
|
||||
// Watchable returns whether the store is watchable are not
|
||||
// Watchable returns whether the store is watchable or not
|
||||
Watchable() bool
|
||||
// Watch for changes on a KVObject
|
||||
Watch(kvObject KVObject, stopCh <-chan struct{}) (<-chan KVObject, error)
|
||||
|
|
|
@ -3,7 +3,6 @@ package libnetwork
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
|
@ -28,15 +27,15 @@ var procGwNetwork = make(chan (bool), 1)
|
|||
- its deleted when an endpoint with GW joins the container
|
||||
*/
|
||||
|
||||
func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
||||
var createOptions []EndpointOption
|
||||
c := srcEp.getNetwork().getController()
|
||||
func (sb *sandbox) setupDefaultGW() error {
|
||||
|
||||
// check if the conitainer already has a GW endpoint
|
||||
if ep := sb.getEndpointInGWNetwork(); ep != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := sb.controller
|
||||
|
||||
// Look for default gw network. In case of error (includes not found),
|
||||
// retry and create it if needed in a serialized execution.
|
||||
n, err := c.NetworkByName(libnGWNetwork)
|
||||
|
@ -46,19 +45,7 @@ func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
|||
}
|
||||
}
|
||||
|
||||
if opt, ok := srcEp.generic[netlabel.PortMap]; ok {
|
||||
if pb, ok := opt.([]types.PortBinding); ok {
|
||||
createOptions = append(createOptions, CreateOptionPortMapping(pb))
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := srcEp.generic[netlabel.ExposedPorts]; ok {
|
||||
if exp, ok := opt.([]types.TransportPort); ok {
|
||||
createOptions = append(createOptions, CreateOptionExposedPorts(exp))
|
||||
}
|
||||
}
|
||||
|
||||
createOptions = append(createOptions, CreateOptionAnonymous())
|
||||
createOptions := []EndpointOption{CreateOptionAnonymous()}
|
||||
|
||||
eplen := gwEPlen
|
||||
if len(sb.containerID) < gwEPlen {
|
||||
|
@ -74,9 +61,13 @@ func (sb *sandbox) setupDefaultGW(srcEp *endpoint) error {
|
|||
if err := epLocal.sbJoin(sb); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// If present, removes the endpoint connecting the sandbox to the default gw network.
|
||||
// Unless it is the endpoint designated to provide the external connectivity.
|
||||
// If the sandbox is being deleted, removes the endpoint unconditionally.
|
||||
func (sb *sandbox) clearDefaultGW() error {
|
||||
var ep *endpoint
|
||||
|
||||
|
@ -84,6 +75,10 @@ func (sb *sandbox) clearDefaultGW() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if ep == sb.getGatewayEndpoint() && !sb.inDelete {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ep.sbLeave(sb, false); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
@ -98,7 +93,7 @@ func (sb *sandbox) needDefaultGW() bool {
|
|||
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.endpointInGWNetwork() {
|
||||
continue
|
||||
return false
|
||||
}
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
|
@ -165,3 +160,16 @@ func (c *controller) defaultGwNetwork() (Network, error) {
|
|||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Returns the endpoint which is providing external connectivity to the sandbox
|
||||
func (sb *sandbox) getGatewayEndpoint() *endpoint {
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
}
|
||||
if len(ep.Gateway()) != 0 {
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ type DiscoveryType int
|
|||
const (
|
||||
// NodeDiscovery represents Node join/leave events provided by discovery
|
||||
NodeDiscovery = iota + 1
|
||||
// DatastoreConfig represents a add/remove datastore event
|
||||
// DatastoreConfig represents an add/remove datastore event
|
||||
DatastoreConfig
|
||||
)
|
||||
|
||||
|
|
|
@ -42,6 +42,14 @@ type Driver interface {
|
|||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
Leave(nid, eid string) error
|
||||
|
||||
// ProgramExternalConnectivity invokes the driver method which does the necessary
|
||||
// programming to allow the external connectivity dictated by the passed options
|
||||
ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error
|
||||
|
||||
// RevokeExternalConnectivity aks the driver to remove any external connectivity
|
||||
// programming that was done so far
|
||||
RevokeExternalConnectivity(nid, eid string) error
|
||||
|
||||
// Type returns the the type of this driver, the network type this driver manages
|
||||
Type() string
|
||||
}
|
||||
|
@ -88,8 +96,8 @@ type JoinInfo interface {
|
|||
// SetGatewayIPv6 sets the default IPv6 gateway when a container joins the endpoint.
|
||||
SetGatewayIPv6(net.IP) error
|
||||
|
||||
// AddStaticRoute adds a routes to the sandbox.
|
||||
// It may be used in addtion to or instead of a default gateway (as above).
|
||||
// AddStaticRoute adds a route to the sandbox.
|
||||
// It may be used in addition to or instead of a default gateway (as above).
|
||||
AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error
|
||||
|
||||
// DisableGatewayService tells libnetwork not to provide Default GW for the container
|
||||
|
|
|
@ -64,7 +64,7 @@ func (i *IPAMData) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Validate checks wheter the IPAMData structure contains congruent data
|
||||
// Validate checks whether the IPAMData structure contains congruent data
|
||||
func (i *IPAMData) Validate() error {
|
||||
var isV6 bool
|
||||
if i.Pool == nil {
|
||||
|
@ -93,7 +93,7 @@ func (i *IPAMData) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// IsV6 returns wheter this is an IPv6 IPAMData structure
|
||||
// IsV6 returns whether this is an IPv6 IPAMData structure
|
||||
func (i *IPAMData) IsV6() bool {
|
||||
return nil == i.Pool.IP.To4()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/docker/libnetwork/netlabel"
|
||||
|
||||
builtinIpam "github.com/docker/libnetwork/ipams/builtin"
|
||||
nullIpam "github.com/docker/libnetwork/ipams/null"
|
||||
remoteIpam "github.com/docker/libnetwork/ipams/remote"
|
||||
)
|
||||
|
||||
|
@ -73,6 +74,7 @@ func initIpams(ic ipamapi.Callback, lDs, gDs interface{}) error {
|
|||
for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
|
||||
builtinIpam.Init,
|
||||
remoteIpam.Init,
|
||||
nullIpam.Init,
|
||||
} {
|
||||
if err := fn(ic, lDs, gDs); err != nil {
|
||||
return err
|
||||
|
|
|
@ -74,9 +74,7 @@ type networkConfiguration struct {
|
|||
|
||||
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type endpointConfiguration struct {
|
||||
MacAddress net.HardwareAddr
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
MacAddress net.HardwareAddr
|
||||
}
|
||||
|
||||
// containerConfiguration represents the user specified configuration for a container
|
||||
|
@ -85,6 +83,12 @@ type containerConfiguration struct {
|
|||
ChildEndpoints []string
|
||||
}
|
||||
|
||||
// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity
|
||||
type connectivityConfiguration struct {
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
type bridgeEndpoint struct {
|
||||
id string
|
||||
srcName string
|
||||
|
@ -93,6 +97,7 @@ type bridgeEndpoint struct {
|
|||
macAddress net.HardwareAddr
|
||||
config *endpointConfiguration // User specified parameters
|
||||
containerConfig *containerConfiguration
|
||||
extConnConfig *connectivityConfiguration
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
}
|
||||
|
||||
|
@ -183,7 +188,7 @@ func (c *networkConfiguration) Conflicts(o *networkConfiguration) error {
|
|||
return fmt.Errorf("same configuration")
|
||||
}
|
||||
|
||||
// Also empty, becasue only one network with empty name is allowed
|
||||
// Also empty, because only one network with empty name is allowed
|
||||
if c.BridgeName == o.BridgeName {
|
||||
return fmt.Errorf("networks have same bridge name")
|
||||
}
|
||||
|
@ -450,7 +455,7 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
|
|||
|
||||
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||
if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
|
||||
return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets")
|
||||
return types.ForbiddenErrorf("bridge driver doesn't support multiple subnets")
|
||||
}
|
||||
|
||||
if len(ipamV4Data) == 0 {
|
||||
|
@ -543,6 +548,9 @@ func (d *driver) getNetworks() []*bridgeNetwork {
|
|||
|
||||
// Create a new network using bridge plugin
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
||||
return types.BadRequestErrorf("ipv4 pool is empty")
|
||||
}
|
||||
// Sanity checks
|
||||
d.Lock()
|
||||
if _, ok := d.networks[id]; ok {
|
||||
|
@ -581,7 +589,7 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
|
|||
nw.Unlock()
|
||||
if err := nwConfig.Conflicts(config); err != nil {
|
||||
return types.ForbiddenErrorf("cannot create network %s (%s): conflicts with network %s (%s): %s",
|
||||
nwConfig.BridgeName, config.ID, nw.id, nw.config.BridgeName, err.Error())
|
||||
config.ID, config.BridgeName, nwConfig.ID, nwConfig.BridgeName, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,28 +956,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
}
|
||||
|
||||
// Create the sandbox side pipe interface
|
||||
// Store the sandbox side pipe interface parameters
|
||||
endpoint.srcName = containerIfName
|
||||
endpoint.macAddress = ifInfo.MacAddress()
|
||||
endpoint.addr = ifInfo.Address()
|
||||
endpoint.addrv6 = ifInfo.AddressIPv6()
|
||||
|
||||
// Down the interface before configuring mac address.
|
||||
if err = netlink.LinkSetDown(sbox); err != nil {
|
||||
return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
|
||||
// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||
// Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||
if endpoint.macAddress == nil {
|
||||
endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP)
|
||||
if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
||||
if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
||||
}
|
||||
|
||||
// Up the host interface after finishing all netlink configuration
|
||||
if err = netlink.LinkSetUp(host); err != nil {
|
||||
|
@ -996,17 +995,11 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
}
|
||||
|
||||
endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask}
|
||||
if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
||||
if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Program any required port mapping and store them in the endpoint
|
||||
endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1061,9 +1054,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|||
}
|
||||
}()
|
||||
|
||||
// Remove port mappings. Do not stop endpoint delete on unmap failure
|
||||
n.releasePorts(ep)
|
||||
|
||||
// Try removal of link. Discard error: it is a best effort.
|
||||
// Also make sure defer does not see this error either.
|
||||
if link, err := netlink.LinkByName(ep.srcName); err == nil {
|
||||
|
@ -1104,10 +1094,10 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
|||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
if ep.config.ExposedPorts != nil {
|
||||
if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil {
|
||||
// Return a copy of the config data
|
||||
epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
|
||||
for _, tp := range ep.config.ExposedPorts {
|
||||
epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts))
|
||||
for _, tp := range ep.extConnConfig.ExposedPorts {
|
||||
epc = append(epc, tp.GetCopy())
|
||||
}
|
||||
m[netlabel.ExposedPorts] = epc
|
||||
|
@ -1147,6 +1137,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
endpoint.containerConfig, err = parseContainerOptions(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iNames := jinfo.InterfaceName()
|
||||
err = iNames.SetNames(endpoint.srcName, containerVethPrefix)
|
||||
if err != nil {
|
||||
|
@ -1163,10 +1158,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, options, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1189,32 +1180,87 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, nil, false)
|
||||
if err = d.link(network, endpoint, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options map[string]interface{}, enable bool) error {
|
||||
var (
|
||||
cc *containerConfiguration
|
||||
err error
|
||||
)
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
if enable {
|
||||
cc, err = parseContainerOptions(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
cc = endpoint.containerConfig
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint == nil {
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
endpoint.extConnConfig, err = parseConnectivityOptions(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Program any required port mapping and store them in the endpoint
|
||||
endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !network.config.EnableICC {
|
||||
return d.link(network, endpoint, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if endpoint == nil {
|
||||
return EndpointNotFoundError(eid)
|
||||
}
|
||||
|
||||
err = network.releasePorts(endpoint)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error {
|
||||
var err error
|
||||
|
||||
cc := endpoint.containerConfig
|
||||
if cc == nil {
|
||||
return nil
|
||||
}
|
||||
ec := endpoint.extConnConfig
|
||||
if ec == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if endpoint.config != nil && endpoint.config.ExposedPorts != nil {
|
||||
if ec.ExposedPorts != nil {
|
||||
for _, p := range cc.ParentEndpoints {
|
||||
var parentEndpoint *bridgeEndpoint
|
||||
parentEndpoint, err = network.getEndpoint(p)
|
||||
|
@ -1228,7 +1274,7 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
|
||||
l := newLink(parentEndpoint.addr.IP.String(),
|
||||
endpoint.addr.IP.String(),
|
||||
endpoint.config.ExposedPorts, network.config.BridgeName)
|
||||
ec.ExposedPorts, network.config.BridgeName)
|
||||
if enable {
|
||||
err = l.Enable()
|
||||
if err != nil {
|
||||
|
@ -1255,13 +1301,13 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
err = InvalidEndpointIDError(c)
|
||||
return err
|
||||
}
|
||||
if childEndpoint.config == nil || childEndpoint.config.ExposedPorts == nil {
|
||||
if childEndpoint.extConnConfig == nil || childEndpoint.extConnConfig.ExposedPorts == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
l := newLink(endpoint.addr.IP.String(),
|
||||
childEndpoint.addr.IP.String(),
|
||||
childEndpoint.config.ExposedPorts, network.config.BridgeName)
|
||||
childEndpoint.extConnConfig.ExposedPorts, network.config.BridgeName)
|
||||
if enable {
|
||||
err = l.Enable()
|
||||
if err != nil {
|
||||
|
@ -1277,10 +1323,6 @@ func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, options
|
|||
}
|
||||
}
|
||||
|
||||
if enable {
|
||||
endpoint.containerConfig = cc
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1313,22 +1355,6 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
|
|||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
ec.PortBindings = bs
|
||||
} else {
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
ec.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
|
@ -1354,6 +1380,32 @@ func parseContainerOptions(cOptions map[string]interface{}) (*containerConfigura
|
|||
}
|
||||
}
|
||||
|
||||
func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) {
|
||||
if cOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
cc := &connectivityConfiguration{}
|
||||
|
||||
if opt, ok := cOptions[netlabel.PortMap]; ok {
|
||||
if pb, ok := opt.([]types.PortBinding); ok {
|
||||
cc.PortBindings = pb
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt)
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := cOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
cc.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt)
|
||||
}
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr {
|
||||
if epConfig != nil && epConfig.MacAddress != nil {
|
||||
return epConfig.MacAddress
|
||||
|
|
|
@ -14,8 +14,8 @@ var (
|
|||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if epConfig == nil || epConfig.PortBindings == nil {
|
||||
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, ep *bridg
|
|||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
return n.allocatePortsInternal(epConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
return n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
|
|
|
@ -63,6 +63,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
|
|
@ -63,6 +63,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func setFilters(cname, brName string, remove bool) error {
|
|||
opt = "-D"
|
||||
}
|
||||
|
||||
// Everytime we set filters for a new subnet make sure to move the global overlay hook to the top of the both the OUTPUT and forward chains
|
||||
// Every time we set filters for a new subnet make sure to move the global overlay hook to the top of the both the OUTPUT and forward chains
|
||||
if !remove {
|
||||
for _, chain := range []string{"OUTPUT", "FORWARD"} {
|
||||
exists := iptables.Exists(iptables.Filter, chain, "-j", globalChain)
|
||||
|
|
|
@ -54,7 +54,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
return err
|
||||
}
|
||||
|
||||
ep.ifName = overlayIfName
|
||||
ep.ifName = containerIfName
|
||||
|
||||
// Set the container interface and its peer MTU to 1450 to allow
|
||||
// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
|
||||
|
|
|
@ -63,6 +63,9 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
|||
if id == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
||||
return types.BadRequestErrorf("ipv4 pool is empty")
|
||||
}
|
||||
|
||||
// Since we perform lazy configuration make sure we try
|
||||
// configuring the driver when we enter CreateNetwork
|
||||
|
@ -111,6 +114,14 @@ func (d *driver) DeleteNetwork(nid string) error {
|
|||
return n.releaseVxlanID()
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) incEndpointCount() {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
|
|
@ -153,6 +153,29 @@ type LeaveResponse struct {
|
|||
Response
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityRequest describes the API for programming the external connectivity for the given endpoint.
|
||||
type ProgramExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityResponse is the answer to ProgramExternalConnectivityRequest.
|
||||
type ProgramExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityRequest describes the API for revoking the external connectivity for the given endpoint.
|
||||
type RevokeExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityResponse is the answer to RevokeExternalConnectivityRequest.
|
||||
type RevokeExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// DiscoveryNotification represents a discovery notification
|
||||
type DiscoveryNotification struct {
|
||||
DiscoveryType discoverapi.DiscoveryType
|
||||
|
|
|
@ -3,6 +3,7 @@ package remote
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
|
@ -13,6 +14,10 @@ import (
|
|||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
missingMethod = "404 page not found"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
endpoint *plugins.Client
|
||||
networkType string
|
||||
|
@ -247,6 +252,35 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return d.call("Leave", leave, &api.LeaveResponse{})
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivity is invoked to program the rules to allow external connectivity for the endpoint.
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
data := &api.ProgramExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
Options: options,
|
||||
}
|
||||
err := d.call("ProgramExternalConnectivity", data, &api.ProgramExternalConnectivityResponse{})
|
||||
if err != nil && strings.Contains(err.Error(), missingMethod) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivity method is invoked to remove any external connectivity programming related to the endpoint.
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
data := &api.RevokeExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
err := d.call("RevokeExternalConnectivity", data, &api.RevokeExternalConnectivityResponse{})
|
||||
if err != nil && strings.Contains(err.Error(), missingMethod) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.networkType
|
||||
}
|
||||
|
|
|
@ -36,11 +36,20 @@ type networkConfiguration struct {
|
|||
RDID string
|
||||
}
|
||||
|
||||
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type endpointConfiguration struct {
|
||||
MacAddress net.HardwareAddr
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
type hnsEndpoint struct {
|
||||
id string
|
||||
profileID string
|
||||
macAddress net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
id string
|
||||
profileID string
|
||||
macAddress net.HardwareAddr
|
||||
config *endpointConfiguration // User specified parameters
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
addr *net.IPNet
|
||||
}
|
||||
|
||||
type hnsNetwork struct {
|
||||
|
@ -58,7 +67,7 @@ type driver struct {
|
|||
}
|
||||
|
||||
func isValidNetworkType(networkType string) bool {
|
||||
if "L2Bridge" == networkType || "L2Tunnel" == networkType || "NAT" == networkType || "Transparent" == networkType {
|
||||
if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "transparent" == networkType {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -126,7 +135,7 @@ func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string
|
|||
|
||||
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||
if len(ipamV6Data) > 0 {
|
||||
return types.ForbiddenErrorf("windowsshim driver doesnt support v6 subnets")
|
||||
return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
|
||||
}
|
||||
|
||||
if len(ipamV4Data) == 0 {
|
||||
|
@ -177,8 +186,11 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
|||
|
||||
for _, ipData := range ipV4Data {
|
||||
subnet := hcsshim.Subnet{
|
||||
AddressPrefix: ipData.Pool.String(),
|
||||
GatewayAddress: ipData.Gateway.IP.String(),
|
||||
AddressPrefix: ipData.Pool.String(),
|
||||
}
|
||||
|
||||
if ipData.Gateway != nil {
|
||||
subnet.GatewayAddress = ipData.Gateway.IP.String()
|
||||
}
|
||||
|
||||
subnets = append(subnets, subnet)
|
||||
|
@ -276,6 +288,64 @@ func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, e
|
|||
return pbs, nil
|
||||
}
|
||||
|
||||
func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
|
||||
var bindings []types.PortBinding
|
||||
hcsPolicy := &hcsshim.NatPolicy{}
|
||||
|
||||
for _, elem := range policies {
|
||||
|
||||
if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
|
||||
continue
|
||||
}
|
||||
|
||||
binding := types.PortBinding{
|
||||
HostPort: hcsPolicy.ExternalPort,
|
||||
HostPortEnd: hcsPolicy.ExternalPort,
|
||||
Port: hcsPolicy.InternalPort,
|
||||
Proto: types.ParseProtocol(hcsPolicy.Protocol),
|
||||
HostIP: net.IPv4(0, 0, 0, 0),
|
||||
}
|
||||
|
||||
bindings = append(bindings, binding)
|
||||
}
|
||||
|
||||
return bindings, nil
|
||||
}
|
||||
|
||||
func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
|
||||
if epOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ec := &endpointConfiguration{}
|
||||
|
||||
if opt, ok := epOptions[netlabel.MacAddress]; ok {
|
||||
if mac, ok := opt.(net.HardwareAddr); ok {
|
||||
ec.MacAddress = mac
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
ec.PortBindings = bs
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
ec.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
|
@ -292,16 +362,16 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
VirtualNetwork: n.config.HnsID,
|
||||
}
|
||||
|
||||
// Convert the port mapping for the network
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
endpointStruct.Policies, err = convertPortBindings(bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Invalid endpoint configuration for endpoint id%s", eid)
|
||||
}
|
||||
ec, err := parseEndpointOptions(epOptions)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpointStruct.Policies, err = convertPortBindings(ec.PortBindings)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(endpointStruct)
|
||||
|
@ -325,7 +395,16 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
|||
addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
|
||||
macAddress: mac,
|
||||
}
|
||||
|
||||
endpoint.profileID = hnsresponse.Id
|
||||
endpoint.config = ec
|
||||
endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies)
|
||||
|
||||
if err != nil {
|
||||
hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
|
||||
return err
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
n.endpoints[eid] = endpoint
|
||||
n.Unlock()
|
||||
|
@ -365,13 +444,34 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
ep, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[string]interface{}, 1)
|
||||
data["hnsid"] = endpoint.profileID
|
||||
data["hnsid"] = ep.profileID
|
||||
if ep.config.ExposedPorts != nil {
|
||||
// Return a copy of the config data
|
||||
epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
|
||||
for _, tp := range ep.config.ExposedPorts {
|
||||
epc = append(epc, tp.GetCopy())
|
||||
}
|
||||
data[netlabel.ExposedPorts] = epc
|
||||
}
|
||||
|
||||
if ep.portMapping != nil {
|
||||
// Return a copy of the operational data
|
||||
pmc := make([]types.PortBinding, 0, len(ep.portMapping))
|
||||
for _, pm := range ep.portMapping {
|
||||
pmc = append(pmc, pm.GetCopy())
|
||||
}
|
||||
data[netlabel.PortMap] = pmc
|
||||
}
|
||||
|
||||
if len(ep.macAddress) != 0 {
|
||||
data[netlabel.MacAddress] = ep.macAddress
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
|
@ -412,6 +512,14 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.name
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
func getInitializers() []initializer {
|
||||
return []initializer{
|
||||
{null.Init, "null"},
|
||||
{windows.GetInit("Transparent"), "Transparent"},
|
||||
{windows.GetInit("L2Bridge"), "L2Bridge"},
|
||||
{windows.GetInit("L2Tunnel"), "L2Tunnel"},
|
||||
{windows.GetInit("NAT"), "NAT"},
|
||||
{windows.GetInit("transparent"), "transparent"},
|
||||
{windows.GetInit("l2bridge"), "l2bridge"},
|
||||
{windows.GetInit("l2tunnel"), "l2tunnel"},
|
||||
{windows.GetInit("nat"), "nat"},
|
||||
}
|
||||
}
|
||||
|
|
138
vendor/src/github.com/docker/libnetwork/endpoint.go
vendored
138
vendor/src/github.com/docker/libnetwork/endpoint.go
vendored
|
@ -359,22 +359,16 @@ func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
|
|||
sb.joinLeaveStart()
|
||||
defer sb.joinLeaveEnd()
|
||||
|
||||
return ep.sbJoin(sbox, options...)
|
||||
return ep.sbJoin(sb, options...)
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
||||
var err error
|
||||
sb, ok := sbox.(*sandbox)
|
||||
if !ok {
|
||||
return types.BadRequestErrorf("not a valid Sandbox interface")
|
||||
}
|
||||
|
||||
network, err := ep.getNetworkFromStore()
|
||||
func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network from store during join: %v", err)
|
||||
}
|
||||
|
||||
ep, err = network.getEndpointFromStore(ep.ID())
|
||||
ep, err = n.getEndpointFromStore(ep.ID())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get endpoint from store during join: %v", err)
|
||||
}
|
||||
|
@ -384,11 +378,8 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
ep.Unlock()
|
||||
return types.ForbiddenErrorf("another container is attached to the same network endpoint")
|
||||
}
|
||||
ep.Unlock()
|
||||
|
||||
ep.Lock()
|
||||
ep.network = network
|
||||
ep.sandboxID = sbox.ID()
|
||||
ep.network = n
|
||||
ep.sandboxID = sb.ID()
|
||||
ep.joinInfo = &endpointJoinInfo{}
|
||||
epid := ep.id
|
||||
ep.Unlock()
|
||||
|
@ -400,32 +391,29 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
}
|
||||
}()
|
||||
|
||||
network.Lock()
|
||||
nid := network.id
|
||||
network.Unlock()
|
||||
nid := n.ID()
|
||||
|
||||
ep.processOptions(options...)
|
||||
|
||||
driver, err := network.driver(true)
|
||||
d, err := n.driver(true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to join endpoint: %v", err)
|
||||
}
|
||||
|
||||
err = driver.Join(nid, epid, sbox.Key(), ep, sbox.Labels())
|
||||
err = d.Join(nid, epid, sb.Key(), ep, sb.Labels())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
// Do not alter global err variable, it's needed by the previous defer
|
||||
if err := driver.Leave(nid, epid); err != nil {
|
||||
if err := d.Leave(nid, epid); err != nil {
|
||||
log.Warnf("driver leave failed while rolling back join: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Watch for service records
|
||||
network.getController().watchSvcRecord(ep)
|
||||
n.getController().watchSvcRecord(ep)
|
||||
|
||||
address := ""
|
||||
if ip := ep.getFirstInterfaceAddress(); ip != nil {
|
||||
|
@ -434,27 +422,23 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
if err = sb.updateHostsFile(address); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = sb.updateDNS(network.enableIPv6); err != nil {
|
||||
if err = sb.updateDNS(n.enableIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = network.getController().updateToStore(ep); err != nil {
|
||||
if err = n.getController().updateToStore(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Current endpoint providing external connectivity for the sandbox
|
||||
extEp := sb.getGatewayEndpoint()
|
||||
|
||||
sb.Lock()
|
||||
heap.Push(&sb.endpoints, ep)
|
||||
sb.Unlock()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
for i, e := range sb.getConnectedEndpoints() {
|
||||
if e == ep {
|
||||
sb.Lock()
|
||||
heap.Remove(&sb.endpoints, i)
|
||||
sb.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
sb.removeEndpoint(ep)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -463,9 +447,39 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
|
|||
}
|
||||
|
||||
if sb.needDefaultGW() {
|
||||
return sb.setupDefaultGW(ep)
|
||||
return sb.setupDefaultGW()
|
||||
}
|
||||
return nil
|
||||
|
||||
moveExtConn := sb.getGatewayEndpoint() != extEp
|
||||
|
||||
if moveExtConn {
|
||||
if extEp != nil {
|
||||
log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
||||
if err = d.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
|
||||
return types.InternalErrorf(
|
||||
"driver failed revoking external connectivity on endpoint %s (%s): %v",
|
||||
extEp.Name(), extEp.ID(), err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if e := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
|
||||
log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
|
||||
extEp.Name(), extEp.ID(), e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
if !n.internal {
|
||||
log.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
||||
if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
|
||||
return types.InternalErrorf(
|
||||
"driver failed programming external connectivity on endpoint %s (%s): %v",
|
||||
ep.Name(), ep.ID(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.clearDefaultGW()
|
||||
}
|
||||
|
||||
func (ep *endpoint) rename(name string) error {
|
||||
|
@ -533,15 +547,10 @@ func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
|
|||
sb.joinLeaveStart()
|
||||
defer sb.joinLeaveEnd()
|
||||
|
||||
return ep.sbLeave(sbox, false, options...)
|
||||
return ep.sbLeave(sb, false, options...)
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption) error {
|
||||
sb, ok := sbox.(*sandbox)
|
||||
if !ok {
|
||||
return types.BadRequestErrorf("not a valid Sandbox interface")
|
||||
}
|
||||
|
||||
func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) error {
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network from store during leave: %v", err)
|
||||
|
@ -559,8 +568,8 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
if sid == "" {
|
||||
return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
|
||||
}
|
||||
if sid != sbox.ID() {
|
||||
return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sbox.ID())
|
||||
if sid != sb.ID() {
|
||||
return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID())
|
||||
}
|
||||
|
||||
ep.processOptions(options...)
|
||||
|
@ -575,7 +584,19 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
ep.network = n
|
||||
ep.Unlock()
|
||||
|
||||
// Current endpoint providing external connectivity to the sandbox
|
||||
extEp := sb.getGatewayEndpoint()
|
||||
moveExtConn := extEp != nil && (extEp.ID() == ep.ID())
|
||||
|
||||
if d != nil {
|
||||
if moveExtConn {
|
||||
log.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
||||
if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
|
||||
log.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
|
||||
ep.Name(), ep.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.Leave(n.id, ep.id); err != nil {
|
||||
if _, ok := err.(types.MaskableError); !ok {
|
||||
log.Warnf("driver error disconnecting container %s : %v", ep.name, err)
|
||||
|
@ -597,7 +618,24 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
|
|||
}
|
||||
|
||||
sb.deleteHostsEntries(n.getSvcRecords(ep))
|
||||
return nil
|
||||
if !sb.inDelete && sb.needDefaultGW() {
|
||||
if sb.getEPwithoutGateway() == nil {
|
||||
return fmt.Errorf("endpoint without GW expected, but not found")
|
||||
}
|
||||
return sb.setupDefaultGW()
|
||||
}
|
||||
|
||||
// New endpoint providing external connectivity for the sandbox
|
||||
extEp = sb.getGatewayEndpoint()
|
||||
if moveExtConn && extEp != nil {
|
||||
log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
||||
if err := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
|
||||
log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
|
||||
extEp.Name(), extEp.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return sb.clearDefaultGW()
|
||||
}
|
||||
|
||||
func (n *network) validateForceDelete(locator string) error {
|
||||
|
@ -643,7 +681,7 @@ func (ep *endpoint) Delete(force bool) error {
|
|||
}
|
||||
|
||||
if sb != nil {
|
||||
if e := ep.sbLeave(sb, force); e != nil {
|
||||
if e := ep.sbLeave(sb.(*sandbox), force); e != nil {
|
||||
log.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
|
||||
}
|
||||
}
|
||||
|
@ -929,9 +967,13 @@ func (ep *endpoint) releaseAddress() {
|
|||
log.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
|
||||
return
|
||||
}
|
||||
if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
|
||||
log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
|
||||
|
||||
if ep.iface.addr != nil {
|
||||
if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
|
||||
log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
|
||||
if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
|
||||
log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@ -78,10 +79,17 @@ func Build(path, IP, hostname, domainname string, extraContent []Record) error {
|
|||
//set main record
|
||||
var mainRec Record
|
||||
mainRec.IP = IP
|
||||
// User might have provided a FQDN in hostname or split it across hostname
|
||||
// and domainname. We want the FQDN and the bare hostname.
|
||||
fqdn := hostname
|
||||
if domainname != "" {
|
||||
mainRec.Hosts = fmt.Sprintf("%s.%s %s", hostname, domainname, hostname)
|
||||
fqdn = fmt.Sprintf("%s.%s", fqdn, domainname)
|
||||
}
|
||||
parts := strings.SplitN(fqdn, ".", 2)
|
||||
if len(parts) == 2 {
|
||||
mainRec.Hosts = fmt.Sprintf("%s %s", fqdn, parts[0])
|
||||
} else {
|
||||
mainRec.Hosts = hostname
|
||||
mainRec.Hosts = fqdn
|
||||
}
|
||||
if _, err := mainRec.WriteTo(content); err != nil {
|
||||
return err
|
||||
|
@ -151,6 +159,10 @@ func Delete(path string, recs []Record) error {
|
|||
loop:
|
||||
for s.Scan() {
|
||||
b := s.Bytes()
|
||||
if len(b) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if b[0] == '#' {
|
||||
buf.Write(b)
|
||||
buf.Write(eol)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/docker/libnetwork/datastore"
|
||||
)
|
||||
|
||||
// Idm manages the reservation/release of numerical ids from a contiguos set
|
||||
// Idm manages the reservation/release of numerical ids from a contiguous set
|
||||
type Idm struct {
|
||||
start uint64
|
||||
end uint64
|
||||
|
|
|
@ -40,7 +40,7 @@ type addrSpace struct {
|
|||
}
|
||||
|
||||
// AddressRange specifies first and last ip ordinal which
|
||||
// identify a range in a a pool of addresses
|
||||
// identifies a range in a pool of addresses
|
||||
type AddressRange struct {
|
||||
Sub *net.IPNet
|
||||
Start, End uint64
|
||||
|
@ -85,7 +85,7 @@ func (s *SubnetKey) String() string {
|
|||
return k
|
||||
}
|
||||
|
||||
// FromString populate the SubnetKey object reading it from string
|
||||
// FromString populates the SubnetKey object reading it from string
|
||||
func (s *SubnetKey) FromString(str string) error {
|
||||
if str == "" || !strings.Contains(str, "/") {
|
||||
return types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
|
||||
|
|
|
@ -62,7 +62,7 @@ func getAddressVersion(ip net.IP) ipVersion {
|
|||
}
|
||||
|
||||
// Adds the ordinal IP to the current array
|
||||
// 192.168.0.0 + 53 => 192.168.53
|
||||
// 192.168.0.0 + 53 => 192.168.0.53
|
||||
func addIntToIP(array []byte, ordinal uint64) {
|
||||
for i := len(array) - 1; i >= 0; i-- {
|
||||
array[i] |= (byte)(ordinal & 0xff)
|
||||
|
|
|
@ -15,6 +15,8 @@ import (
|
|||
const (
|
||||
// DefaultIPAM is the name of the built-in default ipam driver
|
||||
DefaultIPAM = "default"
|
||||
// NullIPAM is the name of the built-in null ipam driver
|
||||
NullIPAM = "null"
|
||||
// PluginEndpointType represents the Endpoint Type used by Plugin system
|
||||
PluginEndpointType = "IpamDriver"
|
||||
// RequestAddressType represents the Address Type used when requesting an address
|
||||
|
@ -33,7 +35,7 @@ type Callback interface {
|
|||
* IPAM Errors
|
||||
**************/
|
||||
|
||||
// Weel-known errors returned by IPAM
|
||||
// Well-known errors returned by IPAM
|
||||
var (
|
||||
ErrIpamInternalError = types.InternalErrorf("IPAM Internal Error")
|
||||
ErrInvalidAddressSpace = types.BadRequestErrorf("Invalid Address Space")
|
||||
|
|
71
vendor/src/github.com/docker/libnetwork/ipams/null/null.go
vendored
Normal file
71
vendor/src/github.com/docker/libnetwork/ipams/null/null.go
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Package null implements the null ipam driver. Null ipam driver satisfies ipamapi contract,
|
||||
// but does not effectively reserve/allocate any address pool or address
|
||||
package null
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultAS = "null"
|
||||
defaultPool, _ = types.ParseCIDR("0.0.0.0/0")
|
||||
defaultPoolID = fmt.Sprintf("%s/%s", defaultAS, defaultPool.String())
|
||||
)
|
||||
|
||||
type allocator struct{}
|
||||
|
||||
func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
|
||||
return defaultAS, defaultAS, nil
|
||||
}
|
||||
|
||||
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
||||
if addressSpace != defaultAS {
|
||||
return "", nil, nil, types.BadRequestErrorf("unknown address space: %s", addressSpace)
|
||||
}
|
||||
if pool != "" {
|
||||
return "", nil, nil, types.BadRequestErrorf("null ipam driver does not handle specific address pool requests")
|
||||
}
|
||||
if subPool != "" {
|
||||
return "", nil, nil, types.BadRequestErrorf("null ipam driver does not handle specific address subpool requests")
|
||||
}
|
||||
if v6 {
|
||||
return "", nil, nil, types.BadRequestErrorf("null ipam driver does not handle IPv6 address pool pool requests")
|
||||
}
|
||||
return defaultPoolID, defaultPool, nil, nil
|
||||
}
|
||||
|
||||
func (a *allocator) ReleasePool(poolID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *allocator) RequestAddress(poolID string, ip net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
|
||||
if poolID != defaultPoolID {
|
||||
return nil, nil, types.BadRequestErrorf("unknown pool id: %s", poolID)
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func (a *allocator) ReleaseAddress(poolID string, ip net.IP) error {
|
||||
if poolID != defaultPoolID {
|
||||
return types.BadRequestErrorf("unknown pool id: %s", poolID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init registers a remote ipam when its plugin is activated
|
||||
func Init(ic ipamapi.Callback, l, g interface{}) error {
|
||||
return ic.RegisterIpamDriver(ipamapi.NullIPAM, &allocator{})
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
|
@ -33,7 +34,7 @@ func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
|
|||
}
|
||||
|
||||
// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the
|
||||
// subnet user asked and does not validate anything. Doesnt support subpool allocation
|
||||
// subnet user asked and does not validate anything. Doesn't support subpool allocation
|
||||
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
||||
log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
||||
if subPool != "" || v6 {
|
||||
|
@ -64,14 +65,19 @@ func (a *allocator) ReleasePool(poolID string) error {
|
|||
// RequestAddress returns an address from the specified pool ID.
|
||||
// Always allocate the 0.0.0.0/32 ip if no preferred address was specified
|
||||
func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
|
||||
log.Debugf("RequestAddress(%s, %v, %v) %s", poolID, prefAddress, opts, opts["RequestAddressType"])
|
||||
log.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
|
||||
_, ipNet, err := net.ParseCIDR(poolID)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if prefAddress == nil {
|
||||
|
||||
// TODO Windows: Remove this once the bug in docker daemon is fixed
|
||||
// that causes it to throw an exception on nil gateway
|
||||
if opts[ipamapi.RequestAddressType] == netlabel.Gateway {
|
||||
return ipNet, nil, nil
|
||||
} else if prefAddress == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -36,6 +37,7 @@ const (
|
|||
var (
|
||||
iptablesPath string
|
||||
supportsXlock = false
|
||||
supportsCOpt = false
|
||||
// used to lock iptables commands if xtables lock is not supported
|
||||
bestEffortLock sync.Mutex
|
||||
// ErrIptablesNotFound is returned when the rule is not found.
|
||||
|
@ -60,7 +62,6 @@ func (e ChainError) Error() string {
|
|||
}
|
||||
|
||||
func initCheck() error {
|
||||
|
||||
if iptablesPath == "" {
|
||||
path, err := exec.LookPath("iptables")
|
||||
if err != nil {
|
||||
|
@ -68,6 +69,12 @@ func initCheck() error {
|
|||
}
|
||||
iptablesPath = path
|
||||
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
|
||||
mj, mn, mc, err := GetVersion()
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to read iptables version: %v", err)
|
||||
return nil
|
||||
}
|
||||
supportsCOpt = supportsCOption(mj, mn, mc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -299,20 +306,21 @@ func Exists(table Table, chain string, rule ...string) bool {
|
|||
table = Filter
|
||||
}
|
||||
|
||||
// iptables -C, --check option was added in v.1.4.11
|
||||
// http://ftp.netfilter.org/pub/iptables/changes-iptables-1.4.11.txt
|
||||
initCheck()
|
||||
|
||||
// try -C
|
||||
// if exit status is 0 then return true, the rule exists
|
||||
if _, err := Raw(append([]string{
|
||||
"-t", string(table), "-C", chain}, rule...)...); err == nil {
|
||||
return true
|
||||
if supportsCOpt {
|
||||
// if exit status is 0 then return true, the rule exists
|
||||
_, err := Raw(append([]string{"-t", string(table), "-C", chain}, rule...)...)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// parse "iptables -S" for the rule (this checks rules in a specific chain
|
||||
// in a specific table)
|
||||
ruleString := strings.Join(rule, " ")
|
||||
ruleString = chain + " " + ruleString
|
||||
// parse "iptables -S" for the rule (it checks rules in a specific chain
|
||||
// in a specific table and it is very unreliable)
|
||||
return existsRaw(table, chain, rule...)
|
||||
}
|
||||
|
||||
func existsRaw(table Table, chain string, rule ...string) bool {
|
||||
ruleString := fmt.Sprintf("%s %s\n", chain, strings.Join(rule, " "))
|
||||
existingRules, _ := exec.Command(iptablesPath, "-t", string(table), "-S", chain).Output()
|
||||
|
||||
return strings.Contains(string(existingRules), ruleString)
|
||||
|
@ -380,3 +388,25 @@ func ExistChain(chain string, table Table) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetVersion reads the iptables version numbers
|
||||
func GetVersion() (major, minor, micro int, err error) {
|
||||
out, err := Raw("--version")
|
||||
if err == nil {
|
||||
major, minor, micro = parseVersionNumbers(string(out))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseVersionNumbers(input string) (major, minor, micro int) {
|
||||
re := regexp.MustCompile(`v\d*.\d*.\d*`)
|
||||
line := re.FindString(input)
|
||||
fmt.Sscanf(line, "v%d.%d.%d", &major, &minor, µ)
|
||||
return
|
||||
}
|
||||
|
||||
// iptables -C, --check option was added in v.1.4.11
|
||||
// http://ftp.netfilter.org/pub/iptables/changes-iptables-1.4.11.txt
|
||||
func supportsCOption(mj, mn, mc int) bool {
|
||||
return mj > 1 || (mj == 1 && (mn > 4 || (mn == 4 && mc >= 11)))
|
||||
}
|
||||
|
|
|
@ -600,7 +600,7 @@ func (n *network) driver(load bool) (driverapi.Driver, error) {
|
|||
return nil, err
|
||||
}
|
||||
} else if !ok {
|
||||
// dont fail if driver loading is not required
|
||||
// don't fail if driver loading is not required
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -851,14 +851,25 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
|
|||
if iface := ep.Iface(); iface.Address() != nil {
|
||||
myAliases := ep.MyAliases()
|
||||
if isAdd {
|
||||
if !ep.isAnonymous() {
|
||||
// If anonymous endpoint has an alias use the first alias
|
||||
// for ip->name mapping. Not having the reverse mapping
|
||||
// breaks some apps
|
||||
if ep.isAnonymous() {
|
||||
if len(myAliases) > 0 {
|
||||
n.addSvcRecords(myAliases[0], iface.Address().IP, true)
|
||||
}
|
||||
} else {
|
||||
n.addSvcRecords(epName, iface.Address().IP, true)
|
||||
}
|
||||
for _, alias := range myAliases {
|
||||
n.addSvcRecords(alias, iface.Address().IP, false)
|
||||
}
|
||||
} else {
|
||||
if !ep.isAnonymous() {
|
||||
if ep.isAnonymous() {
|
||||
if len(myAliases) > 0 {
|
||||
n.deleteSvcRecords(myAliases[0], iface.Address().IP, true)
|
||||
}
|
||||
} else {
|
||||
n.deleteSvcRecords(epName, iface.Address().IP, true)
|
||||
}
|
||||
for _, alias := range myAliases {
|
||||
|
|
|
@ -21,6 +21,7 @@ type nwIface struct {
|
|||
dstName string
|
||||
master string
|
||||
dstMaster string
|
||||
mac net.HardwareAddr
|
||||
address *net.IPNet
|
||||
addressIPv6 *net.IPNet
|
||||
routes []*net.IPNet
|
||||
|
@ -64,6 +65,13 @@ func (i *nwIface) Master() string {
|
|||
return i.master
|
||||
}
|
||||
|
||||
func (i *nwIface) MacAddress() net.HardwareAddr {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
return types.GetMacCopy(i.mac)
|
||||
}
|
||||
|
||||
func (i *nwIface) Address() *net.IPNet {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
@ -304,6 +312,7 @@ func configureInterface(iface netlink.Link, i *nwIface) error {
|
|||
ErrMessage string
|
||||
}{
|
||||
{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())},
|
||||
{setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC to %q", ifaceName, i.MacAddress())},
|
||||
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %q", ifaceName, i.Address())},
|
||||
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %q", ifaceName, i.AddressIPv6())},
|
||||
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
||||
|
@ -326,6 +335,13 @@ func setInterfaceMaster(iface netlink.Link, i *nwIface) error {
|
|||
LinkAttrs: netlink.LinkAttrs{Name: i.DstMaster()}})
|
||||
}
|
||||
|
||||
func setInterfaceMAC(iface netlink.Link, i *nwIface) error {
|
||||
if i.MacAddress() == nil {
|
||||
return nil
|
||||
}
|
||||
return netlink.LinkSetHardwareAddr(iface, i.MacAddress())
|
||||
}
|
||||
|
||||
func setInterfaceIP(iface netlink.Link, i *nwIface) error {
|
||||
if i.Address() == nil {
|
||||
return nil
|
||||
|
|
|
@ -42,6 +42,12 @@ func (n *networkNamespace) Master(name string) IfaceOption {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *networkNamespace) MacAddress(mac net.HardwareAddr) IfaceOption {
|
||||
return func(i *nwIface) {
|
||||
i.mac = mac
|
||||
}
|
||||
}
|
||||
|
||||
func (n *networkNamespace) Address(addr *net.IPNet) IfaceOption {
|
||||
return func(i *nwIface) {
|
||||
i.address = addr
|
||||
|
|
|
@ -76,6 +76,9 @@ type IfaceOptionSetter interface {
|
|||
// Bridge returns an option setter to set if the interface is a bridge.
|
||||
Bridge(bool) IfaceOption
|
||||
|
||||
// MacAddress returns an option setter to set the MAC address.
|
||||
MacAddress(net.HardwareAddr) IfaceOption
|
||||
|
||||
// Address returns an option setter to set IPv4 address.
|
||||
Address(*net.IPNet) IfaceOption
|
||||
|
||||
|
|
176
vendor/src/github.com/docker/libnetwork/resolver.go
vendored
176
vendor/src/github.com/docker/libnetwork/resolver.go
vendored
|
@ -2,8 +2,11 @@ package libnetwork
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
|
@ -31,23 +34,35 @@ type Resolver interface {
|
|||
}
|
||||
|
||||
const (
|
||||
resolverIP = "127.0.0.11"
|
||||
dnsPort = "53"
|
||||
ptrIPv4domain = ".in-addr.arpa."
|
||||
ptrIPv6domain = ".ip6.arpa."
|
||||
respTTL = 600
|
||||
maxExtDNS = 3 //max number of external servers to try
|
||||
resolverIP = "127.0.0.11"
|
||||
dnsPort = "53"
|
||||
ptrIPv4domain = ".in-addr.arpa."
|
||||
ptrIPv6domain = ".ip6.arpa."
|
||||
respTTL = 600
|
||||
maxExtDNS = 3 //max number of external servers to try
|
||||
extIOTimeout = 3 * time.Second
|
||||
defaultRespSize = 512
|
||||
)
|
||||
|
||||
type extDNSEntry struct {
|
||||
ipStr string
|
||||
extConn net.Conn
|
||||
extOnce sync.Once
|
||||
}
|
||||
|
||||
// resolver implements the Resolver interface
|
||||
type resolver struct {
|
||||
sb *sandbox
|
||||
extDNS []string
|
||||
server *dns.Server
|
||||
conn *net.UDPConn
|
||||
tcpServer *dns.Server
|
||||
tcpListen *net.TCPListener
|
||||
err error
|
||||
sb *sandbox
|
||||
extDNSList [maxExtDNS]extDNSEntry
|
||||
server *dns.Server
|
||||
conn *net.UDPConn
|
||||
tcpServer *dns.Server
|
||||
tcpListen *net.TCPListener
|
||||
err error
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
// NewResolver creates a new instance of the Resolver
|
||||
|
@ -136,7 +151,13 @@ func (r *resolver) Stop() {
|
|||
}
|
||||
|
||||
func (r *resolver) SetExtServers(dns []string) {
|
||||
r.extDNS = dns
|
||||
l := len(dns)
|
||||
if l > maxExtDNS {
|
||||
l = maxExtDNS
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
r.extDNSList[i].ipStr = dns[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resolver) NameServer() string {
|
||||
|
@ -151,22 +172,36 @@ func setCommonFlags(msg *dns.Msg) {
|
|||
msg.RecursionAvailable = true
|
||||
}
|
||||
|
||||
func shuffleAddr(addr []net.IP) []net.IP {
|
||||
for i := len(addr) - 1; i > 0; i-- {
|
||||
r := rand.Intn(i + 1)
|
||||
addr[i], addr[r] = addr[r], addr[i]
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) {
|
||||
addr := r.sb.ResolveName(name)
|
||||
if addr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Debugf("Lookup for %s: IP %s", name, addr.String())
|
||||
log.Debugf("Lookup for %s: IP %v", name, addr)
|
||||
|
||||
resp := new(dns.Msg)
|
||||
resp.SetReply(query)
|
||||
setCommonFlags(resp)
|
||||
|
||||
rr := new(dns.A)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
rr.A = addr
|
||||
resp.Answer = append(resp.Answer, rr)
|
||||
if len(addr) > 1 {
|
||||
addr = shuffleAddr(addr)
|
||||
}
|
||||
|
||||
for _, ip := range addr {
|
||||
rr := new(dns.A)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
rr.A = ip
|
||||
resp.Answer = append(resp.Answer, rr)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
@ -200,10 +235,23 @@ func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error)
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func truncateResp(resp *dns.Msg, maxSize int, isTCP bool) {
|
||||
if !isTCP {
|
||||
resp.Truncated = true
|
||||
}
|
||||
|
||||
// trim the Answer RRs one by one till the whole message fits
|
||||
// within the reply size
|
||||
for resp.Len() > maxSize {
|
||||
resp.Answer = resp.Answer[:len(resp.Answer)-1]
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
||||
var (
|
||||
resp *dns.Msg
|
||||
err error
|
||||
extConn net.Conn
|
||||
resp *dns.Msg
|
||||
err error
|
||||
)
|
||||
|
||||
if query == nil || len(query.Question) == 0 {
|
||||
|
@ -221,28 +269,82 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
return
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
if len(r.extDNS) == 0 {
|
||||
return
|
||||
proto := w.LocalAddr().Network()
|
||||
maxSize := 0
|
||||
if proto == "tcp" {
|
||||
maxSize = dns.MaxMsgSize - 1
|
||||
} else if proto == "udp" {
|
||||
optRR := query.IsEdns0()
|
||||
if optRR != nil {
|
||||
maxSize = int(optRR.UDPSize())
|
||||
}
|
||||
|
||||
num := maxExtDNS
|
||||
if len(r.extDNS) < maxExtDNS {
|
||||
num = len(r.extDNS)
|
||||
if maxSize < defaultRespSize {
|
||||
maxSize = defaultRespSize
|
||||
}
|
||||
for i := 0; i < num; i++ {
|
||||
log.Debugf("Querying ext dns %s:%s for %s[%d]", w.LocalAddr().Network(), r.extDNS[i], name, query.Question[0].Qtype)
|
||||
}
|
||||
|
||||
c := &dns.Client{Net: w.LocalAddr().Network()}
|
||||
addr := fmt.Sprintf("%s:%d", r.extDNS[i], 53)
|
||||
|
||||
resp, _, err = c.Exchange(query, addr)
|
||||
if err == nil {
|
||||
resp.Compress = true
|
||||
if resp != nil {
|
||||
if resp.Len() > maxSize {
|
||||
truncateResp(resp, maxSize, proto == "tcp")
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < maxExtDNS; i++ {
|
||||
extDNS := &r.extDNSList[i]
|
||||
if extDNS.ipStr == "" {
|
||||
break
|
||||
}
|
||||
log.Errorf("external resolution failed, %s", err)
|
||||
log.Debugf("Querying ext dns %s:%s for %s[%d]", proto, extDNS.ipStr, name, query.Question[0].Qtype)
|
||||
|
||||
extConnect := func() {
|
||||
addr := fmt.Sprintf("%s:%d", extDNS.ipStr, 53)
|
||||
extConn, err = net.DialTimeout(proto, addr, extIOTimeout)
|
||||
}
|
||||
|
||||
// For udp clients connection is persisted to reuse for further queries.
|
||||
// Accessing extDNS.extConn be a race here between go rouines. Hence the
|
||||
// connection setup is done in a Once block and fetch the extConn again
|
||||
extConn = extDNS.extConn
|
||||
if extConn == nil || proto == "tcp" {
|
||||
if proto == "udp" {
|
||||
extDNS.extOnce.Do(func() {
|
||||
r.sb.execFunc(extConnect)
|
||||
extDNS.extConn = extConn
|
||||
})
|
||||
extConn = extDNS.extConn
|
||||
} else {
|
||||
r.sb.execFunc(extConnect)
|
||||
}
|
||||
if err != nil {
|
||||
log.Debugf("Connect failed, %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Timeout has to be set for every IO operation.
|
||||
extConn.SetDeadline(time.Now().Add(extIOTimeout))
|
||||
co := &dns.Conn{Conn: extConn}
|
||||
|
||||
defer func() {
|
||||
if proto == "tcp" {
|
||||
co.Close()
|
||||
}
|
||||
}()
|
||||
err = co.WriteMsg(query)
|
||||
if err != nil {
|
||||
log.Debugf("Send to DNS server failed, %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
resp, err = co.ReadMsg()
|
||||
if err != nil {
|
||||
log.Debugf("Read from DNS server failed, %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
resp.Compress = true
|
||||
break
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
return
|
||||
}
|
||||
|
|
105
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
105
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -37,7 +38,7 @@ type Sandbox interface {
|
|||
Delete() error
|
||||
// ResolveName searches for the service name in the networks to which the sandbox
|
||||
// is connected to.
|
||||
ResolveName(name string) net.IP
|
||||
ResolveName(name string) []net.IP
|
||||
// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
|
||||
// notation; the format used for DNS PTR records
|
||||
ResolveIP(name string) string
|
||||
|
@ -118,6 +119,7 @@ type containerConfig struct {
|
|||
useDefaultSandBox bool
|
||||
useExternalKey bool
|
||||
prio int // higher the value, more the priority
|
||||
exposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
func (sb *sandbox) ID() string {
|
||||
|
@ -136,18 +138,27 @@ func (sb *sandbox) Key() string {
|
|||
}
|
||||
|
||||
func (sb *sandbox) Labels() map[string]interface{} {
|
||||
return sb.config.generic
|
||||
sb.Lock()
|
||||
sb.Unlock()
|
||||
opts := make(map[string]interface{}, len(sb.config.generic))
|
||||
for k, v := range sb.config.generic {
|
||||
opts[k] = v
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (sb *sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) {
|
||||
m := make(map[string]*types.InterfaceStatistics)
|
||||
|
||||
if sb.osSbox == nil {
|
||||
sb.Lock()
|
||||
osb := sb.osSbox
|
||||
sb.Unlock()
|
||||
if osb == nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
for _, i := range sb.osSbox.Info().Interfaces() {
|
||||
for _, i := range osb.Info().Interfaces() {
|
||||
if m[i.DstName()], err = i.Statistics(); err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
@ -326,6 +337,18 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint {
|
|||
return eps
|
||||
}
|
||||
|
||||
func (sb *sandbox) removeEndpoint(ep *endpoint) {
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
|
||||
for i, e := range sb.endpoints {
|
||||
if e == ep {
|
||||
heap.Remove(&sb.endpoints, i)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sb *sandbox) getEndpoint(id string) *endpoint {
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
|
@ -391,8 +414,12 @@ func (sb *sandbox) ResolveIP(ip string) string {
|
|||
return svc
|
||||
}
|
||||
|
||||
func (sb *sandbox) ResolveName(name string) net.IP {
|
||||
var ip net.IP
|
||||
func (sb *sandbox) execFunc(f func()) {
|
||||
sb.osSbox.InvokeFunc(f)
|
||||
}
|
||||
|
||||
func (sb *sandbox) ResolveName(name string) []net.IP {
|
||||
var ip []net.IP
|
||||
|
||||
// Embedded server owns the docker network domain. Resolution should work
|
||||
// for both container_name and container_name.network_name
|
||||
|
@ -440,7 +467,7 @@ func (sb *sandbox) ResolveName(name string) net.IP {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) net.IP {
|
||||
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) []net.IP {
|
||||
for _, ep := range epList {
|
||||
name := req
|
||||
n := ep.getNetwork()
|
||||
|
@ -463,7 +490,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
|||
}
|
||||
} else {
|
||||
// If it is a regular lookup and if the requested name is an alias
|
||||
// dont perform a svc lookup for this endpoint.
|
||||
// don't perform a svc lookup for this endpoint.
|
||||
ep.Lock()
|
||||
if _, ok := ep.aliases[req]; ok {
|
||||
ep.Unlock()
|
||||
|
@ -481,7 +508,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
|||
ip, ok := sr.svcMap[name]
|
||||
n.Unlock()
|
||||
if ok {
|
||||
return ip[0]
|
||||
return ip
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -606,6 +633,9 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
|||
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
|
||||
}
|
||||
if i.mac != nil {
|
||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
|
||||
}
|
||||
|
||||
if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
|
||||
return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
|
||||
|
@ -621,14 +651,9 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
|||
}
|
||||
}
|
||||
|
||||
for _, gwep := range sb.getConnectedEndpoints() {
|
||||
if len(gwep.Gateway()) > 0 {
|
||||
if gwep != ep {
|
||||
break
|
||||
}
|
||||
if err := sb.updateGateway(gwep); err != nil {
|
||||
return err
|
||||
}
|
||||
if ep == sb.getGatewayEndpoint() {
|
||||
if err := sb.updateGateway(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +672,7 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
|
|||
ep := sb.getEndpoint(origEp.id)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find the sandbox endpoint data for endpoint %s",
|
||||
ep.name)
|
||||
origEp.id)
|
||||
}
|
||||
|
||||
sb.Lock()
|
||||
|
@ -739,6 +764,13 @@ func (sb *sandbox) joinLeaveEnd() {
|
|||
}
|
||||
}
|
||||
|
||||
func (sb *sandbox) hasPortConfigs() bool {
|
||||
opts := sb.Labels()
|
||||
_, hasExpPorts := opts[netlabel.ExposedPorts]
|
||||
_, hasPortMaps := opts[netlabel.PortMap]
|
||||
return hasExpPorts || hasPortMaps
|
||||
}
|
||||
|
||||
// OptionHostname function returns an option setter for hostname option to
|
||||
// be passed to NewSandbox method.
|
||||
func OptionHostname(name string) SandboxOption {
|
||||
|
@ -848,7 +880,42 @@ func OptionUseExternalKey() SandboxOption {
|
|||
// net container creation method. Container Labels are a good example.
|
||||
func OptionGeneric(generic map[string]interface{}) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
sb.config.generic = generic
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{}, len(generic))
|
||||
}
|
||||
for k, v := range generic {
|
||||
sb.config.generic[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OptionExposedPorts function returns an option setter for the container exposed
|
||||
// ports option to be passed to container Create method.
|
||||
func OptionExposedPorts(exposedPorts []types.TransportPort) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{})
|
||||
}
|
||||
// Defensive copy
|
||||
eps := make([]types.TransportPort, len(exposedPorts))
|
||||
copy(eps, exposedPorts)
|
||||
// Store endpoint label and in generic because driver needs it
|
||||
sb.config.exposedPorts = eps
|
||||
sb.config.generic[netlabel.ExposedPorts] = eps
|
||||
}
|
||||
}
|
||||
|
||||
// OptionPortMapping function returns an option setter for the mapping
|
||||
// ports option to be passed to container Create method.
|
||||
func OptionPortMapping(portBindings []types.PortBinding) SandboxOption {
|
||||
return func(sb *sandbox) {
|
||||
if sb.config.generic == nil {
|
||||
sb.config.generic = make(map[string]interface{})
|
||||
}
|
||||
// Store a copy of the bindings as generic data to pass to the driver
|
||||
pbs := make([]types.PortBinding, len(portBindings))
|
||||
copy(pbs, portBindings)
|
||||
sb.config.generic[netlabel.PortMap] = pbs
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ func (c *controller) acceptClientConnections(sock string, l net.Listener) {
|
|||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
if _, err1 := os.Stat(sock); os.IsNotExist(err1) {
|
||||
logrus.Debugf("Unix socket %s doesnt exist. cannot accept client connections", sock)
|
||||
logrus.Debugf("Unix socket %s doesn't exist. cannot accept client connections", sock)
|
||||
return
|
||||
}
|
||||
logrus.Errorf("Error accepting connection %v", err)
|
||||
|
|
|
@ -389,7 +389,7 @@ const (
|
|||
// NEXTHOP indicates a StaticRoute with an IP next hop.
|
||||
NEXTHOP = iota
|
||||
|
||||
// CONNECTED indicates a StaticRoute with a interface for directly connected peers.
|
||||
// CONNECTED indicates a StaticRoute with an interface for directly connected peers.
|
||||
CONNECTED
|
||||
)
|
||||
|
||||
|
@ -458,25 +458,25 @@ type NotFoundError interface {
|
|||
NotFound()
|
||||
}
|
||||
|
||||
// ForbiddenError is an interface for errors which denote an valid request that cannot be honored
|
||||
// ForbiddenError is an interface for errors which denote a valid request that cannot be honored
|
||||
type ForbiddenError interface {
|
||||
// Forbidden makes implementer into ForbiddenError type
|
||||
Forbidden()
|
||||
}
|
||||
|
||||
// NoServiceError is an interface for errors returned when the required service is not available
|
||||
// NoServiceError is an interface for errors returned when the required service is not available
|
||||
type NoServiceError interface {
|
||||
// NoService makes implementer into NoServiceError type
|
||||
NoService()
|
||||
}
|
||||
|
||||
// TimeoutError is an interface for errors raised because of timeout
|
||||
// TimeoutError is an interface for errors raised because of timeout
|
||||
type TimeoutError interface {
|
||||
// Timeout makes implementer into TimeoutError type
|
||||
Timeout()
|
||||
}
|
||||
|
||||
// NotImplementedError is an interface for errors raised because of requested functionality is not yet implemented
|
||||
// NotImplementedError is an interface for errors raised because of requested functionality is not yet implemented
|
||||
type NotImplementedError interface {
|
||||
// NotImplemented makes implementer into NotImplementedError type
|
||||
NotImplemented()
|
||||
|
|
|
@ -101,6 +101,10 @@ func AddrList(link Link, family int) ([]Addr, error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if family != FAMILY_ALL && msg.Family != uint8(family) {
|
||||
continue
|
||||
}
|
||||
|
||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -56,6 +56,7 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass {
|
|||
ceil := cattrs.Ceil / 8
|
||||
buffer := cattrs.Buffer
|
||||
cbuffer := cattrs.Cbuffer
|
||||
|
||||
if ceil == 0 {
|
||||
ceil = rate
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
|
@ -65,15 +66,32 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
|
|||
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
||||
if htb, ok := class.(*HtbClass); ok {
|
||||
opt := nl.TcHtbCopt{}
|
||||
opt.Rate.Rate = uint32(htb.Rate)
|
||||
opt.Ceil.Rate = uint32(htb.Ceil)
|
||||
opt.Buffer = htb.Buffer
|
||||
opt.Cbuffer = htb.Cbuffer
|
||||
opt.Quantum = htb.Quantum
|
||||
opt.Level = htb.Level
|
||||
opt.Prio = htb.Prio
|
||||
// TODO: Handle Debug properly. For now default to 0
|
||||
/* Calculate {R,C}Tab and set Rate and Ceil */
|
||||
cell_log := -1
|
||||
ccell_log := -1
|
||||
linklayer := nl.LINKLAYER_ETHERNET
|
||||
mtu := 1600
|
||||
var rtab [256]uint32
|
||||
var ctab [256]uint32
|
||||
tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)}
|
||||
if CalcRtable(&tcrate, rtab, cell_log, uint32(mtu), linklayer) < 0 {
|
||||
return errors.New("HTB: failed to calculate rate table.")
|
||||
}
|
||||
opt.Rate = tcrate
|
||||
tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)}
|
||||
if CalcRtable(&tcceil, ctab, ccell_log, uint32(mtu), linklayer) < 0 {
|
||||
return errors.New("HTB: failed to calculate ceil rate table.")
|
||||
}
|
||||
opt.Ceil = tcceil
|
||||
nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize())
|
||||
nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab))
|
||||
nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab))
|
||||
}
|
||||
req.AddData(options)
|
||||
return nil
|
||||
|
|
|
@ -204,6 +204,7 @@ type Vxlan struct {
|
|||
RSC bool
|
||||
L2miss bool
|
||||
L3miss bool
|
||||
UDPCSum bool
|
||||
NoAge bool
|
||||
GBP bool
|
||||
Age int
|
||||
|
|
|
@ -142,6 +142,54 @@ func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// LinkSetVfHardwareAddr sets the hardware address of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf mac $hwaddr`
|
||||
func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
|
||||
base := link.Attrs()
|
||||
ensureIndex(base)
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
|
||||
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
||||
vfmsg := nl.VfMac{
|
||||
Vf: uint32(vf),
|
||||
}
|
||||
copy(vfmsg.Mac[:], []byte(hwaddr))
|
||||
nl.NewRtAttrChild(info, nl.IFLA_VF_MAC, vfmsg.Serialize())
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetVfVlan sets the vlan of a vf for the link.
|
||||
// Equivalent to: `ip link set $link vf $vf vlan $vlan`
|
||||
func LinkSetVfVlan(link Link, vf, vlan int) error {
|
||||
base := link.Attrs()
|
||||
ensureIndex(base)
|
||||
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
|
||||
|
||||
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
||||
msg.Index = int32(base.Index)
|
||||
req.AddData(msg)
|
||||
|
||||
data := nl.NewRtAttr(nl.IFLA_VFINFO_LIST, nil)
|
||||
info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
|
||||
vfmsg := nl.VfVlan{
|
||||
Vf: uint32(vf),
|
||||
Vlan: uint32(vlan),
|
||||
}
|
||||
nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
|
||||
req.AddData(data)
|
||||
|
||||
_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// LinkSetMaster sets the master of the link device.
|
||||
// Equivalent to: `ip link set $link master $master`
|
||||
func LinkSetMaster(link Link, master *Bridge) error {
|
||||
|
@ -277,10 +325,12 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
|
|||
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
|
||||
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
|
||||
|
||||
if vxlan.UDPCSum {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
|
||||
}
|
||||
if vxlan.GBP {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, boolAttr(vxlan.GBP))
|
||||
}
|
||||
|
||||
if vxlan.NoAge {
|
||||
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
|
||||
} else if vxlan.Age > 0 {
|
||||
|
@ -815,6 +865,7 @@ func LinkList() ([]Link, error) {
|
|||
// LinkUpdate is used to pass information back from LinkSubscribe()
|
||||
type LinkUpdate struct {
|
||||
nl.IfInfomsg
|
||||
Header syscall.NlMsghdr
|
||||
Link
|
||||
}
|
||||
|
||||
|
@ -844,7 +895,7 @@ func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
ch <- LinkUpdate{IfInfomsg: *ifmsg, Link: link}
|
||||
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: m.Header, Link: link}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -935,6 +986,8 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|||
vxlan.L2miss = int8(datum.Value[0]) != 0
|
||||
case nl.IFLA_VXLAN_L3MISS:
|
||||
vxlan.L3miss = int8(datum.Value[0]) != 0
|
||||
case nl.IFLA_VXLAN_UDP_CSUM:
|
||||
vxlan.UDPCSum = int8(datum.Value[0]) != 0
|
||||
case nl.IFLA_VXLAN_GBP:
|
||||
vxlan.GBP = int8(datum.Value[0]) != 0
|
||||
case nl.IFLA_VXLAN_AGEING:
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package nl
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_CHANGE = 0xFFFFFFFF
|
||||
// doesn't exist in syscall
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -182,3 +188,209 @@ const (
|
|||
GRE_FLAGS = 0x00F8
|
||||
GRE_VERSION = 0x0007
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_INFO_UNSPEC = iota
|
||||
IFLA_VF_INFO
|
||||
IFLA_VF_INFO_MAX = IFLA_VF_INFO
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_UNSPEC = iota
|
||||
IFLA_VF_MAC /* Hardware queue specific attributes */
|
||||
IFLA_VF_VLAN
|
||||
IFLA_VF_TX_RATE /* Max TX Bandwidth Allocation */
|
||||
IFLA_VF_SPOOFCHK /* Spoof Checking on/off switch */
|
||||
IFLA_VF_LINK_STATE /* link state enable/disable/auto switch */
|
||||
IFLA_VF_RATE /* Min and Max TX Bandwidth Allocation */
|
||||
IFLA_VF_RSS_QUERY_EN /* RSS Redirection Table and Hash Key query
|
||||
* on/off switch
|
||||
*/
|
||||
IFLA_VF_STATS /* network device statistics */
|
||||
IFLA_VF_MAX = IFLA_VF_STATS
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_LINK_STATE_AUTO = iota /* link state of the uplink */
|
||||
IFLA_VF_LINK_STATE_ENABLE /* link always up */
|
||||
IFLA_VF_LINK_STATE_DISABLE /* link always down */
|
||||
IFLA_VF_LINK_STATE_MAX = IFLA_VF_LINK_STATE_DISABLE
|
||||
)
|
||||
|
||||
const (
|
||||
IFLA_VF_STATS_RX_PACKETS = iota
|
||||
IFLA_VF_STATS_TX_PACKETS
|
||||
IFLA_VF_STATS_RX_BYTES
|
||||
IFLA_VF_STATS_TX_BYTES
|
||||
IFLA_VF_STATS_BROADCAST
|
||||
IFLA_VF_STATS_MULTICAST
|
||||
IFLA_VF_STATS_MAX = IFLA_VF_STATS_MULTICAST
|
||||
)
|
||||
|
||||
const (
|
||||
SizeofVfMac = 0x24
|
||||
SizeofVfVlan = 0x0c
|
||||
SizeofVfTxRate = 0x08
|
||||
SizeofVfRate = 0x0c
|
||||
SizeofVfSpoofchk = 0x08
|
||||
SizeofVfLinkState = 0x08
|
||||
SizeofVfRssQueryEn = 0x08
|
||||
)
|
||||
|
||||
// struct ifla_vf_mac {
|
||||
// __u32 vf;
|
||||
// __u8 mac[32]; /* MAX_ADDR_LEN */
|
||||
// };
|
||||
|
||||
type VfMac struct {
|
||||
Vf uint32
|
||||
Mac [32]byte
|
||||
}
|
||||
|
||||
func (msg *VfMac) Len() int {
|
||||
return SizeofVfMac
|
||||
}
|
||||
|
||||
func DeserializeVfMac(b []byte) *VfMac {
|
||||
return (*VfMac)(unsafe.Pointer(&b[0:SizeofVfMac][0]))
|
||||
}
|
||||
|
||||
func (msg *VfMac) Serialize() []byte {
|
||||
return (*(*[SizeofVfMac]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_vlan {
|
||||
// __u32 vf;
|
||||
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
// __u32 qos;
|
||||
// };
|
||||
|
||||
type VfVlan struct {
|
||||
Vf uint32
|
||||
Vlan uint32
|
||||
Qos uint32
|
||||
}
|
||||
|
||||
func (msg *VfVlan) Len() int {
|
||||
return SizeofVfVlan
|
||||
}
|
||||
|
||||
func DeserializeVfVlan(b []byte) *VfVlan {
|
||||
return (*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0]))
|
||||
}
|
||||
|
||||
func (msg *VfVlan) Serialize() []byte {
|
||||
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_tx_rate {
|
||||
// __u32 vf;
|
||||
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
|
||||
// };
|
||||
|
||||
type VfTxRate struct {
|
||||
Vf uint32
|
||||
Rate uint32
|
||||
}
|
||||
|
||||
func (msg *VfTxRate) Len() int {
|
||||
return SizeofVfTxRate
|
||||
}
|
||||
|
||||
func DeserializeVfTxRate(b []byte) *VfTxRate {
|
||||
return (*VfTxRate)(unsafe.Pointer(&b[0:SizeofVfTxRate][0]))
|
||||
}
|
||||
|
||||
func (msg *VfTxRate) Serialize() []byte {
|
||||
return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_rate {
|
||||
// __u32 vf;
|
||||
// __u32 min_tx_rate; /* Min Bandwidth in Mbps */
|
||||
// __u32 max_tx_rate; /* Max Bandwidth in Mbps */
|
||||
// };
|
||||
|
||||
type VfRate struct {
|
||||
Vf uint32
|
||||
MinTxRate uint32
|
||||
MaxTxRate uint32
|
||||
}
|
||||
|
||||
func (msg *VfRate) Len() int {
|
||||
return SizeofVfRate
|
||||
}
|
||||
|
||||
func DeserializeVfRate(b []byte) *VfRate {
|
||||
return (*VfRate)(unsafe.Pointer(&b[0:SizeofVfRate][0]))
|
||||
}
|
||||
|
||||
func (msg *VfRate) Serialize() []byte {
|
||||
return (*(*[SizeofVfRate]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_spoofchk {
|
||||
// __u32 vf;
|
||||
// __u32 setting;
|
||||
// };
|
||||
|
||||
type VfSpoofchk struct {
|
||||
Vf uint32
|
||||
Setting uint32
|
||||
}
|
||||
|
||||
func (msg *VfSpoofchk) Len() int {
|
||||
return SizeofVfSpoofchk
|
||||
}
|
||||
|
||||
func DeserializeVfSpoofchk(b []byte) *VfSpoofchk {
|
||||
return (*VfSpoofchk)(unsafe.Pointer(&b[0:SizeofVfSpoofchk][0]))
|
||||
}
|
||||
|
||||
func (msg *VfSpoofchk) Serialize() []byte {
|
||||
return (*(*[SizeofVfSpoofchk]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_link_state {
|
||||
// __u32 vf;
|
||||
// __u32 link_state;
|
||||
// };
|
||||
|
||||
type VfLinkState struct {
|
||||
Vf uint32
|
||||
LinkState uint32
|
||||
}
|
||||
|
||||
func (msg *VfLinkState) Len() int {
|
||||
return SizeofVfLinkState
|
||||
}
|
||||
|
||||
func DeserializeVfLinkState(b []byte) *VfLinkState {
|
||||
return (*VfLinkState)(unsafe.Pointer(&b[0:SizeofVfLinkState][0]))
|
||||
}
|
||||
|
||||
func (msg *VfLinkState) Serialize() []byte {
|
||||
return (*(*[SizeofVfLinkState]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
||||
// struct ifla_vf_rss_query_en {
|
||||
// __u32 vf;
|
||||
// __u32 setting;
|
||||
// };
|
||||
|
||||
type VfRssQueryEn struct {
|
||||
Vf uint32
|
||||
Setting uint32
|
||||
}
|
||||
|
||||
func (msg *VfRssQueryEn) Len() int {
|
||||
return SizeofVfRssQueryEn
|
||||
}
|
||||
|
||||
func DeserializeVfRssQueryEn(b []byte) *VfRssQueryEn {
|
||||
return (*VfRssQueryEn)(unsafe.Pointer(&b[0:SizeofVfRssQueryEn][0]))
|
||||
}
|
||||
|
||||
func (msg *VfRssQueryEn) Serialize() []byte {
|
||||
return (*(*[SizeofVfRssQueryEn]byte)(unsafe.Pointer(msg)))[:]
|
||||
}
|
||||
|
|
|
@ -110,9 +110,6 @@ func XfrmStateDel(state *XfrmState) error {
|
|||
func XfrmStateList(family int) ([]XfrmState, error) {
|
||||
req := nl.NewNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)
|
||||
|
||||
msg := nl.NewIfInfomsg(family)
|
||||
req.AddData(msg)
|
||||
|
||||
msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in a new issue