diff --git a/networking/ipam/ipam.go b/networking/ipam/ipam.go index 843c7ba..2809845 100644 --- a/networking/ipam/ipam.go +++ b/networking/ipam/ipam.go @@ -101,6 +101,7 @@ func parseArgs(args string) (*options, error) { return opts, nil } +// AllocIP allocates an IP in a given range. func AllocIP(contID types.UUID, netConf, ifName, args string) (*net.IPNet, net.IP, error) { opts, err := parseArgs(args) if err != nil { @@ -129,7 +130,7 @@ func AllocIP(contID types.UUID, netConf, ifName, args string) (*net.IPNet, net.I _, rng, err := net.ParseCIDR(n.IPAlloc.Subnet) if err != nil { // TODO: cleanup - return nil, nil, fmt.Errorf("error parsing %q conf: ipAlloc.Subnet: %v") + return nil, nil, fmt.Errorf("error parsing %q conf: ipAlloc.Subnet: %v", netConf, err) } ip, err := allocIP(rng) @@ -148,7 +149,7 @@ func AllocIP(contID types.UUID, netConf, ifName, args string) (*net.IPNet, net.I } } -// allocates a /31 for point-to-point links +// AllocPtP allocates a /31 for point-to-point links. func AllocPtP(contID types.UUID, netConf, ifName, args string) ([2]net.IP, error) { ipn, _, err := AllocIP(contID, netConf, ifName, args) if err != nil { @@ -162,6 +163,7 @@ func AllocPtP(contID types.UUID, netConf, ifName, args string) ([2]net.IP, error return [2]net.IP{first, second}, nil } +// DeallocIP is a no-op. func DeallocIP(contID types.UUID, netConf, ifName string, ipn *net.IPNet) error { return nil } diff --git a/networking/net-plugin.go b/networking/net-plugin.go index 8fb3ac3..33f31f4 100644 --- a/networking/net-plugin.go +++ b/networking/net-plugin.go @@ -31,6 +31,7 @@ import ( "github.com/coreos/rocket/networking/util" ) +// NetPlugin encodes a networking plugin. type NetPlugin struct { Name string `json:"name,omitempty"` Endpoint string `json:"endpoint,omitempty"` @@ -40,8 +41,10 @@ type NetPlugin struct { } } +// RktNetPluginsPath is the absolute path of rkt-net-plugins.conf.d. const RktNetPluginsPath = "/etc/rkt-net-plugins.conf.d" +// LoadNetPlugin loads a JSON-encoded NetPlugin from the filesystem. func LoadNetPlugin(path string) (*NetPlugin, error) { c, err := ioutil.ReadFile(path) if err != nil { @@ -56,6 +59,8 @@ func LoadNetPlugin(path string) (*NetPlugin, error) { return np, nil } +// LoadNetPlugins produces a collection of NetPlugins loaded from +// RktNetPluginsPath. func LoadNetPlugins() (map[string]*NetPlugin, error) { plugins := make(map[string]*NetPlugin) @@ -86,6 +91,7 @@ func LoadNetPlugins() (map[string]*NetPlugin, error) { return plugins, nil } +// Add invokes the plugin's add command, if defined. func (np *NetPlugin) Add(n *Net, contID types.UUID, netns, args, ifName string) (*net.IPNet, error) { switch { case np.Endpoint != "": @@ -105,6 +111,7 @@ func (np *NetPlugin) Add(n *Net, contID types.UUID, netns, args, ifName string) } } +// Del invokes the plugin's del command, if defined. func (np *NetPlugin) Del(n *Net, contID types.UUID, netns, args, ifName string) error { switch { case np.Endpoint != "": diff --git a/networking/net.go b/networking/net.go index dd1e9de..9e52a83 100644 --- a/networking/net.go +++ b/networking/net.go @@ -24,11 +24,13 @@ import ( "github.com/coreos/rocket/networking/util" ) +// Net encodes a network plugin. type Net struct { util.Net args string } +// RktNetPath is the absolute path of rkt-net.conf.d. const RktNetPath = "/etc/rkt-net.conf.d" func listFiles(dir string) ([]string, error) { @@ -53,6 +55,7 @@ func listFiles(dir string) ([]string, error) { return files, nil } +// LoadNets produces a collection of NetPlugins loaded from RktNetPluginsPath. func LoadNets() ([]Net, error) { files, err := listFiles(RktNetPath) if err != nil { diff --git a/networking/networking.go b/networking/networking.go index d1547de..bb65d0a 100644 --- a/networking/networking.go +++ b/networking/networking.go @@ -39,6 +39,7 @@ type activeNet struct { ipn *net.IPNet } +// Networking describes the networking details of a container. type Networking struct { MetadataIP net.IP @@ -50,6 +51,7 @@ type Networking struct { plugins map[string]*NetPlugin } +// Setup produces a Networking object for a given container ID. func Setup(contID types.UUID) (*Networking, error) { var err error n := Networking{contID: contID} @@ -96,12 +98,13 @@ func Setup(contID types.UUID) (*Networking, error) { return &n, nil } +// Teardown cleans up a produced Networking object. func (n *Networking) Teardown() { - // teardown everything in reverse order of setup. - // this is called during error case as well so not - // everything maybe setup. - // N.B. better to keep going in case of errors to get as much - // cleaned up as possible + // Teardown everything in reverse order of setup. + // This is called during error cases as well, so + // not everything may be setup. + // N.B. better to keep going in case of errors + // to get as much cleaned up as possible. if n.contNS == nil || n.hostNS == nil { return @@ -119,7 +122,7 @@ func (n *Networking) Teardown() { } if err := syscall.Unmount(n.contNSPath, 0); err != nil { - log.Print("Error unmounting %q: %v", n.contNSPath, err) + log.Printf("Error unmounting %q: %v", n.contNSPath, err) } } @@ -141,10 +144,12 @@ func basicNetNS() (hostNS, contNS *os.File, err error) { return } +// EnterHostNS moves into the host's network namespace. func (n *Networking) EnterHostNS() error { return util.SetNS(n.hostNS, syscall.CLONE_NEWNET) } +// EnterContNS moves into the container's network namespace. func (n *Networking) EnterContNS() error { return util.SetNS(n.contNS, syscall.CLONE_NEWNET) } diff --git a/networking/plugins/bridge/bridge.go b/networking/plugins/bridge/bridge.go index 71b1c70..76dc0d2 100644 --- a/networking/plugins/bridge/bridge.go +++ b/networking/plugins/bridge/bridge.go @@ -17,7 +17,7 @@ import ( const defaultBrName = "rkt0" -type Net struct { +type netConf struct { util.Net BrName string `json:"brName"` IsGW bool `json:"isGW"` @@ -30,6 +30,35 @@ func init() { runtime.LockOSThread() } +func usage() int { + fmt.Fprintln(os.Stderr, "USAGE: add|del CONTAINER-ID NETNS NET-CONF IF-NAME") + return 1 +} + +func main() { + if len(os.Args) != 6 { + os.Exit(usage()) + } + + var err error + + switch os.Args[1] { + case "add": + err = cmdAdd(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) + + case "del": + err = cmdDel(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) + + default: + os.Exit(usage()) + } + + if err != nil { + log.Printf("%v: %v", os.Args[1], err) + os.Exit(1) + } +} + func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet) error { addrs, err := netlink.AddrList(br, syscall.AF_INET) if err != nil && err != syscall.ENOENT { @@ -48,7 +77,7 @@ func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet) error { return fmt.Errorf("%q already has an IP address different from %v", br.Name, ipn.String()) } - addr := &netlink.Addr{ipn, ""} + addr := &netlink.Addr{IPNet: ipn, Label: ""} if err := netlink.AddrAdd(br, addr); err != nil { return fmt.Errorf("could not add IP address to %q: %v", br.Name, err) } @@ -122,26 +151,26 @@ func setupVeth(contID types.UUID, netns string, br *netlink.Bridge, ipn *net.IPN // connect host veth end to the bridge if err = netlink.LinkSetMaster(hostVeth, br); err != nil { - return fmt.Errorf("failed to connect %q to bridge: %v", hostVethName, br.Attrs().Name, err) + return fmt.Errorf("failed to connect %q to bridge %v: %v", hostVethName, br.Attrs().Name, err) } return nil } -func cmdAdd(contID, netns, netConf, ifName string) error { +func cmdAdd(contID, netns, netCfg, ifName string) error { cid, err := types.NewUUID(contID) if err != nil { return fmt.Errorf("error parsing ContainerID: %v", err) } - conf := Net{ + conf := netConf{ BrName: defaultBrName, } - if err := util.LoadNet(netConf, &conf); err != nil { - return fmt.Errorf("failed to load %q: %v", netConf, err) + if err := util.LoadNet(netCfg, &conf); err != nil { + return fmt.Errorf("failed to load %q: %v", netCfg, err) } - ipn, gw, err := ipam.AllocIP(*cid, netConf, ifName, "") + ipn, gw, err := ipam.AllocIP(*cid, netCfg, ifName, "") if err != nil { return err } @@ -178,32 +207,3 @@ func cmdDel(contID, netns, netConf, ifName string) error { return util.DelLinkByName(ifName) }) } - -func usage() int { - fmt.Fprintln(os.Stderr, "USAGE: add|del CONTAINER-ID NETNS NET-CONF IF-NAME") - return 1 -} - -func main() { - if len(os.Args) != 6 { - os.Exit(usage()) - } - - var err error - - switch os.Args[1] { - case "add": - err = cmdAdd(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) - - case "del": - err = cmdDel(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) - - default: - os.Exit(usage()) - } - - if err != nil { - log.Printf("%v: %v", os.Args[1], err) - os.Exit(1) - } -} diff --git a/networking/plugins/veth/veth.go b/networking/plugins/veth/veth.go index c10fab9..bc9f380 100644 --- a/networking/plugins/veth/veth.go +++ b/networking/plugins/veth/veth.go @@ -35,6 +35,35 @@ func init() { runtime.LockOSThread() } +func usage() int { + fmt.Fprintln(os.Stderr, "USAGE: add|del CONTAINER-ID NETNS NET-CONF IF-NAME ARGS") + return 1 +} + +func main() { + if len(os.Args) != 7 { + os.Exit(usage()) + } + + var err error + + switch os.Args[1] { + case "add": + err = cmdAdd(os.Args[2], os.Args[3], os.Args[4], os.Args[5], os.Args[6]) + + case "del": + err = cmdDel(os.Args[2], os.Args[3], os.Args[4], os.Args[5], os.Args[6]) + + default: + os.Exit(usage()) + } + + if err != nil { + log.Printf("%v: %v", os.Args[1], err) + os.Exit(1) + } +} + func cmdAdd(contID, netns, netConf, ifName, args string) error { var hostVethName, contIPNet string @@ -98,7 +127,7 @@ func cmdAdd(contID, netns, netConf, ifName, args string) error { IP: hostIP, Mask: net.CIDRMask(31, 32), } - addr := &netlink.Addr{ipn, ""} + addr := &netlink.Addr{IPNet: ipn, Label: ""} if err = netlink.AddrAdd(hostVeth, addr); err != nil { return fmt.Errorf("failed to add IP addr to veth: %v", err) } @@ -118,32 +147,3 @@ func cmdDel(contID, netns, netConf, ifName, args string) error { return util.DelLinkByName(ifName) }) } - -func usage() int { - fmt.Fprintln(os.Stderr, "USAGE: add|del CONTAINER-ID NETNS NET-CONF IF-NAME ARGS") - return 1 -} - -func main() { - if len(os.Args) != 7 { - os.Exit(usage()) - } - - var err error - - switch os.Args[1] { - case "add": - err = cmdAdd(os.Args[2], os.Args[3], os.Args[4], os.Args[5], os.Args[6]) - - case "del": - err = cmdDel(os.Args[2], os.Args[3], os.Args[4], os.Args[5], os.Args[6]) - - default: - os.Exit(usage()) - } - - if err != nil { - log.Printf("%v: %v", os.Args[1], err) - os.Exit(1) - } -} diff --git a/networking/util/cidr.go b/networking/util/cidr.go index 2aa015b..00b92fd 100644 --- a/networking/util/cidr.go +++ b/networking/util/cidr.go @@ -18,6 +18,7 @@ import ( "net" ) +// ParseCIDR invokes net.ParseCIDR. func ParseCIDR(s string) (*net.IPNet, error) { ip, ipn, err := net.ParseCIDR(s) if err != nil { diff --git a/networking/util/link.go b/networking/util/link.go index 20b808b..014c3b9 100644 --- a/networking/util/link.go +++ b/networking/util/link.go @@ -44,7 +44,8 @@ func hash(s string) string { return fmt.Sprintf("%x", h.Sum(nil)) } -// Should be in container netns +// 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, ipn *net.IPNet, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) { // NetworkManager (recent versions) will ignore veth devices that start with "veth" @@ -72,7 +73,7 @@ func SetupVeth(entropy, contVethName string, ipn *net.IPNet, hostNS *os.File) (h } if ipn != nil { - addr := &netlink.Addr{ipn, ""} + addr := &netlink.Addr{IPNet: ipn, Label: ""} if err = netlink.AddrAdd(contVeth, addr); err != nil { err = fmt.Errorf("failed to add IP addr to veth: %v", err) return @@ -87,6 +88,7 @@ func SetupVeth(entropy, contVethName string, ipn *net.IPNet, hostNS *os.File) (h return } +// DelLinkByName removes an interface link. func DelLinkByName(ifName string) error { iface, err := netlink.LinkByName(ifName) if err != nil { diff --git a/networking/util/net.go b/networking/util/net.go index 1eac215..bd7ed0d 100644 --- a/networking/util/net.go +++ b/networking/util/net.go @@ -20,6 +20,7 @@ import ( "reflect" ) +// Net describes a network. type Net struct { Filename string Name string `json:"name,omitempty"` @@ -31,6 +32,7 @@ type Net struct { Routes []string `json:"routes,omitempty"` } +// LoadNet loads a JSON-encoded Net from the filesystem. func LoadNet(path string, n interface{}) error { c, err := ioutil.ReadFile(path) if err != nil { diff --git a/networking/util/route.go b/networking/util/route.go index 36b431f..e1a3f91 100644 --- a/networking/util/route.go +++ b/networking/util/route.go @@ -20,11 +20,13 @@ import ( "github.com/coreos/rocket/Godeps/_workspace/src/github.com/vishvananda/netlink" ) +// AddDefaultRoute sets the default route on the given gateway. func AddDefaultRoute(gw net.IP, dev netlink.Link) error { _, defNet, _ := net.ParseCIDR("0.0.0.0/0") return AddRoute(defNet, gw, dev) } +// AddRoute adds a universally-scoped route to a device. func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { return netlink.RouteAdd(&netlink.Route{ LinkIndex: dev.Attrs().Index, @@ -34,6 +36,7 @@ func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { }) } +// AddHostRoute adds a host-scoped route to a device. func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { return netlink.RouteAdd(&netlink.Route{ LinkIndex: dev.Attrs().Index, diff --git a/networking/util/setns.go b/networking/util/setns.go index 57025b4..e29e21e 100644 --- a/networking/util/setns.go +++ b/networking/util/setns.go @@ -27,6 +27,7 @@ var setNsMap = map[string]uintptr{ "arm": 374, } +// SetNS sets the network namespace on a target file. func SetNS(f *os.File, flags uintptr) error { if runtime.GOOS != "linux" { return fmt.Errorf("unsupported OS: %s", runtime.GOOS) @@ -36,6 +37,7 @@ func SetNS(f *os.File, flags uintptr) error { if !ok { return fmt.Errorf("unsupported arch: %s", runtime.GOARCH) } + _, _, err := syscall.RawSyscall(trap, f.Fd(), flags, 0) if err != 0 { return err @@ -44,6 +46,8 @@ func SetNS(f *os.File, flags uintptr) error { return nil } +// WithNetNSPath executes the passed closure under the given network +// namespace, restoring the original namespace afterwards. func WithNetNSPath(nspath string, f func(*os.File) error) error { // save a handle to current (host) network namespace thisNS, err := os.Open("/proc/self/ns/net")