|
@@ -3,10 +3,13 @@ package bridge
|
|
import (
|
|
import (
|
|
"errors"
|
|
"errors"
|
|
"fmt"
|
|
"fmt"
|
|
|
|
+ "io/ioutil"
|
|
"net"
|
|
"net"
|
|
"os/exec"
|
|
"os/exec"
|
|
|
|
+ "path/filepath"
|
|
"strconv"
|
|
"strconv"
|
|
"sync"
|
|
"sync"
|
|
|
|
+ "syscall"
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/libnetwork/driverapi"
|
|
"github.com/docker/libnetwork/driverapi"
|
|
@@ -776,6 +779,37 @@ func addToBridge(ifaceName, bridgeName string) error {
|
|
return ioctlAddToBridge(iface, master)
|
|
return ioctlAddToBridge(iface, master)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func setHairpinMode(link netlink.Link, enable bool) error {
|
|
|
|
+ err := netlink.LinkSetHairpin(link, enable)
|
|
|
|
+ if err != nil && err != syscall.EINVAL {
|
|
|
|
+ // If error is not EINVAL something else went wrong, bail out right away
|
|
|
|
+ return fmt.Errorf("unable to set hairpin mode on %s via netlink: %v",
|
|
|
|
+ link.Attrs().Name, err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Hairpin mode successfully set up
|
|
|
|
+ if err == nil {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // The netlink method failed with EINVAL which is probably because of an older
|
|
|
|
+ // kernel. Try one more time via the sysfs method.
|
|
|
|
+ path := filepath.Join("/sys/class/net", link.Attrs().Name, "brport/hairpin_mode")
|
|
|
|
+
|
|
|
|
+ var val []byte
|
|
|
|
+ if enable {
|
|
|
|
+ val = []byte{'1', '\n'}
|
|
|
|
+ } else {
|
|
|
|
+ val = []byte{'0', '\n'}
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if err := ioutil.WriteFile(path, val, 0644); err != nil {
|
|
|
|
+ return fmt.Errorf("unable to set hairpin mode on %s via sysfs: %v", link.Attrs().Name, err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
|
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
|
var (
|
|
var (
|
|
ipv6Addr *net.IPNet
|
|
ipv6Addr *net.IPNet
|
|
@@ -906,7 +940,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
|
}
|
|
}
|
|
|
|
|
|
if !config.EnableUserlandProxy {
|
|
if !config.EnableUserlandProxy {
|
|
- err = netlink.LinkSetHairpin(host, true)
|
|
|
|
|
|
+ err = setHairpinMode(host, true)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|