device_windows.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2018 flannel authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build windows
  15. package vxlan
  16. import (
  17. "encoding/json"
  18. "time"
  19. "github.com/Microsoft/hcsshim/hcn"
  20. "github.com/flannel-io/flannel/pkg/ip"
  21. "github.com/pkg/errors"
  22. "k8s.io/apimachinery/pkg/util/wait"
  23. log "k8s.io/klog"
  24. )
  25. type vxlanDeviceAttrs struct {
  26. vni uint32
  27. name string
  28. gbp bool
  29. addressPrefix ip.IP4Net
  30. }
  31. type vxlanDevice struct {
  32. link *hcn.HostComputeNetwork
  33. macPrefix string
  34. directRouting bool
  35. }
  36. func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
  37. subnet := createSubnet(devAttrs.addressPrefix.String(), (devAttrs.addressPrefix.IP + 1).String(), "0.0.0.0/0")
  38. network := &hcn.HostComputeNetwork{
  39. Type: "Overlay",
  40. Name: devAttrs.name,
  41. Ipams: []hcn.Ipam{
  42. {
  43. Type: "Static",
  44. Subnets: []hcn.Subnet{
  45. *subnet,
  46. },
  47. },
  48. },
  49. Flags: hcn.EnableNonPersistent,
  50. SchemaVersion: hcn.SchemaVersion{
  51. Major: 2,
  52. Minor: 0,
  53. },
  54. }
  55. vsid := &hcn.VsidPolicySetting{
  56. IsolationId: devAttrs.vni,
  57. }
  58. vsidJson, err := json.Marshal(vsid)
  59. if err != nil {
  60. return nil, err
  61. }
  62. sp := &hcn.SubnetPolicy{
  63. Type: hcn.VSID,
  64. }
  65. sp.Settings = vsidJson
  66. spJson, err := json.Marshal(sp)
  67. if err != nil {
  68. return nil, err
  69. }
  70. network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson)
  71. hnsNetwork, err := ensureNetwork(network, devAttrs.addressPrefix.String())
  72. if err != nil {
  73. return nil, err
  74. }
  75. return &vxlanDevice{
  76. link: hnsNetwork,
  77. }, nil
  78. }
  79. func ensureNetwork(expectedNetwork *hcn.HostComputeNetwork, expectedAddressPrefix string) (*hcn.HostComputeNetwork, error) {
  80. createNetwork := true
  81. networkName := expectedNetwork.Name
  82. // 1. Check if the HostComputeNetwork exists and has the expected settings
  83. existingNetwork, err := hcn.GetNetworkByName(networkName)
  84. if err == nil {
  85. if existingNetwork.Type == expectedNetwork.Type {
  86. if existingNetwork.Ipams[0].Subnets[0].IpAddressPrefix == expectedAddressPrefix {
  87. createNetwork = false
  88. log.Infof("Found existing HostComputeNetwork %s", networkName)
  89. }
  90. }
  91. }
  92. // 2. Create a new HNSNetwork
  93. if createNetwork {
  94. if existingNetwork != nil {
  95. if err := existingNetwork.Delete(); err != nil {
  96. return nil, errors.Wrapf(err, "failed to delete existing HostComputeNetwork %s", networkName)
  97. }
  98. log.Infof("Deleted stale HostComputeNetwork %s", networkName)
  99. }
  100. log.Infof("Attempting to create HostComputeNetwork %v", expectedNetwork)
  101. newNetwork, err := expectedNetwork.Create()
  102. if err != nil {
  103. return nil, errors.Wrapf(err, "failed to create HostComputeNetwork %s", networkName)
  104. }
  105. var waitErr, lastErr error
  106. // Wait for the network to populate Management IP
  107. log.Infof("Waiting to get ManagementIP from HostComputeNetwork %s", networkName)
  108. var newNetworkID = newNetwork.Id
  109. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  110. newNetwork, lastErr = hcn.GetNetworkByID(newNetworkID)
  111. return newNetwork != nil && len(getManagementIP(newNetwork)) != 0, nil
  112. })
  113. if waitErr == wait.ErrWaitTimeout {
  114. // Do not swallow the root cause
  115. if lastErr != nil {
  116. waitErr = lastErr
  117. }
  118. return nil, errors.Wrapf(lastErr, "timeout, failed to get management IP from HostComputeNetwork %s", networkName)
  119. }
  120. managementIP := getManagementIP(newNetwork)
  121. // Wait for the interface with the management IP
  122. log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
  123. managementIPv4, err := ip.ParseIP4(managementIP)
  124. if err != nil {
  125. return nil, errors.Wrapf(err, "Failed to parse management ip (%s)", managementIP)
  126. }
  127. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  128. _, lastErr = ip.GetInterfaceByIP(managementIPv4.ToIP())
  129. return lastErr == nil, nil
  130. })
  131. if waitErr == wait.ErrWaitTimeout {
  132. return nil, errors.Wrapf(lastErr, "timeout, failed to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
  133. }
  134. log.Infof("Created HostComputeNetwork %s", networkName)
  135. existingNetwork = newNetwork
  136. }
  137. addHostRoute := true
  138. for _, policy := range existingNetwork.Policies {
  139. if policy.Type == hcn.HostRoute {
  140. addHostRoute = false
  141. }
  142. }
  143. if addHostRoute {
  144. hostRoutePolicy := hcn.NetworkPolicy{
  145. Type: hcn.HostRoute,
  146. Settings: []byte("{}"),
  147. }
  148. networkRequest := hcn.PolicyNetworkRequest{
  149. Policies: []hcn.NetworkPolicy{hostRoutePolicy},
  150. }
  151. err = existingNetwork.AddPolicy(networkRequest)
  152. if err != nil {
  153. log.Infof("Could not apply HostRoute policy for local host to local pod connectivity. This policy requires Windows 18321.1000.19h1_release.190117-1502 or newer")
  154. }
  155. }
  156. return existingNetwork, nil
  157. }
  158. func getManagementIP(network *hcn.HostComputeNetwork) string {
  159. for _, policy := range network.Policies {
  160. if policy.Type == hcn.ProviderAddress {
  161. policySettings := hcn.ProviderAddressEndpointPolicySetting{}
  162. err := json.Unmarshal(policy.Settings, &policySettings)
  163. if err != nil {
  164. return ""
  165. }
  166. return policySettings.ProviderAddress
  167. }
  168. }
  169. return ""
  170. }
  171. func createSubnet(AddressPrefix string, NextHop string, DestPrefix string) *hcn.Subnet {
  172. return &hcn.Subnet{
  173. IpAddressPrefix: AddressPrefix,
  174. Routes: []hcn.Route{
  175. {
  176. NextHop: NextHop,
  177. DestinationPrefix: DestPrefix,
  178. },
  179. },
  180. }
  181. }