Просмотр исходного кода

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 лет назад
Родитель
Сommit
2dd9a6fa75
1 измененных файлов с 35 добавлено и 1 удалено
  1. 35 1
      libnetwork/drivers/bridge/bridge.go

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

@@ -3,10 +3,13 @@ package bridge
 import (
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"net"
 	"os/exec"
+	"path/filepath"
 	"strconv"
 	"sync"
+	"syscall"
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/driverapi"
@@ -772,6 +775,37 @@ func addToBridge(ifaceName, bridgeName string) error {
 	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 {
 	var (
 		ipv6Addr *net.IPNet
@@ -902,7 +936,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 
 	if !config.EnableUserlandProxy {
-		err = netlink.LinkSetHairpin(host, true)
+		err = setHairpinMode(host, true)
 		if err != nil {
 			return err
 		}