diff --git a/cni/cni.go b/cni/cni.go index 4a58dcc1..92c29972 100644 --- a/cni/cni.go +++ b/cni/cni.go @@ -30,6 +30,25 @@ const ( // Supported CNI versions. var VersionsSupported = []string{"0.2.0", "0.3.0", "0.4.0", "1.0.0"} +// Aliases for the Windows CNI plugin binary names: +const ( + NatPluginName = "nat" + SdnBridgePluginName = "sdnbridge" + SdnOverlayPluginName = "sdnoverlay" + // SdnTunnelPluginName = "sdntunnel" +) + +// NOTE(aznashwan): this mapping between the names of binary releases of the WinCNI +// plugins and the underlying HCN network types is required for +// backwards-compatibility with callers which rely on the old plugin naming schemes. +// See: https://github.com/microsoft/windows-container-networking/issues/57 +var CniPluginNameToHcnTypeMap map[string]hcn.NetworkType = map[string]hcn.NetworkType{ + NatPluginName: hcn.NAT, + SdnBridgePluginName: hcn.L2Bridge, + SdnOverlayPluginName: hcn.Overlay, + // SdnTunnelPluginName: network.L2Tunnel, +} + type KVP struct { Name string `json:"name"` Value json.RawMessage `json:"value"` @@ -67,8 +86,8 @@ type IpamConfig struct { // Defined as per https://github.com/containernetworking/cni/blob/master/SPEC.md type NetworkConfig struct { CniVersion string `json:"cniVersion"` - Name string `json:"name"` // Name is the Network Name. We would also use this as the Type of HNS Network - Type string `json:"type"` // As per SPEC, Type is Name of the Binary + Name string `json:"name"` // Name is the Network Name. + Type hcn.NetworkType `json:"type"` // As per SPEC, Type is Name of the Binary Ipam IpamConfig `json:"ipam"` DNS cniTypes.DNS `json:"dns"` OptionalFlags OptionalFlags `json:"optionalFlags"` @@ -180,6 +199,12 @@ func ParseNetworkConfig(b []byte) (*NetworkConfig, error) { return nil, err } + hcnType, err := MapCniTypeToHcnType(config.Type) + if err != nil { + return nil, err + } + config.Type = hcnType + return &config, nil } @@ -252,7 +277,7 @@ func (config *NetworkConfig) GetNetworkInfo(podNamespace string) (ninfo *network ninfo = &network.NetworkInfo{ ID: config.Name, Name: config.Name, - Type: network.NetworkType(config.Type), + Type: config.Type, Subnets: subnets, InterfaceName: "", DNS: dnsSettings, @@ -494,3 +519,23 @@ func GetInterface(endpoint *network.EndpointInfo) Interface { Sandbox: "", } } + +// Maps the given CNI network config "type" field into the correct HNS network type. +func MapCniTypeToHcnType(typeArg hcn.NetworkType) (hcn.NetworkType, error) { + var mappedType *hcn.NetworkType = nil + for binaryName, netType := range CniPluginNameToHcnTypeMap { + if string(typeArg) == binaryName || typeArg == netType { + mappedType = &netType + break + } + } + + if mappedType == nil { + return hcn.NetworkType(""), fmt.Errorf("Unsupported CNI config 'type' %q. Options are the keys/values from: %v", typeArg, CniPluginNameToHcnTypeMap) + } + if *mappedType != typeArg { + logrus.Warnf("Provided CNI config 'type' %q will be mapped to %q", typeArg, *mappedType) + } + + return *mappedType, nil +} diff --git a/common/core/network.go b/common/core/network.go index d15dd2a4..ce560450 100644 --- a/common/core/network.go +++ b/common/core/network.go @@ -152,7 +152,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) { return err } - if nwConfig.Type != network.L2Bridge { + if nwConfig.Type != hcn.L2Bridge { logrus.Errorf("[cni-net] Dual stack can only be specified with l2bridge network: [%v].", nwConfig.Type) return errors.New("Dual stack specified with non l2bridge network") } diff --git a/network/network.go b/network/network.go index dc944ea1..c64881e9 100644 --- a/network/network.go +++ b/network/network.go @@ -11,16 +11,6 @@ import ( "github.com/Microsoft/hcsshim/hcn" ) -type NetworkType string - -const ( - NAT NetworkType = "NAT" - Overlay NetworkType = "Overlay" - Transparent NetworkType = "Transparent" - L2Tunnel NetworkType = "L2Tunnel" - L2Bridge NetworkType = "L2Bridge" -) - type DNSInfo struct { Nameservers []string Domain string @@ -32,7 +22,7 @@ type DNSInfo struct { type NetworkInfo struct { ID string Name string - Type NetworkType + Type hcn.NetworkType InterfaceName string Subnets []SubnetInfo DNS DNSInfo @@ -99,7 +89,7 @@ func GetNetworkInfoFromHostComputeNetwork(hcnNetwork *hcn.HostComputeNetwork) *N return &NetworkInfo{ ID: hcnNetwork.Id, Name: hcnNetwork.Name, - Type: NetworkType(hcnNetwork.Type), + Type: hcnNetwork.Type, // Note: HostComputeNetwork has NetAdapterNameNetworkPolicySetting instead of a NetworkAdapterName/InterfaceName field. InterfaceName: GetNetAdapterNameNetworkPolicySetting(hcnNetwork.Policies), Subnets: subnets, diff --git a/plugins/nat/nat_windows_test.go b/plugins/nat/nat_windows_test.go index 7fe24d36..c7893fa7 100644 --- a/plugins/nat/nat_windows_test.go +++ b/plugins/nat/nat_windows_test.go @@ -5,22 +5,23 @@ import ( "testing" "github.com/Microsoft/hcsshim/hcn" + "github.com/Microsoft/windows-container-networking/cni" util "github.com/Microsoft/windows-container-networking/test/utilities" ) var testDualStack bool var imageToUse string -func CreateNatTestNetwork() *hcn.HostComputeNetwork { +func CreateNatTestNetwork(t *testing.T) *hcn.HostComputeNetwork { ipams := util.GetDefaultIpams() - return util.CreateTestNetwork("natNet", "Nat", ipams, false) + return util.CreateTestNetwork(t, "natNet", cni.NatPluginName, ipams, false) } func TestNatCmdAdd(t *testing.T) { // t.Skip("Nat test is disabled for now.") testDualStack = (os.Getenv("TestDualStack") == "1") imageToUse = os.Getenv("ImageToUse") - testNetwork := CreateNatTestNetwork() - pt := util.MakeTestStruct(t, testNetwork, "nat", false, false, "", testDualStack, imageToUse) + testNetwork := CreateNatTestNetwork(t) + pt := util.MakeTestStruct(t, testNetwork, false, false, "", testDualStack, imageToUse) pt.RunAll(t) } diff --git a/plugins/sdnbridge/sdnbridge_windows_test.go b/plugins/sdnbridge/sdnbridge_windows_test.go index fb8b81b7..65a06f5a 100644 --- a/plugins/sdnbridge/sdnbridge_windows_test.go +++ b/plugins/sdnbridge/sdnbridge_windows_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/Microsoft/hcsshim/hcn" + "github.com/Microsoft/windows-container-networking/cni" util "github.com/Microsoft/windows-container-networking/test/utilities" "os" @@ -12,20 +13,20 @@ import ( var testDualStack bool var imageToUse string -func CreateBridgeTestNetwork() *hcn.HostComputeNetwork { +func CreateBridgeTestNetwork(t *testing.T) *hcn.HostComputeNetwork { ipams := util.GetDefaultIpams() if testDualStack { ipams = append(ipams, util.GetDefaultIpv6Ipams()...) } - return util.CreateTestNetwork("bridgeNet", "L2Bridge", ipams, true) + return util.CreateTestNetwork(t, "bridgeNet", cni.SdnBridgePluginName, ipams, true) } func TestBridgeCmdAdd(t *testing.T) { // t.Skip("Bridge test is disabled for now.") testDualStack = (os.Getenv("TestDualStack") == "1") imageToUse = os.Getenv("ImageToUse") - testNetwork := CreateBridgeTestNetwork() - pt := util.MakeTestStruct(t, testNetwork, "L2Bridge", true, true, "", testDualStack, imageToUse) + testNetwork := CreateBridgeTestNetwork(t) + pt := util.MakeTestStruct(t, testNetwork, true, true, "", testDualStack, imageToUse) pt.Ipv6Url = os.Getenv("Ipv6UrlToUse") pt.RunAll(t) } diff --git a/plugins/sdnoverlay/sdnoverlay_windows_test.go b/plugins/sdnoverlay/sdnoverlay_windows_test.go index eb5ab374..36691c29 100644 --- a/plugins/sdnoverlay/sdnoverlay_windows_test.go +++ b/plugins/sdnoverlay/sdnoverlay_windows_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/Microsoft/hcsshim/hcn" + "github.com/Microsoft/windows-container-networking/cni" util "github.com/Microsoft/windows-container-networking/test/utilities" ) @@ -28,17 +29,17 @@ func GetVsidPol() []json.RawMessage { return []json.RawMessage{vsidPolRaw} } -func CreateOverlayTestNetwork() *hcn.HostComputeNetwork { +func CreateOverlayTestNetwork(t *testing.T) *hcn.HostComputeNetwork { ipams := util.GetDefaultIpams() ipams[0].Subnets[0].Policies = GetVsidPol() - return util.CreateTestNetwork("overlayNet", "Overlay", ipams, true) + return util.CreateTestNetwork(t, "overlayNet", cni.SdnOverlayPluginName, ipams, true) } func TestOverlayCmdAdd(t *testing.T) { // t.Skip("Overlay test is disabled for now.") testDualStack = (os.Getenv("TestDualStack") == "1") imageToUse = os.Getenv("ImageToUse") - testNetwork := CreateOverlayTestNetwork() - pt := util.MakeTestStruct(t, testNetwork, "Overlay", true, false, "", testDualStack, imageToUse) + testNetwork := CreateOverlayTestNetwork(t) + pt := util.MakeTestStruct(t, testNetwork, true, false, "", testDualStack, imageToUse) pt.RunAll(t) } diff --git a/test/utilities/connectivity_testing.go b/test/utilities/connectivity_testing.go index 27c66c67..09a5b7a7 100644 --- a/test/utilities/connectivity_testing.go +++ b/test/utilities/connectivity_testing.go @@ -88,32 +88,52 @@ func CreateNetConfIpam(cidr string) cni.IpamConfig { return testIpam } -func CreateNetworkConf(cniVersion string, name string, pluginType string, - dns *cniTypes.DNS, addArgs []cni.KVP, gatewayPrefix string) *cni.NetworkConfig { +func CreateNetworkConf(t *testing.T, cniVersion string, name string, pluginType hcn.NetworkType, + dns *cniTypes.DNS, addArgs []cni.KVP, gatewayPrefix string) (*cni.NetworkConfig, error) { + + mappedType, err := cni.MapCniTypeToHcnType(pluginType) + if err != nil { + return nil, err + } + + if pluginType != mappedType { + t.Logf("WARN: supplied network plugin type %q was mapped to HCN network type %q", pluginType, mappedType) + } + netConf := cni.NetworkConfig{ CniVersion: cniVersion, Name: name, Ipam: CreateNetConfIpam(gatewayPrefix), - Type: pluginType, + Type: mappedType, DNS: *dns, AdditionalArgs: addArgs, } - return &netConf + return &netConf, nil } func CreateDualStackNetworkConf( + t *testing.T, cniVersion string, name string, - pluginType string, + pluginType hcn.NetworkType, dns *cniTypes.DNS, addArgs []cni.KVP, gatewayPrefixv4 string, - gatewayPrefixv6 string) *cni.NetworkConfig { + gatewayPrefixv6 string) (*cni.NetworkConfig, error) { + + mappedType, err := cni.MapCniTypeToHcnType(pluginType) + if err != nil { + return nil, err + } + + if pluginType != mappedType { + t.Logf("WARN: supplied network plugin type %q was mapped to HCN network type %q", pluginType, mappedType) + } netConf := cni.NetworkConfig{ CniVersion: cniVersion, Name: name, - Type: pluginType, + Type: mappedType, DNS: *dns, AdditionalArgs: addArgs, } @@ -139,7 +159,7 @@ func CreateDualStackNetworkConf( netConf.AdditionalRoutes = append(netConf.AdditionalRoutes, testRoute) - return &netConf + return &netConf, nil } func GetDefaultIpams() []hcn.Ipam { @@ -289,14 +309,24 @@ func CreateGatewayEp(t *testing.T, networkId string, ipAddress string, ipv6Adres return nil } -func CreateTestNetwork(name string, netType string, ipams []hcn.Ipam, tryGetNetAdapter bool) *hcn.HostComputeNetwork { +func CreateTestNetwork(t *testing.T, name string, netType string, ipams []hcn.Ipam, tryGetNetAdapter bool) *hcn.HostComputeNetwork { + hcnNetType := hcn.NetworkType(netType) + mappedType, err := cni.MapCniTypeToHcnType(hcnNetType) + if err != nil { + t.Errorf("Failed to map testing network type %q to HCN network type: %v", netType, err) + } + + if mappedType != hcnNetType { + t.Logf("WARN: testing network type %q was mapped to HCN network type %q", netType, mappedType) + } + network := &hcn.HostComputeNetwork{ SchemaVersion: hcn.SchemaVersion{ Major: 2, Minor: 0, }, Name: name, - Type: hcn.NetworkType(netType), + Type: mappedType, Ipams: ipams, } @@ -312,7 +342,6 @@ func CreateTestNetwork(name string, netType string, ipams []hcn.Ipam, tryGetNetA func MakeTestStruct( t *testing.T, testNetwork *hcn.HostComputeNetwork, - pluginType string, epPols bool, needGW bool, cid string, @@ -352,11 +381,15 @@ func MakeTestStruct( var netConf *cni.NetworkConfig if !testDualStack { - netConf = CreateNetworkConf(defaultCniVersion, testNetwork.Name, pluginType, dns, addArgs, netConfPrefix) + if netConf, err = CreateNetworkConf(t, defaultCniVersion, testNetwork.Name, testNetwork.Type, dns, addArgs, netConfPrefix); err != nil { + t.Errorf("Failed to create testing network config: %v", err) + return nil + } } else { - netConfPrefixv6 := "fd00::101/64" - netConf = CreateDualStackNetworkConf(defaultCniVersion, testNetwork.Name, pluginType, dns, addArgs, netConfPrefix, netConfPrefixv6) + if netConf, err = CreateDualStackNetworkConf(t, defaultCniVersion, testNetwork.Name, testNetwork.Type, dns, addArgs, netConfPrefix, netConfPrefixv6); err != nil { + return nil + } } netJson, _ := json.Marshal(netConf)