Kaynağa Gözat

Use sysfs to set hairpin mode

Set the hairpin mode using the sysfs interface which
looks like it is working all the way to the oldest
of RHEL6.6 kernels.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 10 yıl önce
ebeveyn
işleme
2dd9a6fa75
1 değiştirilmiş dosya ile 35 ekleme ve 1 silme
  1. 35 1
      libnetwork/drivers/bridge/bridge.go

+ 35 - 1
libnetwork/drivers/bridge/bridge.go

@@ -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"
@@ -772,6 +775,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
@@ -902,7 +936,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
 		}
 		}