Libnetwork sha# e578e95aa101441481411ff1d620f343895f24fe
Signed-off-by: Madhu Venugopal <madhu@docker.com>
| ... | ... |
@@ -17,7 +17,7 @@ clone hg code.google.com/p/go.net 84a4013f96e0 |
| 17 | 17 |
clone hg code.google.com/p/gosqlite 74691fb6f837 |
| 18 | 18 |
|
| 19 | 19 |
#get libnetwork packages |
| 20 |
-clone git github.com/docker/libnetwork 90638ec9cf7fa7b7f5d0e96b0854f136d66bff92 |
|
| 20 |
+clone git github.com/docker/libnetwork e578e95aa101441481411ff1d620f343895f24fe |
|
| 21 | 21 |
clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c |
| 22 | 22 |
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c |
| 23 | 23 |
|
| ... | ... |
@@ -98,3 +98,20 @@ func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
|
| 98 | 98 |
c.Fatalf("Expected message %q but received %q", msg, final)
|
| 99 | 99 |
} |
| 100 | 100 |
} |
| 101 |
+ |
|
| 102 |
+func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
|
|
| 103 |
+ testRequires(c, SameHostDaemon, NativeExecDriver) |
|
| 104 |
+ msg := "it works" |
|
| 105 |
+ startServerContainer(c, msg, 8080) |
|
| 106 |
+ endpoint := getExternalAddress(c) |
|
| 107 |
+ runCmd := exec.Command(dockerBinary, "run", "-t", "--net=container:server", "busybox", |
|
| 108 |
+ "sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String()))
|
|
| 109 |
+ out, _, err := runCommandWithOutput(runCmd) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ c.Fatal(out, err) |
|
| 112 |
+ } |
|
| 113 |
+ final := strings.TrimRight(string(out), "\n") |
|
| 114 |
+ if final != msg {
|
|
| 115 |
+ c.Fatalf("Expected message %q but received %q", msg, final)
|
|
| 116 |
+ } |
|
| 117 |
+} |
| ... | ... |
@@ -516,6 +516,13 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn |
| 516 | 516 |
return err |
| 517 | 517 |
} |
| 518 | 518 |
|
| 519 |
+ if !config.EnableUserlandProxy {
|
|
| 520 |
+ err = netlink.LinkSetHairpin(host, true) |
|
| 521 |
+ if err != nil {
|
|
| 522 |
+ return err |
|
| 523 |
+ } |
|
| 524 |
+ } |
|
| 525 |
+ |
|
| 519 | 526 |
// v4 address for the sandbox side pipe interface |
| 520 | 527 |
ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil) |
| 521 | 528 |
if err != nil {
|
| ... | ... |
@@ -44,9 +44,10 @@ var ( |
| 44 | 44 |
|
| 45 | 45 |
// Chain defines the iptables chain. |
| 46 | 46 |
type Chain struct {
|
| 47 |
- Name string |
|
| 48 |
- Bridge string |
|
| 49 |
- Table Table |
|
| 47 |
+ Name string |
|
| 48 |
+ Bridge string |
|
| 49 |
+ Table Table |
|
| 50 |
+ HairpinMode bool |
|
| 50 | 51 |
} |
| 51 | 52 |
|
| 52 | 53 |
// ChainError is returned to represent errors during ip table operation. |
| ... | ... |
@@ -75,9 +76,10 @@ func initCheck() error {
|
| 75 | 75 |
// NewChain adds a new chain to ip table. |
| 76 | 76 |
func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error) {
|
| 77 | 77 |
c := &Chain{
|
| 78 |
- Name: name, |
|
| 79 |
- Bridge: bridge, |
|
| 80 |
- Table: table, |
|
| 78 |
+ Name: name, |
|
| 79 |
+ Bridge: bridge, |
|
| 80 |
+ Table: table, |
|
| 81 |
+ HairpinMode: hairpinMode, |
|
| 81 | 82 |
} |
| 82 | 83 |
|
| 83 | 84 |
if string(c.Table) == "" {
|
| ... | ... |
@@ -151,12 +153,16 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri |
| 151 | 151 |
// value" by both iptables and ip6tables. |
| 152 | 152 |
daddr = "0/0" |
| 153 | 153 |
} |
| 154 |
- if output, err := Raw("-t", string(Nat), string(action), c.Name,
|
|
| 154 |
+ args := []string{"-t", string(Nat), string(action), c.Name,
|
|
| 155 | 155 |
"-p", proto, |
| 156 | 156 |
"-d", daddr, |
| 157 | 157 |
"--dport", strconv.Itoa(port), |
| 158 | 158 |
"-j", "DNAT", |
| 159 |
- "--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))); err != nil {
|
|
| 159 |
+ "--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))} |
|
| 160 |
+ if !c.HairpinMode {
|
|
| 161 |
+ args = append(args, "!", "-i", c.Bridge) |
|
| 162 |
+ } |
|
| 163 |
+ if output, err := Raw(args...); err != nil {
|
|
| 160 | 164 |
return err |
| 161 | 165 |
} else if len(output) != 0 {
|
| 162 | 166 |
return ChainError{Chain: "FORWARD", Output: output}
|