Move NetDev utils from common/ to net/

This commit is contained in:
Martynas Pumputis committed 2016-10-19 17:03:30 +01:00
1 parent 3492cd93d0
commit e611f04f41
7 files changed
+172 -175

No files matched your search

+1 -159
View File
@@ -1,18 +1,6 @@
package common
import (
"fmt"
"net"
"os"
"regexp"
"strconv"
"strings"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
weavenet "github.com/weaveworks/weave/net"
)
import "strings"
// Assert test is true, panic otherwise
func Assert(test bool) {
@@ -28,149 +16,3 @@ func ErrorMessages(errors []error) string {
}
return strings.Join(result, "\n")
}
var netdevRegExp = regexp.MustCompile(`^([^ ]+?) ([^ ]+?) \[([^]]*)\]$`)
type NetDev struct {
Name string
MAC net.HardwareAddr
CIDRs []*net.IPNet
}
func (d NetDev) String() string {
return fmt.Sprintf("%s %s %s", d.Name, d.MAC, d.CIDRs)
}
func ParseNetDev(netdev string) (NetDev, error) {
match := netdevRegExp.FindStringSubmatch(netdev)
if match == nil {
return NetDev{}, fmt.Errorf("invalid netdev: %s", netdev)
}
iface := match[1]
mac, err := net.ParseMAC(match[2])
if err != nil {
return NetDev{}, fmt.Errorf("cannot parse mac %s: %s", match[2], err)
}
var cidrs []*net.IPNet
for _, cidr := range strings.Split(match[3], " ") {
if cidr != "" {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return NetDev{}, fmt.Errorf("cannot parse cidr %s: %s", cidr, err)
}
ipnet.IP = ip
cidrs = append(cidrs, ipnet)
}
}
return NetDev{Name: iface, MAC: mac, CIDRs: cidrs}, nil
}
func LinkToNetDev(link netlink.Link) (NetDev, error) {
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return NetDev{}, err
}
netDev := NetDev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
for _, addr := range addrs {
netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
}
return netDev, nil
}
// ConnectedToBridgeVethPeerIds returns peer indexes of veth links connected to
// the given bridge. The peer index is used to query from a container netns
// whether the container is connected to the bridge.
func ConnectedToBridgeVethPeerIds(bridgeName string) ([]int, error) {
var ids []int
br, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, err
}
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
for _, link := range links {
if _, isveth := link.(*netlink.Veth); isveth && link.Attrs().MasterIndex == br.Attrs().Index {
peerID := link.Attrs().ParentIndex
if peerID == 0 {
// perhaps running on an older kernel where ParentIndex doesn't work.
// as fall-back, assume the peers are consecutive
peerID = link.Attrs().Index - 1
}
ids = append(ids, peerID)
}
}
return ids, nil
}
// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]NetDev, error) {
peerIDs, err := ConnectedToBridgeVethPeerIds("weave")
if err != nil {
return nil, err
}
return GetNetDevsByVethPeerIds(processID, peerIDs)
}
func GetNetDevsByVethPeerIds(processID int, peerIDs []int) ([]NetDev, error) {
// Bail out if this container is running in the root namespace
netnsRoot, err := netns.GetFromPid(1)
if err != nil {
return nil, fmt.Errorf("unable to open root namespace: %s", err)
}
defer netnsRoot.Close()
netnsContainer, err := netns.GetFromPid(processID)
if err != nil {
// Unable to find a namespace for this process - just return nothing
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
}
defer netnsContainer.Close()
if netnsRoot.Equal(netnsContainer) {
return nil, nil
}
var netdevs []NetDev
peersStr := make([]string, len(peerIDs))
for i, id := range peerIDs {
peersStr[i] = strconv.Itoa(id)
}
netdevsStr, err := weavenet.WithNetNSByPid(processID, "list-netdevs", strings.Join(peersStr, ","))
if err != nil {
return nil, fmt.Errorf("list-netdevs failed: %s", err)
}
for _, netdevStr := range strings.Split(netdevsStr, "\n") {
if netdevStr != "" {
netdev, err := ParseNetDev(netdevStr)
if err != nil {
return nil, fmt.Errorf("cannot parse netdev %s: %s", netdevStr, err)
}
netdevs = append(netdevs, netdev)
}
}
return netdevs, nil
}
// Get the weave bridge interface.
// NB: Should be called from the root network namespace.
func GetBridgeNetDev(bridgeName string) (NetDev, error) {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return NetDev{}, err
}
return LinkToNetDev(link)
}
+159
View File
@@ -0,0 +1,159 @@
package net
import (
"fmt"
"net"
"os"
"regexp"
"strconv"
"strings"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)
var netdevRegExp = regexp.MustCompile(`^([^ ]+?) ([^ ]+?) \[([^]]*)\]$`)
type Dev struct {
Name string
MAC net.HardwareAddr
CIDRs []*net.IPNet
}
func (d Dev) String() string {
return fmt.Sprintf("%s %s %s", d.Name, d.MAC, d.CIDRs)
}
func ParseNetDev(netdev string) (Dev, error) {
match := netdevRegExp.FindStringSubmatch(netdev)
if match == nil {
return Dev{}, fmt.Errorf("invalid netdev: %s", netdev)
}
iface := match[1]
mac, err := net.ParseMAC(match[2])
if err != nil {
return Dev{}, fmt.Errorf("cannot parse mac %s: %s", match[2], err)
}
var cidrs []*net.IPNet
for _, cidr := range strings.Split(match[3], " ") {
if cidr != "" {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return Dev{}, fmt.Errorf("cannot parse cidr %s: %s", cidr, err)
}
ipnet.IP = ip
cidrs = append(cidrs, ipnet)
}
}
return Dev{Name: iface, MAC: mac, CIDRs: cidrs}, nil
}
func LinkToNetDev(link netlink.Link) (Dev, error) {
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return Dev{}, err
}
netDev := Dev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
for _, addr := range addrs {
netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
}
return netDev, nil
}
// ConnectedToBridgeVethPeerIds returns peer indexes of veth links connected to
// the given bridge. The peer index is used to query from a container netns
// whether the container is connected to the bridge.
func ConnectedToBridgeVethPeerIds(bridgeName string) ([]int, error) {
var ids []int
br, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, err
}
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
for _, link := range links {
if _, isveth := link.(*netlink.Veth); isveth && link.Attrs().MasterIndex == br.Attrs().Index {
peerID := link.Attrs().ParentIndex
if peerID == 0 {
// perhaps running on an older kernel where ParentIndex doesn't work.
// as fall-back, assume the peers are consecutive
peerID = link.Attrs().Index - 1
}
ids = append(ids, peerID)
}
}
return ids, nil
}
// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]Dev, error) {
peerIDs, err := ConnectedToBridgeVethPeerIds("weave")
if err != nil {
return nil, err
}
return GetNetDevsByVethPeerIds(processID, peerIDs)
}
func GetNetDevsByVethPeerIds(processID int, peerIDs []int) ([]Dev, error) {
// Bail out if this container is running in the root namespace
netnsRoot, err := netns.GetFromPid(1)
if err != nil {
return nil, fmt.Errorf("unable to open root namespace: %s", err)
}
defer netnsRoot.Close()
netnsContainer, err := netns.GetFromPid(processID)
if err != nil {
// Unable to find a namespace for this process - just return nothing
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
}
defer netnsContainer.Close()
if netnsRoot.Equal(netnsContainer) {
return nil, nil
}
var netdevs []Dev
peersStr := make([]string, len(peerIDs))
for i, id := range peerIDs {
peersStr[i] = strconv.Itoa(id)
}
netdevsStr, err := WithNetNSByPid(processID, "list-netdevs", strings.Join(peersStr, ","))
if err != nil {
return nil, fmt.Errorf("list-netdevs failed: %s", err)
}
for _, netdevStr := range strings.Split(netdevsStr, "\n") {
if netdevStr != "" {
netdev, err := ParseNetDev(netdevStr)
if err != nil {
return nil, fmt.Errorf("cannot parse netdev %s: %s", netdevStr, err)
}
netdevs = append(netdevs, netdev)
}
}
return netdevs, nil
}
// Get the weave bridge interface.
// NB: Should be called from the root network namespace.
func GetBridgeNetDev(bridgeName string) (Dev, error) {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return Dev{}, err
}
return LinkToNetDev(link)
}
+1 -2
View File
@@ -12,7 +12,6 @@ import (
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
)
@@ -159,7 +158,7 @@ func assignBridgeIP(bridgeName string, ipnet net.IPNet) error {
var errBridgeNoIP = fmt.Errorf("Bridge has no IP address")
func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) {
netdev, err := common.GetBridgeNetDev(bridgeName)
netdev, err := weavenet.GetBridgeNetDev(bridgeName)
if err != nil {
return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err)
}
+6 -7
View File
@@ -5,7 +5,6 @@ import (
"github.com/fsouza/go-dockerclient"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
)
@@ -20,7 +19,7 @@ func containerAddrs(args []string) error {
return err
}
peerIDs, err := common.ConnectedToBridgeVethPeerIds(bridgeName)
peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName)
if err != nil {
if err == weavenet.ErrLinkNotFound {
return nil
@@ -33,11 +32,11 @@ func containerAddrs(args []string) error {
for _, cid := range args[1:] {
if cid == "weave:expose" {
netDev, err := common.GetBridgeNetDev(bridgeName)
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
if err != nil {
return err
}
printNetDevs(cid, []common.NetDev{netDev})
printNetDevs(cid, []weavenet.Dev{netDev})
continue
}
if containers[cid], err = client.InspectContainer(cid); err != nil {
@@ -61,14 +60,14 @@ func containerAddrs(args []string) error {
return nil
}
func getNetDevs(c *docker.Client, container *docker.Container, peerIDs []int) ([]common.NetDev, error) {
func getNetDevs(c *docker.Client, container *docker.Container, peerIDs []int) ([]weavenet.Dev, error) {
if container.State.Pid == 0 {
return nil, nil
}
return common.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs)
return weavenet.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs)
}
func printNetDevs(cid string, netDevs []common.NetDev) {
func printNetDevs(cid string, netDevs []weavenet.Dev) {
for _, netDev := range netDevs {
fmt.Printf("%12s %s %s", cid, netDev.Name, netDev.MAC.String())
for _, cidr := range netDev.CIDRs {
+1 -2
View File
@@ -9,7 +9,6 @@ import (
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
)
@@ -120,7 +119,7 @@ func listNetDevs(args []string) error {
for _, link := range links {
if _, found := indexes[link.Attrs().Index]; found {
netdev, err := common.LinkToNetDev(link)
netdev, err := weavenet.LinkToNetDev(link)
if err != nil {
return err
}
+2 -2
View File
@@ -13,7 +13,7 @@ func processAddrs(args []string) error {
}
bridgeName := args[0]
peerIDs, err := common.ConnectedToBridgeVethPeerIds(bridgeName)
peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName)
if err != nil {
if err == weavenet.ErrLinkNotFound {
return nil
@@ -27,7 +27,7 @@ func processAddrs(args []string) error {
}
for _, pid := range pids {
netDevs, err := common.GetNetDevsByVethPeerIds(pid, peerIDs)
netDevs, err := weavenet.GetNetDevsByVethPeerIds(pid, peerIDs)
if err != nil {
return err
}
+2 -3
View File
@@ -17,7 +17,6 @@ import (
docker "github.com/fsouza/go-dockerclient"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
weavedocker "github.com/weaveworks/weave/common/docker"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
@@ -149,7 +148,7 @@ func NewProxy(c Config) (*Proxy, error) {
p.client = client.Client
if !p.WithoutDNS {
netDev, err := common.GetBridgeNetDev(c.DockerBridge)
netDev, err := weavenet.GetBridgeNetDev(c.DockerBridge)
if err != nil {
return nil, err
}
@@ -625,7 +624,7 @@ func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error {
if err := proxy.waitForStartByIdent(containerID); err != nil {
return err
}
netDevs, err := common.GetWeaveNetDevs(pid)
netDevs, err := weavenet.GetWeaveNetDevs(pid)
if err != nil || len(netDevs) == 0 || len(netDevs[0].CIDRs) == 0 {
return err
}