
The source address selection was random, and sometimes we picked a source address that the container didn't have a route to. Adding a default route fixes that!
104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
// Copyright 2017 CNI authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/containernetworking/plugins/pkg/ns"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"testing"
|
|
)
|
|
|
|
func TestPortmap(t *testing.T) {
|
|
RegisterFailHandler(Fail)
|
|
RunSpecs(t, "portmap Suite")
|
|
}
|
|
|
|
// OpenEchoServer opens a server that listens until closeChan is closed.
|
|
// It opens on a random port and sends the port number on portChan when
|
|
// the server is up and running. If an error is encountered, closes portChan.
|
|
// If closeChan is closed, closes the socket.
|
|
func OpenEchoServer(portChan chan<- int, closeChan <-chan interface{}) error {
|
|
laddr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
|
|
if err != nil {
|
|
close(portChan)
|
|
return err
|
|
}
|
|
sock, err := net.ListenTCP("tcp", laddr)
|
|
if err != nil {
|
|
close(portChan)
|
|
return err
|
|
}
|
|
defer sock.Close()
|
|
|
|
switch addr := sock.Addr().(type) {
|
|
case *net.TCPAddr:
|
|
portChan <- addr.Port
|
|
default:
|
|
close(portChan)
|
|
return fmt.Errorf("addr cast failed!")
|
|
}
|
|
for {
|
|
select {
|
|
case <-closeChan:
|
|
break
|
|
default:
|
|
}
|
|
|
|
sock.SetDeadline(time.Now().Add(time.Second))
|
|
con, err := sock.AcceptTCP()
|
|
if err != nil {
|
|
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
|
|
continue
|
|
}
|
|
continue
|
|
}
|
|
|
|
buf := make([]byte, 512)
|
|
con.Read(buf)
|
|
con.Write(buf)
|
|
con.Close()
|
|
}
|
|
}
|
|
|
|
func RunEchoServerInNS(netNS ns.NetNS) (int, chan interface{}, error) {
|
|
portChan := make(chan int)
|
|
closeChan := make(chan interface{})
|
|
|
|
go func() {
|
|
err := netNS.Do(func(ns.NetNS) error {
|
|
OpenEchoServer(portChan, closeChan)
|
|
return nil
|
|
})
|
|
// Somehow the ns.Do failed
|
|
if err != nil {
|
|
close(portChan)
|
|
}
|
|
}()
|
|
|
|
portNum := <-portChan
|
|
if portNum == 0 {
|
|
return 0, nil, fmt.Errorf("failed to execute server")
|
|
}
|
|
|
|
return portNum, closeChan, nil
|
|
}
|