device_windows.go 7.7 KB

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