device_windows.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. package vxlan
  15. import (
  16. "encoding/json"
  17. "github.com/Microsoft/hcsshim/hcn"
  18. "github.com/coreos/flannel/pkg/ip"
  19. log "github.com/golang/glog"
  20. "github.com/juju/errors"
  21. "github.com/rakelkar/gonetsh/netsh"
  22. "k8s.io/apimachinery/pkg/util/wait"
  23. utilexec "k8s.io/utils/exec"
  24. "time"
  25. )
  26. type vxlanDeviceAttrs struct {
  27. vni uint32
  28. name string
  29. gbp bool
  30. addressPrefix ip.IP4Net
  31. }
  32. type vxlanDevice struct {
  33. link *hcn.HostComputeNetwork
  34. macPrefix string
  35. directRouting bool
  36. }
  37. func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
  38. subnet := createSubnet(devAttrs.addressPrefix.String(), (devAttrs.addressPrefix.IP + 1).String(), "0.0.0.0/0")
  39. network := &hcn.HostComputeNetwork{
  40. Type: "Overlay",
  41. Name: devAttrs.name,
  42. Ipams: []hcn.Ipam{
  43. {
  44. Type: "Static",
  45. Subnets: []hcn.Subnet{
  46. *subnet,
  47. },
  48. },
  49. },
  50. Flags: hcn.EnableNonPersistent,
  51. SchemaVersion: hcn.SchemaVersion{
  52. Major: 2,
  53. Minor: 0,
  54. },
  55. }
  56. vsid := &hcn.VsidPolicySetting{
  57. IsolationId: devAttrs.vni,
  58. }
  59. vsidJson, err := json.Marshal(vsid)
  60. if err != nil {
  61. return nil, err
  62. }
  63. sp := &hcn.SubnetPolicy{
  64. Type: hcn.VSID,
  65. }
  66. sp.Settings = vsidJson
  67. spJson, err := json.Marshal(sp)
  68. if err != nil {
  69. return nil, err
  70. }
  71. network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson)
  72. hnsNetwork, err := ensureNetwork(network, devAttrs.addressPrefix.String())
  73. if err != nil {
  74. return nil, err
  75. }
  76. return &vxlanDevice{
  77. link: hnsNetwork,
  78. }, nil
  79. }
  80. func ensureNetwork(expectedNetwork *hcn.HostComputeNetwork, expectedAddressPrefix string) (*hcn.HostComputeNetwork, error) {
  81. createNetwork := true
  82. networkName := expectedNetwork.Name
  83. // 1. Check if the HostComputeNetwork exists and has the expected settings
  84. existingNetwork, err := hcn.GetNetworkByName(networkName)
  85. if err == nil {
  86. if existingNetwork.Type == expectedNetwork.Type {
  87. if existingNetwork.Ipams[0].Subnets[0].IpAddressPrefix == expectedAddressPrefix {
  88. createNetwork = false
  89. log.Infof("Found existing HostComputeNetwork %s", networkName)
  90. }
  91. }
  92. }
  93. // 2. Create a new HNSNetwork
  94. if createNetwork {
  95. if existingNetwork != nil {
  96. if err := existingNetwork.Delete(); err != nil {
  97. return nil, errors.Annotatef(err, "failed to delete existing HostComputeNetwork %s", networkName)
  98. }
  99. log.Infof("Deleted stale HostComputeNetwork %s", networkName)
  100. }
  101. log.Infof("Attempting to create HostComputeNetwork %v", expectedNetwork)
  102. newNetwork, err := expectedNetwork.Create()
  103. if err != nil {
  104. return nil, errors.Annotatef(err, "failed to create HostComputeNetwork %s", networkName)
  105. }
  106. var waitErr, lastErr error
  107. // Wait for the network to populate Management IP
  108. log.Infof("Waiting to get ManagementIP from HostComputeNetwork %s", networkName)
  109. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  110. newNetwork, lastErr = hcn.GetNetworkByID(newNetwork.Id)
  111. return newNetwork != nil && len(getManagementIP(newNetwork)) != 0, nil
  112. })
  113. if waitErr == wait.ErrWaitTimeout {
  114. return nil, errors.Annotatef(lastErr, "timeout, failed to get management IP from HostComputeNetwork %s", networkName)
  115. }
  116. managementIP := getManagementIP(newNetwork)
  117. // Wait for the interface with the management IP
  118. netshHelper := netsh.New(utilexec.New())
  119. log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
  120. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  121. _, lastErr = netshHelper.GetInterfaceByIP(managementIP)
  122. return lastErr == nil, nil
  123. })
  124. if waitErr == wait.ErrWaitTimeout {
  125. return nil, errors.Annotatef(lastErr, "timeout, failed to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
  126. }
  127. log.Infof("Created HostComputeNetwork %s", networkName)
  128. existingNetwork = newNetwork
  129. }
  130. addHostRoute := true
  131. for _, policy := range existingNetwork.Policies {
  132. if policy.Type == hcn.HostRoute {
  133. addHostRoute = false
  134. }
  135. }
  136. if addHostRoute {
  137. hostRoutePolicy := hcn.NetworkPolicy{
  138. Type: hcn.HostRoute,
  139. Settings: []byte("{}"),
  140. }
  141. networkRequest := hcn.PolicyNetworkRequest{
  142. Policies: []hcn.NetworkPolicy{hostRoutePolicy},
  143. }
  144. err = existingNetwork.AddPolicy(networkRequest)
  145. if err != nil {
  146. 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")
  147. }
  148. }
  149. return existingNetwork, nil
  150. }
  151. func getManagementIP(network *hcn.HostComputeNetwork) string {
  152. for _, policy := range network.Policies {
  153. if policy.Type == hcn.ProviderAddress {
  154. policySettings := hcn.ProviderAddressEndpointPolicySetting{}
  155. err := json.Unmarshal(policy.Settings, &policySettings)
  156. if err != nil {
  157. return ""
  158. }
  159. return policySettings.ProviderAddress
  160. }
  161. }
  162. return ""
  163. }
  164. func createSubnet(AddressPrefix string, NextHop string, DestPrefix string) *hcn.Subnet {
  165. return &hcn.Subnet{
  166. IpAddressPrefix: AddressPrefix,
  167. Routes: []hcn.Route{
  168. {
  169. NextHop: NextHop,
  170. DestinationPrefix: DestPrefix,
  171. },
  172. },
  173. }
  174. }