From c99d1522d6a52765cb8bb664149c705e33911f7d Mon Sep 17 00:00:00 2001 From: Kuralamudhan Ramakrishnan Date: Tue, 4 Aug 2020 14:33:21 -0700 Subject: adding the sfc features - including the network/iface.go file - adding the default gw features in pod network namespaces - fixing insync message bug Signed-off-by: Kuralamudhan Ramakrishnan Change-Id: I9b595c5cae415cc594f7682f1ffdbdf6291ea909 --- internal/pkg/network/iface.go | 114 +++++++++++++++++++++++++++++++++++++++ internal/pkg/network/iptables.go | 2 +- internal/pkg/utils/chain.go | 49 +++++++++++++++-- 3 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 internal/pkg/network/iface.go (limited to 'internal/pkg') diff --git a/internal/pkg/network/iface.go b/internal/pkg/network/iface.go new file mode 100644 index 0000000..b2a57bd --- /dev/null +++ b/internal/pkg/network/iface.go @@ -0,0 +1,114 @@ +package network + +import ( + "errors" + "net" + "syscall" + + "github.com/vishvananda/netlink" +) + +//GetDefaultGateway return default gateway of the network namespace +func GetDefaultGateway() (string, error) { + routes, err := netlink.RouteList(nil, syscall.AF_INET) + if err != nil { + return "", err + } + + for _, route := range routes { + if route.Dst == nil || route.Dst.String() == "0.0.0.0/0" { + if route.Gw.To4() == nil { + return "", errors.New("Found default route but could not determine gateway") + } + return route.Gw.To4().String(), nil + } + } + + return "", errors.New("Unable to find default route") +} + +// GetDefaultGatewayInterface return default gateway interface link +func GetDefaultGatewayInterface() (*net.Interface, error) { + routes, err := netlink.RouteList(nil, syscall.AF_INET) + if err != nil { + return nil, err + } + + for _, route := range routes { + if route.Dst == nil || route.Dst.String() == "0.0.0.0/0" { + if route.LinkIndex <= 0 { + return nil, errors.New("Found default route but could not determine interface") + } + return net.InterfaceByIndex(route.LinkIndex) + } + } + + return nil, errors.New("Unable to find default route") +} + +func getIfaceAddrs(iface *net.Interface) ([]netlink.Addr, error) { + + link := &netlink.Device{ + netlink.LinkAttrs{ + Index: iface.Index, + }, + } + + return netlink.AddrList(link, syscall.AF_INET) +} + +//GetInterfaceIP4Addr return IP4addr of a interface +func GetInterfaceIP4Addr(iface *net.Interface) (netlink.Addr, error) { + addrs, err := getIfaceAddrs(iface) + if err != nil { + return netlink.Addr{}, err + } + + // prefer non link-local addr + var ll netlink.Addr + + for _, addr := range addrs { + if addr.IP.To4() == nil { + continue + } + + if addr.IP.IsGlobalUnicast() { + return addr, nil + } + + if addr.IP.IsLinkLocalUnicast() { + ll = addr + } + } + + if ll.IP.To4() != nil { + // didn't find global but found link-local. it'll do. + return ll, nil + } + + return netlink.Addr{}, errors.New("No IPv4 address found for given interface") +} + +//GetHostNetwork return default gateway interface network +func GetHostNetwork() (string, error) { + + iface, err := GetDefaultGatewayInterface() + if err != nil { + log.Error(err, "error in gettting default gateway interface") + return "", err + } + + ipv4addr, err := GetInterfaceIP4Addr(iface) + if err != nil { + log.Error(err, "error in gettting default gateway interface IPv4 address") + return "", err + } + + _, ipv4Net, err := net.ParseCIDR(ipv4addr.IPNet.String()) + if err != nil { + log.Error(err, "error in gettting default gateway interface network") + return "", err + } + + return ipv4Net.String(), nil +} diff --git a/internal/pkg/network/iptables.go b/internal/pkg/network/iptables.go index 6e71b3f..5a59dc7 100644 --- a/internal/pkg/network/iptables.go +++ b/internal/pkg/network/iptables.go @@ -9,7 +9,7 @@ import ( "github.com/coreos/go-iptables/iptables" ) -var log = logf.Log.WithName("iptables") +var log = logf.Log.WithName("network") type IPTables interface { AppendUnique(table string, chain string, rulespec ...string) error diff --git a/internal/pkg/utils/chain.go b/internal/pkg/utils/chain.go index aa98aa1..8198dcb 100644 --- a/internal/pkg/utils/chain.go +++ b/internal/pkg/utils/chain.go @@ -19,6 +19,7 @@ package nfn import ( "context" "fmt" + "ovn4nfv-k8s-plugin/internal/pkg/network" "ovn4nfv-k8s-plugin/internal/pkg/ovn" k8sv1alpha1 "ovn4nfv-k8s-plugin/pkg/apis/k8s/v1alpha1" "strings" @@ -123,6 +124,13 @@ func calculateDeploymentRoutes(namespace, label string, pos int, num int, ln []k r.DynamicNetworkRoutes = append(r.DynamicNetworkRoutes, rt) } } + + //Add Default Route based on Right Network + rt := k8sv1alpha1.Route{ + GW: nextRightIP, + Dst: "0.0.0.0", + } + r.DynamicNetworkRoutes = append(r.DynamicNetworkRoutes, rt) return } @@ -145,6 +153,11 @@ func CalculateRoutes(cr *k8sv1alpha1.NetworkChaining) ([]RoutingInfo, error) { i++ } num := len(deploymentList) + log.Info("Display the num", "num", num) + log.Info("Display the ln", "ln", ln) + log.Info("Display the rn", "rn", rn) + log.Info("Display the networklist", "networkList", networkList) + log.Info("Display the deploymentlist", "deploymentList", deploymentList) for i, deployment := range deploymentList { r, err := calculateDeploymentRoutes(cr.Namespace, deployment, i, num, ln, rn, networkList, deploymentList) if err != nil { @@ -156,9 +169,14 @@ func CalculateRoutes(cr *k8sv1alpha1.NetworkChaining) ([]RoutingInfo, error) { } func ContainerAddRoute(containerPid int, route []*pb.RouteData) error { - str := fmt.Sprintf("/host/proc/%d/ns/net", containerPid) + hostNet, err := network.GetHostNetwork() + if err != nil { + log.Error(err, "Failed to get host network") + return err + } + nms, err := ns.GetNS(str) if err != nil { log.Error(err, "Failed namesapce", "containerID", containerPid) @@ -166,13 +184,34 @@ func ContainerAddRoute(containerPid int, route []*pb.RouteData) error { } defer nms.Close() err = nms.Do(func(_ ns.NetNS) error { + podGW, err := network.GetDefaultGateway() + if err != nil { + log.Error(err, "Failed to get pod default gateway") + return err + } + + stdout, stderr, err := ovn.RunIP("route", "add", hostNet, "via", podGW) + if err != nil && !strings.Contains(stderr, "RTNETLINK answers: File exists") { + log.Error(err, "Failed to ip route add", "stdout", stdout, "stderr", stderr) + return err + } + for _, r := range route { dst := r.GetDst() gw := r.GetGw() - stdout, stderr, err := ovn.RunIP("route", "add", dst, "via", gw) - if err != nil && !strings.Contains(stderr, "RTNETLINK answers: File exists") { - log.Error(err, "Failed to ip route add", "stdout", stdout, "stderr", stderr) - return err + // Replace default route + if dst == "0.0.0.0" { + stdout, stderr, err := ovn.RunIP("route", "replace", "default", "via", gw) + if err != nil { + log.Error(err, "Failed to ip route replace", "stdout", stdout, "stderr", stderr) + return err + } + } else { + stdout, stderr, err := ovn.RunIP("route", "add", dst, "via", gw) + if err != nil && !strings.Contains(stderr, "RTNETLINK answers: File exists") { + log.Error(err, "Failed to ip route add", "stdout", stdout, "stderr", stderr) + return err + } } } return nil -- cgit 1.2.3-korg