ov_endpoint_windows.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package overlay
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "sync"
  8. "github.com/Microsoft/hcsshim"
  9. "github.com/Microsoft/hcsshim/osversion"
  10. "github.com/containerd/log"
  11. "github.com/docker/docker/libnetwork/driverapi"
  12. "github.com/docker/docker/libnetwork/drivers/windows"
  13. "github.com/docker/docker/libnetwork/netlabel"
  14. "github.com/docker/docker/libnetwork/types"
  15. )
  16. type endpointTable map[string]*endpoint
  17. const overlayEndpointPrefix = "overlay/endpoint"
  18. type endpoint struct {
  19. id string
  20. nid string
  21. profileID string
  22. remote bool
  23. mac net.HardwareAddr
  24. addr *net.IPNet
  25. disablegateway bool
  26. portMapping []types.PortBinding // Operation port bindings
  27. }
  28. var (
  29. // Server 2016 (RS1) does not support concurrent add/delete of endpoints. Therefore, we need
  30. // to use this mutex and serialize the add/delete of endpoints on RS1.
  31. endpointMu sync.Mutex
  32. windowsBuild = osversion.Build()
  33. )
  34. func validateID(nid, eid string) error {
  35. if nid == "" {
  36. return fmt.Errorf("invalid network id")
  37. }
  38. if eid == "" {
  39. return fmt.Errorf("invalid endpoint id")
  40. }
  41. return nil
  42. }
  43. func (n *network) endpoint(eid string) *endpoint {
  44. n.Lock()
  45. defer n.Unlock()
  46. return n.endpoints[eid]
  47. }
  48. func (n *network) addEndpoint(ep *endpoint) {
  49. n.Lock()
  50. n.endpoints[ep.id] = ep
  51. n.Unlock()
  52. }
  53. func (n *network) deleteEndpoint(eid string) {
  54. n.Lock()
  55. delete(n.endpoints, eid)
  56. n.Unlock()
  57. }
  58. func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
  59. var networkEndpoint *endpoint
  60. n.Lock()
  61. for _, ep := range n.endpoints {
  62. if ep.addr.IP.Equal(addr.IP) {
  63. networkEndpoint = ep
  64. break
  65. }
  66. }
  67. if networkEndpoint != nil {
  68. delete(n.endpoints, networkEndpoint.id)
  69. }
  70. n.Unlock()
  71. if networkEndpoint != nil {
  72. log.G(context.TODO()).Debugf("Removing stale endpoint from HNS")
  73. _, err := endpointRequest("DELETE", networkEndpoint.profileID, "")
  74. if err != nil {
  75. log.G(context.TODO()).Debugf("Failed to delete stale overlay endpoint (%.7s) from hns", networkEndpoint.id)
  76. }
  77. }
  78. }
  79. func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
  80. var err error
  81. if err = validateID(nid, eid); err != nil {
  82. return err
  83. }
  84. n := d.network(nid)
  85. if n == nil {
  86. return fmt.Errorf("network id %q not found", nid)
  87. }
  88. ep := n.endpoint(eid)
  89. if ep != nil {
  90. log.G(context.TODO()).Debugf("Deleting stale endpoint %s", eid)
  91. n.deleteEndpoint(eid)
  92. _, err := endpointRequest("DELETE", ep.profileID, "")
  93. if err != nil {
  94. return err
  95. }
  96. }
  97. ep = &endpoint{
  98. id: eid,
  99. nid: n.id,
  100. addr: ifInfo.Address(),
  101. mac: ifInfo.MacAddress(),
  102. }
  103. if ep.addr == nil {
  104. return fmt.Errorf("create endpoint was not passed interface IP address")
  105. }
  106. s := n.getSubnetforIP(ep.addr)
  107. if s == nil {
  108. return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
  109. }
  110. // Todo: Add port bindings and qos policies here
  111. hnsEndpoint := &hcsshim.HNSEndpoint{
  112. Name: eid,
  113. VirtualNetwork: n.hnsID,
  114. IPAddress: ep.addr.IP,
  115. EnableInternalDNS: true,
  116. GatewayAddress: s.gwIP.String(),
  117. }
  118. if ep.mac != nil {
  119. hnsEndpoint.MacAddress = ep.mac.String()
  120. }
  121. paPolicy, err := json.Marshal(hcsshim.PaPolicy{
  122. Type: "PA",
  123. PA: n.providerAddress,
  124. })
  125. if err != nil {
  126. return err
  127. }
  128. hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
  129. natPolicy, err := json.Marshal(hcsshim.PaPolicy{Type: "OutBoundNAT"})
  130. if err != nil {
  131. return err
  132. }
  133. hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy)
  134. epConnectivity, err := windows.ParseEndpointConnectivity(epOptions)
  135. if err != nil {
  136. return err
  137. }
  138. ep.portMapping = epConnectivity.PortBindings
  139. ep.portMapping, err = windows.AllocatePorts(n.portMapper, ep.portMapping, ep.addr.IP)
  140. if err != nil {
  141. return err
  142. }
  143. defer func() {
  144. if err != nil {
  145. windows.ReleasePorts(n.portMapper, ep.portMapping)
  146. }
  147. }()
  148. pbPolicy, err := windows.ConvertPortBindings(ep.portMapping)
  149. if err != nil {
  150. return err
  151. }
  152. hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...)
  153. ep.disablegateway = true
  154. configurationb, err := json.Marshal(hnsEndpoint)
  155. if err != nil {
  156. return err
  157. }
  158. hnsresponse, err := endpointRequest("POST", "", string(configurationb))
  159. if err != nil {
  160. return err
  161. }
  162. ep.profileID = hnsresponse.Id
  163. if ep.mac == nil {
  164. ep.mac, err = net.ParseMAC(hnsresponse.MacAddress)
  165. if err != nil {
  166. return err
  167. }
  168. if err := ifInfo.SetMacAddress(ep.mac); err != nil {
  169. return err
  170. }
  171. }
  172. ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies)
  173. if err != nil {
  174. endpointRequest("DELETE", hnsresponse.Id, "")
  175. return err
  176. }
  177. n.addEndpoint(ep)
  178. return nil
  179. }
  180. func (d *driver) DeleteEndpoint(nid, eid string) error {
  181. if err := validateID(nid, eid); err != nil {
  182. return err
  183. }
  184. n := d.network(nid)
  185. if n == nil {
  186. return fmt.Errorf("network id %q not found", nid)
  187. }
  188. ep := n.endpoint(eid)
  189. if ep == nil {
  190. return fmt.Errorf("endpoint id %q not found", eid)
  191. }
  192. windows.ReleasePorts(n.portMapper, ep.portMapping)
  193. n.deleteEndpoint(eid)
  194. _, err := endpointRequest("DELETE", ep.profileID, "")
  195. if err != nil {
  196. return err
  197. }
  198. return nil
  199. }
  200. func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
  201. if err := validateID(nid, eid); err != nil {
  202. return nil, err
  203. }
  204. n := d.network(nid)
  205. if n == nil {
  206. return nil, fmt.Errorf("network id %q not found", nid)
  207. }
  208. ep := n.endpoint(eid)
  209. if ep == nil {
  210. return nil, fmt.Errorf("endpoint id %q not found", eid)
  211. }
  212. data := make(map[string]interface{}, 1)
  213. data["hnsid"] = ep.profileID
  214. data["AllowUnqualifiedDNSQuery"] = true
  215. if ep.portMapping != nil {
  216. // Return a copy of the operational data
  217. pmc := make([]types.PortBinding, 0, len(ep.portMapping))
  218. for _, pm := range ep.portMapping {
  219. pmc = append(pmc, pm.GetCopy())
  220. }
  221. data[netlabel.PortMap] = pmc
  222. }
  223. return data, nil
  224. }
  225. func endpointRequest(method, path, request string) (*hcsshim.HNSEndpoint, error) {
  226. if windowsBuild == 14393 {
  227. endpointMu.Lock()
  228. }
  229. hnsresponse, err := hcsshim.HNSEndpointRequest(method, path, request)
  230. if windowsBuild == 14393 {
  231. endpointMu.Unlock()
  232. }
  233. return hnsresponse, err
  234. }