Initial changes for ipv6 support for l2bridge network
This commit is contained in:
Родитель
45dfaf4235
Коммит
4077d162c7
105
cni/cni.go
105
cni/cni.go
|
@ -107,7 +107,7 @@ type OptionalFlags struct {
|
|||
LocalRoutePortMapping bool `json:"localRoutedPortMapping"`
|
||||
AllowAclPortMapping bool `json:"allowAclPortMapping"`
|
||||
ForceBridgeGateway bool `json:"forceBridgeGateway"` // Intended to be temporary workaround
|
||||
|
||||
EnableDualStack bool `json:"enableDualStack"`
|
||||
}
|
||||
|
||||
func (r *Result) Print() {
|
||||
|
@ -194,6 +194,7 @@ func (config *NetworkConfig) Serialize() []byte {
|
|||
// GetNetworkInfo from the NetworkConfig
|
||||
func (config *NetworkConfig) GetNetworkInfo(podNamespace string) *network.NetworkInfo {
|
||||
var subnets []network.SubnetInfo
|
||||
// Note the code below is looking inside the ipam specific configuration.
|
||||
if config.Ipam.Subnet != "" {
|
||||
ip, s, _ := net.ParseCIDR(config.Ipam.Subnet)
|
||||
gatewayIP := ip.To4()
|
||||
|
@ -313,7 +314,13 @@ func (config *NetworkConfig) GetEndpointInfo(
|
|||
}
|
||||
|
||||
if len(networkInfo.Subnets) > 0 {
|
||||
// This subnet is not used when constructing
|
||||
// hcn.HostComputeEndpoint from EndpointInfo
|
||||
epInfo.Subnet = networkInfo.Subnets[0].AddressPrefix
|
||||
// Gateway field (below) will be updated to the ipam allocated value
|
||||
// (if applicable) in allocateIpam
|
||||
// The Gateway6 field (ipv6 gatweay) is not derived like this and
|
||||
// must be supplied through the ipam.
|
||||
epInfo.Gateway = networkInfo.Subnets[0].GatewayAddress
|
||||
}
|
||||
|
||||
|
@ -346,24 +353,64 @@ func (config *NetworkConfig) GetEndpointInfo(
|
|||
}
|
||||
|
||||
// GetCurrResult gets the result object
|
||||
func GetCurrResult(network *network.NetworkInfo, endpoint *network.EndpointInfo, ifname string) cniTypesCurr.Result {
|
||||
func GetCurrResult(network *network.NetworkInfo, endpoint *network.EndpointInfo, ifname string, cniConfig *NetworkConfig) cniTypesCurr.Result {
|
||||
result := cniTypesCurr.Result{
|
||||
IPs: []*cniTypesCurr.IPConfig{},
|
||||
Routes: []*cniTypes.Route{}}
|
||||
|
||||
var iFace = GetInterface(endpoint)
|
||||
var ip = GetIP(network, endpoint)
|
||||
ip.InterfaceIndex = 0
|
||||
|
||||
cIP := cniTypesCurr.IPConfig{
|
||||
Version: ip.Version,
|
||||
Address: net.IPNet{
|
||||
IP: ip.Address.IP,
|
||||
Mask: ip.Address.Mask},
|
||||
Gateway: ip.Gateway,
|
||||
Interface: &ip.InterfaceIndex,
|
||||
}
|
||||
result.IPs = append(result.IPs, &cIP)
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
|
||||
var ip = GetIP(network, endpoint)
|
||||
ip.InterfaceIndex = 0
|
||||
|
||||
cIP := cniTypesCurr.IPConfig{
|
||||
Version: ip.Version,
|
||||
Address: net.IPNet{
|
||||
IP: ip.Address.IP,
|
||||
Mask: ip.Address.Mask},
|
||||
Gateway: ip.Gateway,
|
||||
Interface: &ip.InterfaceIndex,
|
||||
}
|
||||
result.IPs = append(result.IPs, &cIP)
|
||||
|
||||
} else {
|
||||
|
||||
ip4, ip6 := GetDualStackAddresses(endpoint)
|
||||
|
||||
if ip4 != nil {
|
||||
|
||||
ip4.InterfaceIndex = 0
|
||||
|
||||
cIP4 := cniTypesCurr.IPConfig{
|
||||
Version: ip4.Version,
|
||||
Address: net.IPNet{
|
||||
IP: ip4.Address.IP,
|
||||
Mask: ip4.Address.Mask},
|
||||
Gateway: ip4.Gateway,
|
||||
Interface: &ip4.InterfaceIndex,
|
||||
}
|
||||
|
||||
result.IPs = append(result.IPs, &cIP4)
|
||||
}
|
||||
|
||||
if ip6 != nil {
|
||||
|
||||
ip6.InterfaceIndex = 0
|
||||
|
||||
cIP6 := cniTypesCurr.IPConfig{
|
||||
Version: ip6.Version,
|
||||
Address: net.IPNet{
|
||||
IP: ip6.Address.IP,
|
||||
Mask: ip6.Address.Mask},
|
||||
Gateway: ip6.Gateway,
|
||||
Interface: &ip6.InterfaceIndex,
|
||||
}
|
||||
|
||||
result.IPs = append(result.IPs, &cIP6)
|
||||
}
|
||||
}
|
||||
|
||||
// Add Interfaces to result.
|
||||
iface := &cniTypesCurr.Interface{
|
||||
|
@ -390,6 +437,38 @@ func GetIP(network *network.NetworkInfo, endpoint *network.EndpointInfo) IP {
|
|||
}
|
||||
}
|
||||
|
||||
// GetDualStackAddresses returns the IPv4 and IPv6 addresses for the endpoint
|
||||
func GetDualStackAddresses(endpoint *network.EndpointInfo) (*IP, *IP) {
|
||||
|
||||
var ip4 *IP
|
||||
var ip6 *IP
|
||||
|
||||
if endpoint.IPAddress != nil {
|
||||
|
||||
ip4address := net.IPNet{}
|
||||
ip4address.IP = endpoint.IPAddress
|
||||
ip4address.Mask = endpoint.IP4Mask
|
||||
|
||||
ip4 = &IP{
|
||||
Version: "4",
|
||||
Address: cniTypes.IPNet(ip4address),
|
||||
Gateway: endpoint.Gateway,
|
||||
InterfaceIndex: 0,
|
||||
}
|
||||
}
|
||||
|
||||
if endpoint.IPAddress6.IP != nil {
|
||||
ip6 = &IP{
|
||||
Version: "6",
|
||||
Address: cniTypes.IPNet(endpoint.IPAddress6),
|
||||
Gateway: endpoint.Gateway6,
|
||||
InterfaceIndex: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return ip4, ip6
|
||||
}
|
||||
|
||||
// GetInterface returns the interface for endpoint
|
||||
func GetInterface(endpoint *network.EndpointInfo) Interface {
|
||||
return Interface{
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/Microsoft/windows-container-networking/cni"
|
||||
"github.com/Microsoft/windows-container-networking/common"
|
||||
"github.com/Microsoft/windows-container-networking/network"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
|
@ -94,6 +95,9 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
logrus.Debugf("[cni-net] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}.",
|
||||
args.ContainerID, args.Netns, args.IfName, args.Args, args.Path)
|
||||
|
||||
var err error
|
||||
var nwConfig *network.NetworkInfo
|
||||
|
||||
podConfig, err := cni.ParseCniArgs(args.Args)
|
||||
k8sNamespace := ""
|
||||
if err == nil {
|
||||
|
@ -109,6 +113,12 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
|
||||
logrus.Debugf("[cni-net] Read network configuration %+v.", cniConfig)
|
||||
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
logrus.Infof("[cni-net] Dual stack is disabled")
|
||||
} else {
|
||||
logrus.Infof("[cni-net] Dual stack is enabled")
|
||||
}
|
||||
|
||||
// Convert cniConfig to NetworkInfo
|
||||
// We don't set namespace, setting namespace is not valid for EP creation
|
||||
networkInfo := cniConfig.GetNetworkInfo(k8sNamespace)
|
||||
|
@ -118,18 +128,30 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
return err
|
||||
}
|
||||
|
||||
epInfo.DualStack = cniConfig.OptionalFlags.EnableDualStack
|
||||
|
||||
// Check for missing namespace
|
||||
if args.Netns == "" {
|
||||
logrus.Errorf("[cni-net] Missing Namespace, cannot add, endpoint : [%v].", epInfo)
|
||||
return errors.New("cannot create endpoint without a namespace")
|
||||
}
|
||||
|
||||
nwConfig, err := getOrCreateNetwork(plugin, networkInfo, cniConfig)
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
nwConfig, err = getOrCreateNetwork(plugin, networkInfo, cniConfig)
|
||||
} else {
|
||||
// The network must be created beforehand
|
||||
nwConfig, err = plugin.nm.GetNetworkByName(cniConfig.Name)
|
||||
|
||||
if nwConfig.Type != network.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")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsEndpoint, err := plugin.nm.GetEndpointByName(epInfo.Name)
|
||||
hnsEndpoint, err := plugin.nm.GetEndpointByName(epInfo.Name, cniConfig.OptionalFlags.EnableDualStack)
|
||||
if hnsEndpoint != nil {
|
||||
logrus.Infof("[cni-net] Endpoint %+v already exists for network %v.", hnsEndpoint, nwConfig.ID)
|
||||
// Endpoint exists
|
||||
|
@ -139,7 +161,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
// Do not allow creation of more endpoints on same network
|
||||
logrus.Debugf("[cni-net] Endpoint exists on same network, ignoring add : [%v].", epInfo)
|
||||
// Convert result to the requested CNI version.
|
||||
res := cni.GetCurrResult(nwConfig, hnsEndpoint, args.IfName)
|
||||
res := cni.GetCurrResult(nwConfig, hnsEndpoint, args.IfName, cniConfig)
|
||||
result, err := res.GetAsVersion(cniConfig.CniVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -152,9 +174,14 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
logrus.Debugf("[cni-net] Creating a new Endpoint")
|
||||
}
|
||||
|
||||
// If Ipam was provided, allocate a pool and obtain V4 address
|
||||
// If Ipam was provided, allocate a pool and obtain address
|
||||
if cniConfig.Ipam.Type != "" {
|
||||
err = allocateIpam(networkInfo, epInfo, cniConfig, cniConfig.OptionalFlags.ForceBridgeGateway)
|
||||
err = allocateIpam(
|
||||
networkInfo,
|
||||
epInfo,
|
||||
cniConfig,
|
||||
cniConfig.OptionalFlags.ForceBridgeGateway,
|
||||
args.StdinData)
|
||||
if err != nil {
|
||||
// Error was logged by allocateIpam.
|
||||
return err
|
||||
|
@ -163,7 +190,8 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
if resultError != nil {
|
||||
logrus.Debugf("[cni-net] failure during ADD cleaning-up ipam, %v", err)
|
||||
os.Setenv("CNI_COMMAND", "DEL")
|
||||
err := deallocateIpam(cniConfig)
|
||||
err := deallocateIpam(cniConfig, args.StdinData)
|
||||
|
||||
os.Setenv("CNI_COMMAND", "ADD")
|
||||
if err != nil {
|
||||
logrus.Debugf("[cni-net] failed during ADD command for clean-up delegate delete call, %v", err)
|
||||
|
@ -182,13 +210,12 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
|
|||
}
|
||||
|
||||
// Convert result to the requested CNI version.
|
||||
res := cni.GetCurrResult(nwConfig, epInfo, args.IfName)
|
||||
res := cni.GetCurrResult(nwConfig, epInfo, args.IfName, cniConfig)
|
||||
result, err := res.GetAsVersion(cniConfig.CniVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// result := cni.GetResult020(nwConfig, epInfo)
|
||||
result.Print()
|
||||
logrus.Debugf("[cni-net] result: %v", result.String())
|
||||
return nil
|
||||
|
@ -199,11 +226,21 @@ func allocateIpam(
|
|||
networkInfo *network.NetworkInfo,
|
||||
endpointInfo *network.EndpointInfo,
|
||||
cniConfig *cni.NetworkConfig,
|
||||
forceBridgeGateway bool) error {
|
||||
forceBridgeGateway bool,
|
||||
networkConfByteStream []byte) error {
|
||||
var result cniTypes.Result
|
||||
var resultImpl *cniTypesImpl.Result
|
||||
var err error
|
||||
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
// It seems the right thing would be to pass the original byte stream instead of the one
|
||||
// which cni parsed into NetworkConfig. However to preserve compatibility continue
|
||||
// the current behavior when dual stack is not enabled
|
||||
result, err = invoke.DelegateAdd(context.TODO(), cniConfig.Ipam.Type, cniConfig.Serialize(), nil)
|
||||
} else {
|
||||
result, err = invoke.DelegateAdd(context.TODO(), cniConfig.Ipam.Type, networkConfByteStream, nil)
|
||||
}
|
||||
|
||||
result, err := invoke.DelegateAdd(context.TODO(), cniConfig.Ipam.Type, cniConfig.Serialize(), nil)
|
||||
if err != nil {
|
||||
logrus.Infof("[cni-net] Failed to allocate pool, err:%v.", err)
|
||||
return err
|
||||
|
@ -216,33 +253,74 @@ func allocateIpam(
|
|||
}
|
||||
|
||||
logrus.Debugf("[cni-net] IPAM plugin returned result %v.", resultImpl)
|
||||
// Derive the subnet from allocated IP address.
|
||||
if resultImpl.IP4 != nil {
|
||||
var subnetInfo = network.SubnetInfo{
|
||||
AddressPrefix: resultImpl.IP4.IP,
|
||||
GatewayAddress: resultImpl.IP4.Gateway,
|
||||
}
|
||||
networkInfo.Subnets = append(networkInfo.Subnets, subnetInfo)
|
||||
endpointInfo.IPAddress = resultImpl.IP4.IP.IP
|
||||
endpointInfo.Gateway = resultImpl.IP4.Gateway
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
// Derive the subnet from allocated IP address.
|
||||
if resultImpl.IP4 != nil {
|
||||
var subnetInfo = network.SubnetInfo{
|
||||
AddressPrefix: resultImpl.IP4.IP,
|
||||
GatewayAddress: resultImpl.IP4.Gateway,
|
||||
}
|
||||
|
||||
if forceBridgeGateway == true {
|
||||
endpointInfo.Gateway = resultImpl.IP4.IP.IP.Mask(resultImpl.IP4.IP.Mask)
|
||||
endpointInfo.Gateway[3] = 2
|
||||
networkInfo.Subnets = append(networkInfo.Subnets, subnetInfo)
|
||||
endpointInfo.IPAddress = resultImpl.IP4.IP.IP
|
||||
endpointInfo.Gateway = resultImpl.IP4.Gateway
|
||||
|
||||
if forceBridgeGateway == true {
|
||||
endpointInfo.Gateway = resultImpl.IP4.IP.IP.Mask(resultImpl.IP4.IP.Mask)
|
||||
endpointInfo.Gateway[3] = 2
|
||||
}
|
||||
|
||||
endpointInfo.Subnet = resultImpl.IP4.IP
|
||||
|
||||
for _, route := range resultImpl.IP4.Routes {
|
||||
// Only default route is populated when calling HNS, and the below information is not passed
|
||||
endpointInfo.Routes = append(endpointInfo.Routes, network.RouteInfo{Destination: route.Dst, Gateway: route.GW})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if resultImpl.IP4 != nil {
|
||||
|
||||
endpointInfo.IPAddress = resultImpl.IP4.IP.IP
|
||||
endpointInfo.IP4Mask = resultImpl.IP4.IP.Mask
|
||||
endpointInfo.Gateway = resultImpl.IP4.Gateway
|
||||
|
||||
if forceBridgeGateway == true {
|
||||
endpointInfo.Gateway = resultImpl.IP4.IP.IP.Mask(resultImpl.IP4.IP.Mask)
|
||||
endpointInfo.Gateway[3] = 2
|
||||
}
|
||||
|
||||
for _, route := range resultImpl.IP4.Routes {
|
||||
// Only default route is populated when calling HNS, and the below information is not being passed right now
|
||||
endpointInfo.Routes = append(endpointInfo.Routes, network.RouteInfo{Destination: route.Dst, Gateway: route.GW})
|
||||
}
|
||||
}
|
||||
|
||||
endpointInfo.Subnet = resultImpl.IP4.IP
|
||||
if resultImpl.IP6 != nil {
|
||||
|
||||
for _, route := range resultImpl.IP4.Routes {
|
||||
endpointInfo.Routes = append(endpointInfo.Routes, network.RouteInfo{Destination: route.Dst, Gateway: route.GW})
|
||||
endpointInfo.IPAddress6 = resultImpl.IP6.IP
|
||||
endpointInfo.Gateway6 = resultImpl.IP6.Gateway
|
||||
|
||||
for _, route := range resultImpl.IP6.Routes {
|
||||
// Only default route is populated when calling HNS, and the below information is not being passed right now
|
||||
endpointInfo.Routes = append(endpointInfo.Routes, network.RouteInfo{Destination: route.Dst, Gateway: route.GW})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// deallocateIpam performs the cleanup necessary for removing an ipam
|
||||
func deallocateIpam(cniConfig *cni.NetworkConfig) error {
|
||||
return invoke.DelegateDel(context.TODO(), cniConfig.Ipam.Type, cniConfig.Serialize(), nil)
|
||||
func deallocateIpam(cniConfig *cni.NetworkConfig, networkConfByteStream []byte) error {
|
||||
|
||||
if cniConfig.OptionalFlags.EnableDualStack == false {
|
||||
logrus.Infof("[cni-net] Delete from ipam when dual stack is disabled")
|
||||
return invoke.DelegateDel(context.TODO(), cniConfig.Ipam.Type, cniConfig.Serialize(), nil)
|
||||
} else {
|
||||
logrus.Infof("[cni-net] Delete from ipam when dual stack is enabled")
|
||||
return invoke.DelegateDel(context.TODO(), cniConfig.Ipam.Type, networkConfByteStream, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// getOrCreateNetwork
|
||||
|
@ -294,7 +372,8 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error {
|
|||
|
||||
if cniConfig.Ipam.Type != "" {
|
||||
logrus.Debugf("[cni-net] Ipam detected, executing delegate call to delete ipam, %v", cniConfig.Ipam)
|
||||
err := deallocateIpam(cniConfig)
|
||||
err := deallocateIpam(cniConfig, args.StdinData)
|
||||
|
||||
if err != nil {
|
||||
logrus.Debugf("[cni-net] Failed during delete call for ipam, %v", err)
|
||||
return fmt.Errorf("ipam deletion failed, %v", err)
|
||||
|
@ -307,7 +386,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpointInfo, err := plugin.nm.GetEndpointByName(epInfo.Name)
|
||||
endpointInfo, err := plugin.nm.GetEndpointByName(epInfo.Name, cniConfig.OptionalFlags.EnableDualStack)
|
||||
if err != nil {
|
||||
if hcn.IsNotFoundError(err) {
|
||||
logrus.Debugf("[cni-net] Endpoint was not found error, err:%v", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ package common
|
|||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -22,3 +23,9 @@ func LogNetworkInterfaces() {
|
|||
logrus.Debugf("[net] Network interface: %+v with IP addresses: %+v", iface, addrs)
|
||||
}
|
||||
}
|
||||
|
||||
func GetAddressAsCidr(ip string, prefix uint8) string {
|
||||
|
||||
return ip + string('/') + strconv.FormatUint(uint64(prefix), 10)
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"cniVersion": "0.2.0",
|
||||
"name": "winl2bridge",
|
||||
"type": "sdnbridge",
|
||||
"master": "Ethernet",
|
||||
"capabilities": {
|
||||
"portMappings": true,
|
||||
"dnsCapabilities": true
|
||||
},
|
||||
"optionalFlags": {
|
||||
"localRoutedPortMapping": true,
|
||||
"allowAclPortMapping": true,
|
||||
"enableDualStack": true
|
||||
},
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"ranges": [
|
||||
[
|
||||
{
|
||||
"subnet": "192.168.1.0/24",
|
||||
"rangeStart": "192.168.1.10",
|
||||
"rangeEnd": "192.168.1.50",
|
||||
"gateway": "192.168.1.2"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"subnet": "fd00::100/120",
|
||||
"rangeStart": "fd00::102",
|
||||
"rangeEnd": "fd00::1fe",
|
||||
"gateway": "fd00::101"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"Nameservers": [
|
||||
"10.127.130.7"
|
||||
],
|
||||
"Search": [
|
||||
"svc.cluster.local"
|
||||
]
|
||||
},
|
||||
"AdditionalArgs": [
|
||||
{
|
||||
"Name": "EndpointPolicy",
|
||||
"Value": {
|
||||
"Type": "OutBoundNAT",
|
||||
"Settings": {
|
||||
"Exceptions": [
|
||||
"192.168.0.0/16",
|
||||
"11.0.0.0/8",
|
||||
"10.124.24.0/23"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "EndpointPolicy",
|
||||
"Value": {
|
||||
"Type": "OutBoundNAT",
|
||||
"Settings": {
|
||||
"VirtualIP": "fc00::123",
|
||||
"Destinations": [
|
||||
"fd01::192",
|
||||
"fd01::193"
|
||||
],
|
||||
"Exceptions": [
|
||||
"fd03::100/120",
|
||||
"fd04::100/120"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "EndpointPolicy",
|
||||
"Value": {
|
||||
"Type": "SDNRoute",
|
||||
"Settings": {
|
||||
"DestinationPrefix": "11.0.0.0/8",
|
||||
"NeedEncap": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "EndpointPolicy",
|
||||
"Value": {
|
||||
"Type": "SDNRoute",
|
||||
"Settings": {
|
||||
"DestinationPrefix": "fd00::200/120",
|
||||
"NeedEncap": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -6,6 +6,7 @@ package network
|
|||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"github.com/Microsoft/windows-container-networking/common"
|
||||
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
)
|
||||
|
@ -18,13 +19,17 @@ type EndpointInfo struct {
|
|||
NetworkID string
|
||||
NamespaceID string
|
||||
IPAddress net.IP
|
||||
IP4Mask net.IPMask // Used when dual stack is enabled
|
||||
IPAddress6 net.IPNet
|
||||
MacAddress net.HardwareAddr
|
||||
Gateway net.IP
|
||||
Gateway6 net.IP
|
||||
Routes []RouteInfo
|
||||
Policies []Policy
|
||||
Subnet net.IPNet
|
||||
DNS DNSInfo
|
||||
ContainerID string
|
||||
DualStack bool
|
||||
}
|
||||
|
||||
// RouteInfo contains information about an IP route.
|
||||
|
@ -38,20 +43,45 @@ func (endpoint *EndpointInfo) GetHostComputeEndpoint() *hcn.HostComputeEndpoint
|
|||
// Check for nil on address objects.
|
||||
ipAddr := ""
|
||||
ipConfig := []hcn.IpConfig{}
|
||||
routes := []hcn.Route{}
|
||||
|
||||
if endpoint.IPAddress != nil {
|
||||
ipAddr = endpoint.IPAddress.String()
|
||||
ipConfig = append(ipConfig, hcn.IpConfig{
|
||||
IpAddress: ipAddr,
|
||||
})
|
||||
}
|
||||
|
||||
if endpoint.IPAddress6.IP != nil {
|
||||
ipAddr = endpoint.IPAddress6.IP.String()
|
||||
ipConfig = append(ipConfig, hcn.IpConfig{
|
||||
IpAddress: ipAddr,
|
||||
})
|
||||
}
|
||||
|
||||
macAddr := ""
|
||||
if endpoint.MacAddress != nil {
|
||||
macAddr = endpoint.MacAddress.String()
|
||||
}
|
||||
|
||||
gwAddr := ""
|
||||
if endpoint.Gateway != nil {
|
||||
gwAddr = endpoint.Gateway.String()
|
||||
}
|
||||
|
||||
routes = append(routes, hcn.Route{
|
||||
NextHop: gwAddr,
|
||||
DestinationPrefix: "0.0.0.0/0",
|
||||
})
|
||||
|
||||
if endpoint.Gateway6 != nil {
|
||||
gwAddr6 := endpoint.Gateway6.String()
|
||||
routes = append(routes, hcn.Route{
|
||||
NextHop: gwAddr6,
|
||||
DestinationPrefix: "::/0",
|
||||
})
|
||||
}
|
||||
|
||||
return &hcn.HostComputeEndpoint{
|
||||
Name: endpoint.Name,
|
||||
Id: endpoint.ID,
|
||||
|
@ -64,12 +94,7 @@ func (endpoint *EndpointInfo) GetHostComputeEndpoint() *hcn.HostComputeEndpoint
|
|||
Options: endpoint.DNS.Options,
|
||||
},
|
||||
MacAddress: macAddr,
|
||||
Routes: []hcn.Route{
|
||||
{
|
||||
NextHop: gwAddr,
|
||||
DestinationPrefix: "0.0.0.0/0",
|
||||
},
|
||||
},
|
||||
Routes: routes,
|
||||
IpConfigurations: ipConfig,
|
||||
SchemaVersion: hcn.SchemaVersion{
|
||||
Major: 2,
|
||||
|
@ -80,17 +105,71 @@ func (endpoint *EndpointInfo) GetHostComputeEndpoint() *hcn.HostComputeEndpoint
|
|||
}
|
||||
|
||||
// GetEndpointInfoFromHostComputeEndpoint converts HostComputeEndpoint to CNI EndpointInfo.
|
||||
func GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint *hcn.HostComputeEndpoint) *EndpointInfo {
|
||||
func GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint *hcn.HostComputeEndpoint, withIpv6 bool) *EndpointInfo {
|
||||
// Ignore empty MAC, GW, and IP.
|
||||
macAddr, _ := net.ParseMAC(hcnEndpoint.MacAddress)
|
||||
var gwAddr net.IP
|
||||
if len(hcnEndpoint.Routes) > 0 {
|
||||
gwAddr = net.ParseIP(hcnEndpoint.Routes[0].NextHop)
|
||||
}
|
||||
var ipAddr net.IP
|
||||
if len(hcnEndpoint.IpConfigurations) > 0 {
|
||||
ipAddr = net.ParseIP(hcnEndpoint.IpConfigurations[0].IpAddress)
|
||||
var gwAddr6 net.IP
|
||||
var ipAddr4 net.IPNet
|
||||
var ipAddr6 net.IPNet
|
||||
|
||||
if withIpv6 == false {
|
||||
|
||||
if len(hcnEndpoint.Routes) > 0 {
|
||||
gwAddr = net.ParseIP(hcnEndpoint.Routes[0].NextHop)
|
||||
}
|
||||
|
||||
if len(hcnEndpoint.IpConfigurations) > 0 {
|
||||
ipAddr4.IP = net.ParseIP(hcnEndpoint.IpConfigurations[0].IpAddress)
|
||||
}
|
||||
} else {
|
||||
var ip4found bool
|
||||
var ip6found bool
|
||||
|
||||
for _, addr := range hcnEndpoint.IpConfigurations {
|
||||
if net.ParseIP(addr.IpAddress).To4() == nil &&
|
||||
ip6found == false {
|
||||
ip, mask, _ := net.ParseCIDR(common.GetAddressAsCidr(addr.IpAddress, addr.PrefixLength))
|
||||
ipAddr6.IP = ip
|
||||
ipAddr6.Mask = mask.Mask
|
||||
ip6found = true
|
||||
} else {
|
||||
if ip4found == false {
|
||||
ip, mask, _ := net.ParseCIDR(common.GetAddressAsCidr(addr.IpAddress, addr.PrefixLength))
|
||||
ipAddr4.IP = ip
|
||||
ipAddr4.Mask = mask.Mask
|
||||
ip4found = true
|
||||
}
|
||||
}
|
||||
|
||||
if ip4found && ip6found {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ip4found = false
|
||||
ip6found = false
|
||||
|
||||
for _, r := range hcnEndpoint.Routes {
|
||||
|
||||
if net.ParseIP(r.NextHop).To4() == nil &&
|
||||
ip6found == false {
|
||||
gwAddr6 = net.ParseIP(r.NextHop)
|
||||
ip6found = true
|
||||
} else {
|
||||
if ip4found == false {
|
||||
gwAddr = net.ParseIP(r.NextHop)
|
||||
ip4found = true
|
||||
}
|
||||
}
|
||||
|
||||
if ip4found && ip6found {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return &EndpointInfo{
|
||||
Name: hcnEndpoint.Name,
|
||||
ID: hcnEndpoint.Id,
|
||||
|
@ -104,9 +183,13 @@ func GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint *hcn.HostComputeEndpoint
|
|||
},
|
||||
MacAddress: macAddr,
|
||||
Gateway: gwAddr,
|
||||
IPAddress: ipAddr,
|
||||
IPAddress: ipAddr4.IP,
|
||||
IP4Mask: ipAddr4.Mask,
|
||||
Gateway6: gwAddr6,
|
||||
IPAddress6: ipAddr6,
|
||||
Policies: GetEndpointPoliciesFromHostComputePolicies(hcnEndpoint.Policies),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// GetEndpointPoliciesFromHostComputePolicies converts HCN Endpoint policy into CNI Policy objects.
|
||||
|
|
|
@ -31,8 +31,8 @@ type Manager interface {
|
|||
// Endpoint
|
||||
CreateEndpoint(networkID string, epInfo *EndpointInfo, namespaceID string) (*EndpointInfo, error)
|
||||
DeleteEndpoint(endpointID string) error
|
||||
GetEndpoint(endpointID string) (*EndpointInfo, error)
|
||||
GetEndpointByName(endpointName string) (*EndpointInfo, error)
|
||||
GetEndpoint(endpointID string, withIpv6 bool) (*EndpointInfo, error)
|
||||
GetEndpointByName(endpointName string, withIpv6 bool) (*EndpointInfo, error)
|
||||
}
|
||||
|
||||
// NewManager creates a new networkManager.
|
||||
|
@ -118,6 +118,7 @@ func (nm *networkManager) GetNetworkByName(networkName string) (*NetworkInfo, er
|
|||
|
||||
// CreateEndpoint creates a new container endpoint.
|
||||
func (nm *networkManager) CreateEndpoint(networkID string, epInfo *EndpointInfo, namespaceID string) (*EndpointInfo, error) {
|
||||
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
|
@ -134,7 +135,7 @@ func (nm *networkManager) CreateEndpoint(networkID string, epInfo *EndpointInfo,
|
|||
return nil, fmt.Errorf("error adding endpoint to namespace %v : endpoint %v", err, hcnEndpoint)
|
||||
}
|
||||
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint), err
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint, epInfo.DualStack), err
|
||||
}
|
||||
|
||||
// DeleteEndpoint deletes an existing container endpoint.
|
||||
|
@ -185,7 +186,7 @@ func (nm *networkManager) DeleteEndpoint(endpointID string) error {
|
|||
}
|
||||
|
||||
// GetEndpoint returns the endpoint matching the Id.
|
||||
func (nm *networkManager) GetEndpoint(endpointID string) (*EndpointInfo, error) {
|
||||
func (nm *networkManager) GetEndpoint(endpointID string, withIpv6 bool) (*EndpointInfo, error) {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
|
@ -194,11 +195,11 @@ func (nm *networkManager) GetEndpoint(endpointID string) (*EndpointInfo, error)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint), nil
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint, withIpv6), nil
|
||||
}
|
||||
|
||||
// GetEndpointByName returns the endpoint matching the Name.
|
||||
func (nm *networkManager) GetEndpointByName(endpointName string) (*EndpointInfo, error) {
|
||||
func (nm *networkManager) GetEndpointByName(endpointName string, withIpv6 bool) (*EndpointInfo, error) {
|
||||
nm.Lock()
|
||||
defer nm.Unlock()
|
||||
|
||||
|
@ -207,5 +208,5 @@ func (nm *networkManager) GetEndpointByName(endpointName string) (*EndpointInfo,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint), nil
|
||||
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint, withIpv6), nil
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче