device_windows.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. "fmt"
  18. "github.com/Microsoft/hcsshim"
  19. "github.com/buger/jsonparser"
  20. "github.com/coreos/flannel/pkg/ip"
  21. log "github.com/golang/glog"
  22. "github.com/juju/errors"
  23. "github.com/rakelkar/gonetsh/netsh"
  24. "k8s.io/apimachinery/pkg/util/wait"
  25. utilexec "k8s.io/utils/exec"
  26. "time"
  27. )
  28. type vxlanDeviceAttrs struct {
  29. vni uint32
  30. name string
  31. gbp bool
  32. addressPrefix ip.IP4Net
  33. }
  34. type vxlanDevice struct {
  35. link *hcsshim.HNSNetwork
  36. macPrefix string
  37. directRouting bool
  38. }
  39. func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
  40. hnsNetwork := &hcsshim.HNSNetwork{
  41. Name: devAttrs.name,
  42. Type: "Overlay",
  43. Subnets: make([]hcsshim.Subnet, 0, 1),
  44. }
  45. hnsNetwork, err := ensureNetwork(hnsNetwork, int64(devAttrs.vni), devAttrs.addressPrefix.String(), (devAttrs.addressPrefix.IP + 1).String())
  46. if err != nil {
  47. return nil, err
  48. }
  49. return &vxlanDevice{
  50. link: hnsNetwork,
  51. }, nil
  52. }
  53. func ensureNetwork(expectedNetwork *hcsshim.HNSNetwork, expectedVSID int64, expectedAddressPrefix, expectedGW string) (*hcsshim.HNSNetwork, error) {
  54. createNetwork := true
  55. networkName := expectedNetwork.Name
  56. // 1. Check if the HNSNetwork exists and has the expected settings
  57. existingNetwork, err := hcsshim.GetHNSNetworkByName(networkName)
  58. if err == nil {
  59. if existingNetwork.Type == expectedNetwork.Type {
  60. for _, existingSubnet := range existingNetwork.Subnets {
  61. if existingSubnet.AddressPrefix == expectedAddressPrefix && existingSubnet.GatewayAddress == expectedGW {
  62. createNetwork = false
  63. log.Infof("Found existing HNSNetwork %s", networkName)
  64. break
  65. }
  66. }
  67. }
  68. }
  69. // 2. Create a new HNSNetwork
  70. if createNetwork {
  71. if existingNetwork != nil {
  72. if _, err := existingNetwork.Delete(); err != nil {
  73. return nil, errors.Annotatef(err, "failed to delete existing HNSNetwork %s", networkName)
  74. }
  75. log.Infof("Deleted stale HNSNetwork %s", networkName)
  76. }
  77. // Add a VxLan subnet
  78. expectedNetwork.Subnets = append(expectedNetwork.Subnets, hcsshim.Subnet{
  79. AddressPrefix: expectedAddressPrefix,
  80. GatewayAddress: expectedGW,
  81. Policies: []json.RawMessage{
  82. []byte(fmt.Sprintf(`{"Type":"VSID","VSID":%d}`, expectedVSID)),
  83. },
  84. })
  85. // Config request params
  86. jsonRequest, err := json.Marshal(expectedNetwork)
  87. if err != nil {
  88. return nil, errors.Annotatef(err, "failed to marshal %+v", expectedNetwork)
  89. }
  90. log.Infof("Attempting to create HNSNetwork %s", string(jsonRequest))
  91. newNetwork, err := hcsshim.HNSNetworkRequest("POST", "", string(jsonRequest))
  92. if err != nil {
  93. return nil, errors.Annotatef(err, "failed to create HNSNetwork %s", networkName)
  94. }
  95. var waitErr, lastErr error
  96. // Wait for the network to populate Management IP
  97. log.Infof("Waiting to get ManagementIP from HNSNetwork %s", networkName)
  98. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  99. newNetwork, lastErr = hcsshim.HNSNetworkRequest("GET", newNetwork.Id, "")
  100. return newNetwork != nil && len(newNetwork.ManagementIP) != 0, nil
  101. })
  102. if waitErr == wait.ErrWaitTimeout {
  103. return nil, errors.Annotatef(lastErr, "timeout, failed to get management IP from HNSNetwork %s", networkName)
  104. }
  105. // Wait for the interface with the management IP
  106. netshHelper := netsh.New(utilexec.New())
  107. log.Infof("Waiting to get net interface for HNSNetwork %s (%s)", networkName, newNetwork.ManagementIP)
  108. waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
  109. _, lastErr = netshHelper.GetInterfaceByIP(newNetwork.ManagementIP)
  110. return lastErr == nil, nil
  111. })
  112. if waitErr == wait.ErrWaitTimeout {
  113. return nil, errors.Annotatef(lastErr, "timeout, failed to get net interface for HNSNetwork %s (%s)", networkName, newNetwork.ManagementIP)
  114. }
  115. log.Infof("Created HNSNetwork %s", networkName)
  116. return newNetwork, nil
  117. }
  118. return existingNetwork, nil
  119. }
  120. type neighbor struct {
  121. MAC string
  122. IP ip.IP4
  123. ManagementAddress string
  124. }
  125. func (dev *vxlanDevice) AddEndpoint(n *neighbor) error {
  126. endpointName := createEndpointName(n.IP)
  127. // 1. Check if the HNSEndpoint exists and has the expected settings
  128. existingEndpoint, err := hcsshim.GetHNSEndpointByName(endpointName)
  129. if err == nil && existingEndpoint.VirtualNetwork == dev.link.Id {
  130. // Check policies if there is PA type
  131. targetType := "PA"
  132. for _, policy := range existingEndpoint.Policies {
  133. policyType, _ := jsonparser.GetUnsafeString(policy, "Type")
  134. if policyType == targetType {
  135. actualPaIP, _ := jsonparser.GetUnsafeString(policy, targetType)
  136. if actualPaIP == n.ManagementAddress {
  137. log.Infof("Found existing remote HNSEndpoint %s", endpointName)
  138. return nil
  139. }
  140. }
  141. }
  142. }
  143. // 2. Create a new HNSNetwork
  144. if existingEndpoint != nil {
  145. if _, err := existingEndpoint.Delete(); err != nil {
  146. return errors.Annotatef(err, "failed to delete existing remote HNSEndpoint %s", endpointName)
  147. }
  148. log.V(4).Infof("Deleted stale HNSEndpoint %s", endpointName)
  149. }
  150. newEndpoint := &hcsshim.HNSEndpoint{
  151. Name: endpointName,
  152. IPAddress: n.IP.ToIP(),
  153. MacAddress: n.MAC,
  154. VirtualNetwork: dev.link.Id,
  155. IsRemoteEndpoint: true,
  156. Policies: []json.RawMessage{
  157. []byte(fmt.Sprintf(`{"Type":"PA","PA":"%s"}`, n.ManagementAddress)),
  158. },
  159. }
  160. if _, err := newEndpoint.Create(); err != nil {
  161. return errors.Annotatef(err, "failed to create remote HNSEndpoint %s", endpointName)
  162. }
  163. log.V(4).Infof("Created HNSEndpoint %s", endpointName)
  164. return nil
  165. }
  166. func (dev *vxlanDevice) DelEndpoint(n *neighbor) error {
  167. endpointName := createEndpointName(n.IP)
  168. existingEndpoint, err := hcsshim.GetHNSEndpointByName(endpointName)
  169. if err == nil && existingEndpoint.VirtualNetwork == dev.link.Id {
  170. // Check policies if there is PA type
  171. targetType := "PA"
  172. for _, policy := range existingEndpoint.Policies {
  173. policyType, _ := jsonparser.GetUnsafeString(policy, "Type")
  174. if policyType == targetType {
  175. actualPaIP, _ := jsonparser.GetUnsafeString(policy, targetType)
  176. if actualPaIP == n.ManagementAddress {
  177. // Found it and delete
  178. if _, err := existingEndpoint.Delete(); err != nil {
  179. return errors.Annotatef(err, "failed to delete remote HNSEndpoint %s", endpointName)
  180. }
  181. log.V(4).Infof("Deleted HNSEndpoint %s", endpointName)
  182. break
  183. }
  184. }
  185. }
  186. }
  187. return nil
  188. }
  189. func (dev *vxlanDevice) ConjureMac(targetIP ip.IP4) string {
  190. a, b, c, d := targetIP.Octets()
  191. return fmt.Sprintf("%v-%02x-%02x-%02x-%02x", dev.macPrefix, a, b, c, d)
  192. }
  193. func createEndpointName(targetIP ip.IP4) string {
  194. return "remote_" + targetIP.String()
  195. }