Do not use netns as ID or for entropy

ContainerID is now required so use that
or generate random bytes.

Fixes #5
This commit is contained in:
Eugene Yakubovich 2015-05-05 13:35:20 -07:00
parent ed97604e74
commit b2d9801b25
9 changed files with 90 additions and 49 deletions

View File

@ -15,7 +15,7 @@
package ip
import (
"crypto/sha512"
"crypto/rand"
"fmt"
"net"
"os"
@ -23,7 +23,7 @@ import (
"github.com/appc/cni/Godeps/_workspace/src/github.com/vishvananda/netlink"
)
func makeVeth(name, peer string, mtu int) (netlink.Link, error) {
func makeVethPair(name, peer string, mtu int) (netlink.Link, error) {
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: name,
@ -39,33 +39,50 @@ func makeVeth(name, peer string, mtu int) (netlink.Link, error) {
return veth, nil
}
func makeVeth(name string, mtu int) (peerName string, veth netlink.Link, err error) {
for i := 0; i < 10; i++ {
peerName, err = RandomVethName()
if err != nil {
return
}
veth, err = makeVethPair(name, peerName, mtu)
switch {
case err == nil:
return
case os.IsExist(err):
continue
default:
err = fmt.Errorf("failed to make veth pair: %v", err)
return
}
}
// should really never be hit
err = fmt.Errorf("failed to find a unique veth name")
return
}
// RandomVethName returns string "veth" with random prefix (hashed from entropy)
func RandomVethName(entropy string) string {
h := sha512.New()
h.Write([]byte(entropy))
return fmt.Sprintf("veth%x", h.Sum(nil)[:5])
func RandomVethName() (string, error) {
entropy := make([]byte, 4)
_, err := rand.Reader.Read(entropy)
if err != nil {
return "", fmt.Errorf("failed to generate random veth name: %v", err)
}
// NetworkManager (recent versions) will ignore veth devices that start with "veth"
return fmt.Sprintf("veth%x", entropy), nil
}
// SetupVeth sets up a virtual ethernet link.
// Should be in container netns.
// TODO(eyakubovich): get rid of entropy and ask kernel to pick name via pattern
func SetupVeth(entropy, contVethName string, mtu int, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) {
// NetworkManager (recent versions) will ignore veth devices that start with "veth"
hostVethName := RandomVethName(entropy)
hostVeth, err = makeVeth(hostVethName, contVethName, mtu)
func SetupVeth(contVethName string, mtu int, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) {
var hostVethName string
hostVethName, contVeth, err = makeVeth(contVethName, mtu)
if err != nil {
err = fmt.Errorf("failed to make veth pair: %v", err)
return
}
if err = netlink.LinkSetUp(hostVeth); err != nil {
err = fmt.Errorf("failed to set %q up: %v", hostVethName, err)
return
}
contVeth, err = netlink.LinkByName(contVethName)
if err != nil {
err = fmt.Errorf("failed to lookup %q: %v", contVethName, err)
return
}
@ -74,6 +91,17 @@ func SetupVeth(entropy, contVethName string, mtu int, hostNS *os.File) (hostVeth
return
}
hostVeth, err = netlink.LinkByName(hostVethName)
if err != nil {
err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
return
}
if err = netlink.LinkSetUp(hostVeth); err != nil {
err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
return
}
if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
err = fmt.Errorf("failed to move veth to host netns: %v", err)
return

View File

@ -48,9 +48,9 @@ func cmdAdd(args *skel.CmdArgs) error {
switch ipamConf.Type {
case "host-local":
ipConf, err = allocator.Get(args.Netns)
ipConf, err = allocator.Get(args.ContainerID)
case "host-local-ptp":
ipConf, err = allocator.GetPtP(args.Netns)
ipConf, err = allocator.GetPtP(args.ContainerID)
default:
return errors.New("Unsupported IPAM plugin type")
}
@ -81,5 +81,5 @@ func cmdDel(args *skel.CmdArgs) error {
return err
}
return allocator.Release(args.Netns)
return allocator.Release(args.ContainerID)
}

View File

@ -130,7 +130,7 @@ func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int, pr *plu
err := ns.WithNetNSPath(netns, func(hostNS *os.File) error {
// create the veth pair in the container and move host end into host netns
hostVeth, _, err := ip.SetupVeth(netns, ifName, mtu, hostNS)
hostVeth, _, err := ip.SetupVeth(ifName, mtu, hostNS)
if err != nil {
return err
}

View File

@ -107,7 +107,11 @@ func cmdAdd(args *skel.CmdArgs) error {
}
defer netns.Close()
tmpName := ip.RandomVethName(args.Netns)
tmpName, err := ip.RandomVethName()
if err != nil {
return err
}
if err = createIpvlan(n, tmpName, netns); err != nil {
return err
}

View File

@ -111,7 +111,11 @@ func cmdAdd(args *skel.CmdArgs) error {
}
defer netns.Close()
tmpName := ip.RandomVethName(args.Netns)
tmpName, err := ip.RandomVethName()
if err != nil {
return err
}
if err = createMacvlan(n, tmpName, netns); err != nil {
return err
}

View File

@ -47,9 +47,7 @@ type NetConf struct {
func setupContainerVeth(netns, ifName string, mtu int, pr *plugin.Result) (string, error) {
var hostVethName string
err := ns.WithNetNSPath(netns, func(hostNS *os.File) error {
entropy := netns + ifName
hostVeth, _, err := ip.SetupVeth(entropy, ifName, mtu, hostNS)
hostVeth, _, err := ip.SetupVeth(ifName, mtu, hostNS)
if err != nil {
return err
}
@ -116,7 +114,7 @@ func cmdAdd(args *skel.CmdArgs) error {
}
if conf.IPMasq {
h := sha512.Sum512([]byte(args.Netns))
h := sha512.Sum512([]byte(args.ContainerID))
chain := fmt.Sprintf("CNI-%s-%x", conf.Name, h[:8])
if err = ip.SetupIPMasq(&result.IP4.IP, chain); err != nil {
return err
@ -143,7 +141,7 @@ func cmdDel(args *skel.CmdArgs) error {
}
if conf.IPMasq {
h := sha512.Sum512([]byte(args.Netns))
h := sha512.Sum512([]byte(args.ContainerID))
chain := fmt.Sprintf("CNI-%s-%x", conf.Name, h[:8])
if err = ip.TeardownIPMasq(ipn, chain); err != nil {
return err

View File

@ -9,10 +9,10 @@ contid=$(docker run -d --net=none busybox:latest /bin/sleep 10000000)
pid=$(docker inspect -f '{{ .State.Pid }}' $contid)
netnspath=/proc/$pid/ns/net
./exec-plugins.sh add $netnspath
./exec-plugins.sh add $contid $netnspath
function cleanup() {
./exec-plugins.sh del $netnspath
./exec-plugins.sh del $contid $netnspath
docker kill $contid >/dev/null
}
trap cleanup EXIT

View File

@ -1,29 +1,36 @@
#!/bin/bash -e
#!/bin/bash
NETCONFPATH=${NETCONFPATH-/etc/cni/net.d}
function exec_plugins() {
i=0
netns=$2
contid=$2
netns=$3
export CNI_COMMAND=$(echo $1 | tr '[:lower:]' '[:upper:]')
export PATH=$CNI_PATH:$PATH
export CNI_CONTAINERID=$contid
export CNI_NETNS=$netns
for netconf in $(echo $NETCONFPATH/*.conf | sort); do
name=$(jq -r '.name' <$netconf)
plugin=$(jq -r '.type' <$netconf)
export CNI_IFNAME=$(printf eth%d $i)
$plugin <$netconf >/dev/null
if [ $? -ne 0 ]; then
echo "${name} : error executing $CNI_COMMAND"
exit 1
fi
let "i=i+1"
done
}
if [ $# -ne 2 ]; then
echo "Usage: $0 add|del NETNS-PATH"
if [ $# -ne 3 ]; then
echo "Usage: $0 add|del CONTAINER-ID NETNS-PATH"
echo " Adds or deletes the container specified by NETNS-PATH to the networks"
echo " specified in \$NETCONFPATH directory"
exit 1
fi
exec_plugins $1 $2
exec_plugins $1 $2 $3

View File

@ -3,18 +3,18 @@
# Run a command in a private network namespace
# set up by CNI plugins
netnsname=$(printf '%x%x' $RANDOM $RANDOM)
netnspath=/var/run/netns/$netnsname
contid=$(printf '%x%x%x%x' $RANDOM $RANDOM $RANDOM $RANDOM)
netnspath=/var/run/netns/$contid
ip netns add $netnsname
ip netns exec $netnsname ip link set lo up
./exec-plugins.sh add $netnspath
ip netns add $contid
ip netns exec $contid ip link set lo up
./exec-plugins.sh add $contid $netnspath
function cleanup() {
./exec-plugins.sh del $netnspath
ip netns delete $netnsname
./exec-plugins.sh del $contid $netnspath
ip netns delete $contid
}
trap cleanup EXIT
ip netns exec $netnsname $@
ip netns exec $contid $@