adding the sfc features 57/70657/4
authorKuralamudhan Ramakrishnan <kuralamudhan.ramakrishnan@intel.com>
Tue, 4 Aug 2020 21:33:21 +0000 (14:33 -0700)
committerKuralamudhan Ramakrishnan <kuralamudhan.ramakrishnan@intel.com>
Fri, 18 Sep 2020 00:10:02 +0000 (17:10 -0700)
- including the network/iface.go file
- adding the default gw features in pod network namespaces
- fixing insync message bug

Signed-off-by: Kuralamudhan Ramakrishnan <kuralamudhan.ramakrishnan@intel.com>
Change-Id: I9b595c5cae415cc594f7682f1ffdbdf6291ea909

cmd/nfn-agent/nfn-agent.go
internal/pkg/network/iface.go [new file with mode: 0644]
internal/pkg/network/iptables.go
internal/pkg/utils/chain.go

index 8e7ad78..33913d8 100644 (file)
@@ -24,8 +24,8 @@ import (
        "os/signal"
        cs "ovn4nfv-k8s-plugin/internal/pkg/cniserver"
        pb "ovn4nfv-k8s-plugin/internal/pkg/nfnNotify/proto"
-        chaining "ovn4nfv-k8s-plugin/internal/pkg/utils"
        "ovn4nfv-k8s-plugin/internal/pkg/ovn"
+       chaining "ovn4nfv-k8s-plugin/internal/pkg/utils"
        "strings"
        "syscall"
        "time"
@@ -286,16 +286,16 @@ func handleNotif(msg *pb.Notification) {
                        }
 
                case *pb.Notification_InSync:
+                       inSyncVlanProvidernetwork()
+                       inSyncDirectProvidernetwork()
+                       pnCreateStore = nil
+                       inSync = true
                        if payload.InSync.GetNodeIntfIpAddress() != "" && payload.InSync.GetNodeIntfMacAddress() != "" {
                                err := createNodeOVSInternalPort(payload)
                                if err != nil {
                                        return
                                }
                        }
-                       inSyncVlanProvidernetwork()
-                       inSyncDirectProvidernetwork()
-                       pnCreateStore = nil
-                       inSync = true
 
                }
        // Add other Types here
diff --git a/internal/pkg/network/iface.go b/internal/pkg/network/iface.go
new file mode 100644 (file)
index 0000000..b2a57bd
--- /dev/null
@@ -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
+}
index 6e71b3f..5a59dc7 100644 (file)
@@ -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
index aa98aa1..8198dcb 100644 (file)
@@ -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