Add bridge and driver code for FreeBSD specifically
This commit is contained in:
parent
3ed6a3a883
commit
027fc3483b
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,384 @@
|
|||
// +build freebsd
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// network config prefix was not specific enough.
|
||||
// To be backward compatible, need custom endpoint
|
||||
// prefix with different root
|
||||
bridgePrefix = "bridge"
|
||||
bridgeEndpointPrefix = "bridge-endpoint"
|
||||
)
|
||||
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
err = d.populateNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.populateEndpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(bridgePrefix), &networkConfiguration{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get bridge network configurations from store: %v", err)
|
||||
}
|
||||
|
||||
// It's normal for network configuration state to be empty. Just return.
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ncfg := kvo.(*networkConfiguration)
|
||||
if err = d.createNetwork(ncfg); err != nil {
|
||||
logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state: %v", ncfg.ID, ncfg.BridgeName, err)
|
||||
}
|
||||
logrus.Debugf("Network (%s) restored", ncfg.ID[0:7])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateEndpoints() error {
|
||||
kvol, err := d.store.List(datastore.Key(bridgeEndpointPrefix), &bridgeEndpoint{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get bridge endpoints from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*bridgeEndpoint)
|
||||
n, ok := d.networks[ep.nid]
|
||||
if !ok {
|
||||
logrus.Debugf("Network (%s) not found for restored bridge endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
||||
logrus.Debugf("Deleting stale bridge endpoint (%s) from store", ep.nid[0:7])
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale bridge endpoint (%s) from store", ep.nid[0:7])
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.endpoints[ep.id] = ep
|
||||
n.restorePortAllocations(ep)
|
||||
logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update bridge store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("bridge store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
nMap["ID"] = ncfg.ID
|
||||
nMap["BridgeName"] = ncfg.BridgeName
|
||||
nMap["BridgeNameInternal"] = ncfg.BridgeNameInternal
|
||||
nMap["EnableIPv6"] = ncfg.EnableIPv6
|
||||
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
|
||||
nMap["EnableICC"] = ncfg.EnableICC
|
||||
nMap["Mtu"] = ncfg.Mtu
|
||||
nMap["Internal"] = ncfg.Internal
|
||||
nMap["DefaultBridge"] = ncfg.DefaultBridge
|
||||
nMap["DefaultBindingIP"] = ncfg.DefaultBindingIP.String()
|
||||
nMap["DefaultBindingIntf"] = ncfg.DefaultBindingIntf
|
||||
nMap["DefaultGatewayIPv4"] = ncfg.DefaultGatewayIPv4.String()
|
||||
nMap["DefaultGatewayIPv6"] = ncfg.DefaultGatewayIPv6.String()
|
||||
|
||||
if ncfg.AddressIPv4 != nil {
|
||||
nMap["AddressIPv4"] = ncfg.AddressIPv4.String()
|
||||
}
|
||||
|
||||
if ncfg.AddressIPv6 != nil {
|
||||
nMap["AddressIPv6"] = ncfg.AddressIPv6.String()
|
||||
}
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv4"]; ok {
|
||||
if ncfg.AddressIPv4, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv4 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv6"]; ok {
|
||||
if ncfg.AddressIPv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv6 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
ncfg.DefaultBridge = nMap["DefaultBridge"].(bool)
|
||||
ncfg.DefaultBindingIP = net.ParseIP(nMap["DefaultBindingIP"].(string))
|
||||
ncfg.DefaultBindingIntf = nMap["DefaultBindingIntf"].(string)
|
||||
ncfg.DefaultGatewayIPv4 = net.ParseIP(nMap["DefaultGatewayIPv4"].(string))
|
||||
ncfg.DefaultGatewayIPv6 = net.ParseIP(nMap["DefaultGatewayIPv6"].(string))
|
||||
ncfg.ID = nMap["ID"].(string)
|
||||
ncfg.BridgeName = nMap["BridgeName"].(string)
|
||||
ncfg.BridgeNameInternal = nMap["BridgeNameInternal"].(string)
|
||||
ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
|
||||
ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
|
||||
ncfg.EnableICC = nMap["EnableICC"].(bool)
|
||||
ncfg.Mtu = int(nMap["Mtu"].(float64))
|
||||
if v, ok := nMap["Internal"]; ok {
|
||||
ncfg.Internal = v.(bool)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Key() []string {
|
||||
return []string{bridgePrefix, ncfg.ID}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) KeyPrefix() []string {
|
||||
return []string{bridgePrefix}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Value() []byte {
|
||||
b, err := json.Marshal(ncfg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ncfg)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Index() uint64 {
|
||||
return ncfg.dbIndex
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetIndex(index uint64) {
|
||||
ncfg.dbIndex = index
|
||||
ncfg.dbExists = true
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Exists() bool {
|
||||
return ncfg.dbExists
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) New() datastore.KVObject {
|
||||
return &networkConfiguration{}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*networkConfiguration)
|
||||
*dstNcfg = *ncfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
epMap["SrcName"] = ep.srcName
|
||||
epMap["MacAddress"] = ep.macAddress.String()
|
||||
epMap["Addr"] = ep.addr.String()
|
||||
if ep.addrv6 != nil {
|
||||
epMap["Addrv6"] = ep.addrv6.String()
|
||||
}
|
||||
epMap["Config"] = ep.config
|
||||
epMap["ContainerConfig"] = ep.containerConfig
|
||||
epMap["ExternalConnConfig"] = ep.extConnConfig
|
||||
epMap["PortMapping"] = ep.portMapping
|
||||
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal to bridge endpoint: %v", err)
|
||||
}
|
||||
|
||||
if v, ok := epMap["MacAddress"]; ok {
|
||||
if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addrv6"]; ok {
|
||||
if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
ep.srcName = epMap["SrcName"].(string)
|
||||
d, _ := json.Marshal(epMap["Config"])
|
||||
if err := json.Unmarshal(d, &ep.config); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint config %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["ContainerConfig"])
|
||||
if err := json.Unmarshal(d, &ep.containerConfig); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint container config %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["ExternalConnConfig"])
|
||||
if err := json.Unmarshal(d, &ep.extConnConfig); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["PortMapping"])
|
||||
if err := json.Unmarshal(d, &ep.portMapping); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint port mapping %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Key() []string {
|
||||
return []string{bridgeEndpointPrefix, ep.id}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) KeyPrefix() []string {
|
||||
return []string{bridgeEndpointPrefix}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) New() datastore.KVObject {
|
||||
return &bridgeEndpoint{}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstEp := o.(*bridgeEndpoint)
|
||||
*dstEp = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) restorePortAllocations(ep *bridgeEndpoint) {
|
||||
if ep.extConnConfig == nil ||
|
||||
ep.extConnConfig.ExposedPorts == nil ||
|
||||
ep.extConnConfig.PortBindings == nil {
|
||||
return
|
||||
}
|
||||
tmp := ep.extConnConfig.PortBindings
|
||||
ep.extConnConfig.PortBindings = ep.portMapping
|
||||
_, err := n.allocatePorts(ep, n.config.DefaultBindingIntf, n.config.DefaultBindingIP, n.driver.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to reserve existing port mapping for endpoint %s:%v", ep.id[0:7], err)
|
||||
}
|
||||
ep.extConnConfig.PortBindings = tmp
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
// +build freebsd
|
||||
package bridge
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when an endpoint create is attempted with an invalid endpoint configuration.
|
||||
type ErrInvalidEndpointConfig struct{}
|
||||
|
||||
func (eiec *ErrInvalidEndpointConfig) Error() string {
|
||||
return "trying to create an endpoint with an invalid endpoint configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eiec *ErrInvalidEndpointConfig) BadRequest() {}
|
||||
|
||||
// ErrNoIPAddr error is returned when bridge has no IPv4 address configured.
|
||||
type ErrNoIPAddr struct{}
|
||||
|
||||
func (enip *ErrNoIPAddr) Error() string {
|
||||
return "bridge has no IPv4 address configured"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (enip *ErrNoIPAddr) InternalError() {}
|
||||
|
||||
// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid.
|
||||
type ErrInvalidGateway struct{}
|
||||
|
||||
func (eig *ErrInvalidGateway) Error() string {
|
||||
return "default gateway ip must be part of the network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eig *ErrInvalidGateway) BadRequest() {}
|
||||
|
||||
// ErrInvalidMtu is returned when the user provided MTU is not valid.
|
||||
type ErrInvalidMtu int
|
||||
|
||||
func (eim ErrInvalidMtu) Error() string {
|
||||
return fmt.Sprintf("invalid MTU number: %d", int(eim))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eim ErrInvalidMtu) BadRequest() {}
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (uat ErrUnsupportedAddressType) BadRequest() {}
|
||||
|
||||
// ActiveEndpointsError is returned when there are
|
||||
// still active endpoints in the network being deleted.
|
||||
type ActiveEndpointsError string
|
||||
|
||||
func (aee ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s has active endpoint", string(aee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// InvalidNetworkIDError is returned when the passed
|
||||
// network id for an existing network is not a known id.
|
||||
type InvalidNetworkIDError string
|
||||
|
||||
func (inie InvalidNetworkIDError) Error() string {
|
||||
return fmt.Sprintf("invalid network id %s", string(inie))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (inie InvalidNetworkIDError) NotFound() {}
|
||||
|
||||
// InvalidEndpointIDError is returned when the passed
|
||||
// endpoint id is not valid.
|
||||
type InvalidEndpointIDError string
|
||||
|
||||
func (ieie InvalidEndpointIDError) Error() string {
|
||||
return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ieie InvalidEndpointIDError) BadRequest() {}
|
||||
|
||||
// EndpointNotFoundError is returned when the no endpoint
|
||||
// with the passed endpoint id is found.
|
||||
type EndpointNotFoundError string
|
||||
|
||||
func (enfe EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enfe EndpointNotFoundError) NotFound() {}
|
||||
|
||||
// NonDefaultBridgeExistError is returned when a non-default
|
||||
// bridge config is passed but it does not already exist.
|
||||
type NonDefaultBridgeExistError string
|
||||
|
||||
func (ndbee NonDefaultBridgeExistError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeExistError) Forbidden() {}
|
||||
|
||||
// NonDefaultBridgeNeedsIPError is returned when a non-default
|
||||
// bridge config is passed but it has no ip configured
|
||||
type NonDefaultBridgeNeedsIPError string
|
||||
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must have a valid IP address", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Forbidden() {}
|
|
@ -0,0 +1,235 @@
|
|||
// +build freebsd
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
//"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
const (
|
||||
maxAllocatePortAttempts = 10
|
||||
)
|
||||
|
||||
func addPFRules(epid, bindIntf string, bs []types.PortBinding) {
|
||||
/*
|
||||
var id string
|
||||
|
||||
if len(epid) > 12 {
|
||||
id = epid[:12]
|
||||
} else {
|
||||
id = epid
|
||||
}
|
||||
|
||||
fname := "/var/lib/docker/network/files/pf." + id
|
||||
|
||||
f, err := os.OpenFile(fname,
|
||||
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
logrus.Warn("cannot open temp pf file")
|
||||
return
|
||||
}
|
||||
for _, b := range bs {
|
||||
r := fmt.Sprintf(
|
||||
"pass in on %s proto %s from any to (%s) "+
|
||||
"port %d rdr-to %s port %d\n", bindIntf,
|
||||
b.Proto.String(), bindIntf, b.HostPort,
|
||||
b.IP.String(), b.Port)
|
||||
_, err = f.WriteString(r)
|
||||
if err != nil {
|
||||
logrus.Warnf("cannot write firewall rules to %s: %v", fname, err)
|
||||
}
|
||||
}
|
||||
f.Close()
|
||||
|
||||
anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
||||
err = exec.Command("/usr/sbin/pfctl", "-a", anchor, "-f", fname).Run()
|
||||
if err != nil {
|
||||
logrus.Warnf("failed to add firewall rules: %v", err)
|
||||
}
|
||||
os.Remove(fname)
|
||||
*/
|
||||
}
|
||||
|
||||
func removePFRules(epid string) {
|
||||
var id string
|
||||
|
||||
if len(epid) > 12 {
|
||||
id = epid[:12]
|
||||
} else {
|
||||
id = epid
|
||||
}
|
||||
|
||||
anchor := fmt.Sprintf("_auto/docker/ep%s", id)
|
||||
err := exec.Command("/usr/sbin/pfctl", "-a", anchor, "-F", "all").Run()
|
||||
if err != nil {
|
||||
logrus.Warnf("failed to remove firewall rules: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, bindIntf string, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
defHostIP := defaultBindingIP
|
||||
if reqDefBindIP != nil {
|
||||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
bs, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, bindIntf, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add PF rules for port bindings, if any
|
||||
if len(bs) > 0 {
|
||||
addPFRules(ep.id, bindIntf, bs)
|
||||
}
|
||||
|
||||
return bs, err
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, bindIntf string, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
bs := make([]types.PortBinding, 0, len(bindings))
|
||||
for _, c := range bindings {
|
||||
b := c.GetCopy()
|
||||
if err := n.allocatePort(&b, containerIP, defHostIP); err != nil {
|
||||
// On allocation failure,release previously
|
||||
// allocated ports. On cleanup error, just log
|
||||
// a warning message
|
||||
if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
||||
logrus.Warnf("Upon allocation failure "+
|
||||
"for %v, failed to clear previously "+
|
||||
"allocated port bindings: %v", b, cuErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP) error {
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
)
|
||||
|
||||
// Store the container interface address in the operational binding
|
||||
bnd.IP = containerIP
|
||||
|
||||
// Adjust the host address in the operational binding
|
||||
if len(bnd.HostIP) == 0 {
|
||||
bnd.HostIP = defHostIP
|
||||
}
|
||||
|
||||
// Adjust HostPortEnd if this is not a range.
|
||||
if bnd.HostPortEnd == 0 {
|
||||
bnd.HostPortEnd = bnd.HostPort
|
||||
}
|
||||
|
||||
/* TODO
|
||||
// Construct the container side transport address
|
||||
container, err := bnd.ContainerAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*/
|
||||
// Try up to maxAllocatePortAttempts times to get a port that's
|
||||
// not already allocated.
|
||||
for i := 0; i < maxAllocatePortAttempts; i++ {
|
||||
/*
|
||||
TODO
|
||||
if host, err = n.portMapper.MapRange(container, bnd.HostIP,
|
||||
int(bnd.HostPort), int(bnd.HostPortEnd), false); err == nil {
|
||||
break
|
||||
}
|
||||
*/
|
||||
// There is no point in immediately retrying to map an
|
||||
// explicitly chosen port.
|
||||
if bnd.HostPort != 0 {
|
||||
logrus.Warnf(
|
||||
"Failed to allocate and map port %d-%d: %s",
|
||||
bnd.HostPort, bnd.HostPortEnd, err)
|
||||
break
|
||||
}
|
||||
logrus.Warnf("Failed to allocate and map port: %s, retry: %d",
|
||||
err, i+1)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save the host port (regardless it was or not specified in the
|
||||
// binding)
|
||||
switch netAddr := host.(type) {
|
||||
case *net.TCPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.TCPAddr).Port)
|
||||
return nil
|
||||
case *net.UDPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.UDPAddr).Port)
|
||||
return nil
|
||||
default:
|
||||
// For completeness
|
||||
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
||||
err := n.releasePortsInternal(ep.portMapping)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// remove rules if there are any port mappings
|
||||
if len(ep.portMapping) > 0 {
|
||||
removePFRules(ep.id)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
|
||||
var errorBuf bytes.Buffer
|
||||
|
||||
// Attempt to release all port bindings, do not stop on failure
|
||||
for _, m := range bindings {
|
||||
if err := n.releasePort(m); err != nil {
|
||||
errorBuf.WriteString(
|
||||
fmt.Sprintf(
|
||||
"\ncould not release %v because of %v",
|
||||
m, err))
|
||||
}
|
||||
}
|
||||
|
||||
if errorBuf.Len() != 0 {
|
||||
return errors.New(errorBuf.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
||||
/*
|
||||
// Construct the host side transport address
|
||||
host, err := bnd.HostAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO
|
||||
return n.portMapper.Unmap(host)
|
||||
*/
|
||||
return nil
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/drivers/freebsd/bridge"
|
||||
"github.com/docker/libnetwork/drivers/null"
|
||||
"github.com/docker/libnetwork/drivers/remote"
|
||||
)
|
||||
|
||||
func getInitializers(experimental bool) []initializer {
|
||||
return []initializer{
|
||||
{bridge.Init, "bridge"},
|
||||
{null.Init, "null"},
|
||||
{remote.Init, "remote"},
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package netutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -19,5 +22,32 @@ func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|||
// FindAvailableNetwork returns a network from the passed list which does not
|
||||
// overlap with existing interfaces in the system
|
||||
func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
|
||||
return nil, types.NotImplementedErrorf("not supported on freebsd")
|
||||
for _, avail := range list {
|
||||
cidr := strings.Split(avail.String(), "/")
|
||||
ipitems := strings.Split(cidr[0], ".")
|
||||
ip := ipitems[0] + "." +
|
||||
ipitems[1] + "." +
|
||||
ipitems[2] + "." + "1"
|
||||
|
||||
out, err := exec.Command("/sbin/route", "get", ip).Output()
|
||||
if err != nil {
|
||||
fmt.Println("failed to run route get command")
|
||||
return nil, err
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, l := range lines {
|
||||
s := strings.Split(string(l), ":")
|
||||
if len(s) == 2 {
|
||||
k, v := s[0], strings.TrimSpace(s[1])
|
||||
if k == "destination" {
|
||||
if v == "default" {
|
||||
return avail, nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no available network")
|
||||
//types.NotImplementedErrorf("not supported on freebsd")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue