diff --git a/pkg/cni/commands/check.go b/pkg/cni/commands/check.go index aed07a5..72f7402 100644 --- a/pkg/cni/commands/check.go +++ b/pkg/cni/commands/check.go @@ -5,8 +5,10 @@ import ( "fmt" flv1 "github.com/cnrancher/rancher-flat-network-operator/pkg/apis/flatnetwork.pandaria.io/v1" + "github.com/cnrancher/rancher-flat-network-operator/pkg/cni/ipvlan" "github.com/cnrancher/rancher-flat-network-operator/pkg/cni/kubeclient" "github.com/cnrancher/rancher-flat-network-operator/pkg/cni/logger" + "github.com/cnrancher/rancher-flat-network-operator/pkg/cni/macvlan" "github.com/cnrancher/rancher-flat-network-operator/pkg/cni/types" "github.com/cnrancher/rancher-flat-network-operator/pkg/utils" "github.com/containernetworking/cni/pkg/skel" @@ -120,7 +122,7 @@ func Check(args *skel.CmdArgs) error { // Check prevResults for ips, routes and dns against values found in the container if err := netns.Do(func(_ ns.NetNS) error { // Check interface against values found in the container - err := validateCniContainerInterface(contMap, subnet.Spec.Mode) + err := validateCniContainerInterface(contMap, subnet.Spec.FlatMode, subnet.Spec.Mode) if err != nil { logrus.Errorf("validateCniContainerInterface failed: %v", err) return err @@ -144,3 +146,87 @@ func Check(args *skel.CmdArgs) error { return nil } + +func validateCniContainerInterface(intf types100.Interface, flatMode string, modeExpected string) error { + var link netlink.Link + var err error + + if intf.Name == "" { + return fmt.Errorf("container interface name missing in prevResult: %v", intf.Name) + } + link, err = netlink.LinkByName(intf.Name) + if err != nil { + return fmt.Errorf("container Interface name in prevResult: %s not found", intf.Name) + } + if intf.Sandbox == "" { + return fmt.Errorf("error: Container interface %s should not be in host namespace", link.Attrs().Name) + } + + switch flatMode { + case flv1.FlatModeMacvlan: + return validateMacvlanIface(intf, link, modeExpected) + case flv1.FlatModeIPvlan: + return validateIPvlanIface(intf, link, modeExpected) + } + return nil +} + +func validateMacvlanIface(intf types100.Interface, link netlink.Link, modeExpected string) error { + macv, isMacvlan := link.(*netlink.Macvlan) + if !isMacvlan { + return fmt.Errorf("error: Container interface %s not of type macvlan", link.Attrs().Name) + } + + mode, err := macvlan.ModeFromString(modeExpected) + if err != nil { + return err + } + if macv.Mode != mode { + currString, err := macvlan.ModeToString(macv.Mode) + if err != nil { + return err + } + confString, err := macvlan.ModeToString(mode) + if err != nil { + return err + } + return fmt.Errorf("container macvlan mode %s does not match expected value: %s", currString, confString) + } + + if intf.Mac != "" { + if intf.Mac != link.Attrs().HardwareAddr.String() { + return fmt.Errorf("interface %s Mac %s doesn't match container Mac: %s", intf.Name, intf.Mac, link.Attrs().HardwareAddr) + } + } + return nil +} + +func validateIPvlanIface(intf types100.Interface, link netlink.Link, modeExpected string) error { + ipv, ipIpvlan := link.(*netlink.IPVlan) + if !ipIpvlan { + return fmt.Errorf("error: Container interface %s not of type IPvlan", link.Attrs().Name) + } + + mode, err := ipvlan.ModeFromString(modeExpected) + if err != nil { + return err + } + if ipv.Mode != mode { + currString, err := ipvlan.ModeToString(ipv.Mode) + if err != nil { + return err + } + confString, err := ipvlan.ModeToString(mode) + if err != nil { + return err + } + return fmt.Errorf("container ipvlan mode %s does not match expected value: %s", currString, confString) + } + + if intf.Mac != "" { + if intf.Mac != link.Attrs().HardwareAddr.String() { + return fmt.Errorf("interface %s Mac %s doesn't match container Mac: %s", intf.Name, intf.Mac, link.Attrs().HardwareAddr) + } + } + return nil +}