windows.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. // +build windows
  2. // Shim for the Host Network Service (HNS) to manage networking for
  3. // Windows Server containers and Hyper-V containers. This module
  4. // is a basic libnetwork driver that passes all the calls to HNS
  5. // It implements the 4 networking modes supported by HNS L2Bridge,
  6. // L2Tunnel, NAT and Transparent(DHCP)
  7. //
  8. // The network are stored in memory and docker daemon ensures discovering
  9. // and loading these networks on startup
  10. package windows
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "net"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "github.com/Microsoft/hcsshim"
  19. "github.com/Sirupsen/logrus"
  20. "github.com/docker/libnetwork/datastore"
  21. "github.com/docker/libnetwork/discoverapi"
  22. "github.com/docker/libnetwork/driverapi"
  23. "github.com/docker/libnetwork/netlabel"
  24. "github.com/docker/libnetwork/types"
  25. )
  26. // networkConfiguration for network specific configuration
  27. type networkConfiguration struct {
  28. ID string
  29. Type string
  30. Name string
  31. HnsID string
  32. RDID string
  33. VLAN uint
  34. VSID uint
  35. DNSServers string
  36. DNSSuffix string
  37. SourceMac string
  38. NetworkAdapterName string
  39. }
  40. // endpointConfiguration represents the user specified configuration for the sandbox endpoint
  41. type endpointOption struct {
  42. MacAddress net.HardwareAddr
  43. QosPolicies []types.QosPolicy
  44. DNSServers []string
  45. DisableDNS bool
  46. DisableICC bool
  47. }
  48. type endpointConnectivity struct {
  49. PortBindings []types.PortBinding
  50. ExposedPorts []types.TransportPort
  51. }
  52. type hnsEndpoint struct {
  53. id string
  54. profileID string
  55. macAddress net.HardwareAddr
  56. epOption *endpointOption // User specified parameters
  57. epConnectivity *endpointConnectivity // User specified parameters
  58. portMapping []types.PortBinding // Operation port bindings
  59. addr *net.IPNet
  60. gateway net.IP
  61. }
  62. type hnsNetwork struct {
  63. id string
  64. config *networkConfiguration
  65. endpoints map[string]*hnsEndpoint // key: endpoint id
  66. driver *driver // The network's driver
  67. sync.Mutex
  68. }
  69. type driver struct {
  70. name string
  71. networks map[string]*hnsNetwork
  72. sync.Mutex
  73. }
  74. // IsBuiltinWindowsDriver vaidates if network-type is a builtin local-scoped driver
  75. func IsBuiltinLocalDriver(networkType string) bool {
  76. if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType {
  77. return true
  78. }
  79. return false
  80. }
  81. // New constructs a new bridge driver
  82. func newDriver(networkType string) *driver {
  83. return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
  84. }
  85. // GetInit returns an initializer for the given network type
  86. func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
  87. return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
  88. if !IsBuiltinLocalDriver(networkType) {
  89. return types.BadRequestErrorf("Network type not supported: %s", networkType)
  90. }
  91. return dc.RegisterDriver(networkType, newDriver(networkType), driverapi.Capability{
  92. DataScope: datastore.LocalScope,
  93. })
  94. }
  95. }
  96. func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
  97. d.Lock()
  98. defer d.Unlock()
  99. if nw, ok := d.networks[id]; ok {
  100. return nw, nil
  101. }
  102. return nil, types.NotFoundErrorf("network not found: %s", id)
  103. }
  104. func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
  105. n.Lock()
  106. defer n.Unlock()
  107. if ep, ok := n.endpoints[eid]; ok {
  108. return ep, nil
  109. }
  110. return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
  111. }
  112. func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
  113. config := &networkConfiguration{}
  114. for label, value := range genericOptions {
  115. switch label {
  116. case NetworkName:
  117. config.Name = value
  118. case HNSID:
  119. config.HnsID = value
  120. case RoutingDomain:
  121. config.RDID = value
  122. case Interface:
  123. config.NetworkAdapterName = value
  124. case DNSSuffix:
  125. config.DNSSuffix = value
  126. case DNSServers:
  127. config.DNSServers = value
  128. case VLAN:
  129. vlan, err := strconv.ParseUint(value, 10, 32)
  130. if err != nil {
  131. return nil, err
  132. }
  133. config.VLAN = uint(vlan)
  134. case VSID:
  135. vsid, err := strconv.ParseUint(value, 10, 32)
  136. if err != nil {
  137. return nil, err
  138. }
  139. config.VSID = uint(vsid)
  140. }
  141. }
  142. config.ID = id
  143. config.Type = d.name
  144. return config, nil
  145. }
  146. func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
  147. if len(ipamV6Data) > 0 {
  148. return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
  149. }
  150. if len(ipamV4Data) == 0 {
  151. return types.BadRequestErrorf("network %s requires ipv4 configuration", id)
  152. }
  153. return nil
  154. }
  155. func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
  156. }
  157. // Create a new network
  158. func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
  159. if _, err := d.getNetwork(id); err == nil {
  160. return types.ForbiddenErrorf("network %s exists", id)
  161. }
  162. genData, ok := option[netlabel.GenericData].(map[string]string)
  163. if !ok {
  164. return fmt.Errorf("Unknown generic data option")
  165. }
  166. // Parse and validate the config. It should not conflict with existing networks' config
  167. config, err := d.parseNetworkOptions(id, genData)
  168. if err != nil {
  169. return err
  170. }
  171. err = config.processIPAM(id, ipV4Data, ipV6Data)
  172. if err != nil {
  173. return err
  174. }
  175. network := &hnsNetwork{
  176. id: config.ID,
  177. endpoints: make(map[string]*hnsEndpoint),
  178. config: config,
  179. driver: d,
  180. }
  181. d.Lock()
  182. d.networks[config.ID] = network
  183. d.Unlock()
  184. // A non blank hnsid indicates that the network was discovered
  185. // from HNS. No need to call HNS if this network was discovered
  186. // from HNS
  187. if config.HnsID == "" {
  188. subnets := []hcsshim.Subnet{}
  189. for _, ipData := range ipV4Data {
  190. subnet := hcsshim.Subnet{
  191. AddressPrefix: ipData.Pool.String(),
  192. }
  193. if ipData.Gateway != nil {
  194. subnet.GatewayAddress = ipData.Gateway.IP.String()
  195. }
  196. subnets = append(subnets, subnet)
  197. }
  198. network := &hcsshim.HNSNetwork{
  199. Name: config.Name,
  200. Type: d.name,
  201. Subnets: subnets,
  202. DNSServerList: config.DNSServers,
  203. DNSSuffix: config.DNSSuffix,
  204. SourceMac: config.SourceMac,
  205. NetworkAdapterName: config.NetworkAdapterName,
  206. }
  207. if config.VLAN != 0 {
  208. vlanPolicy, err := json.Marshal(hcsshim.VlanPolicy{
  209. Type: "VLAN",
  210. VLAN: config.VLAN,
  211. })
  212. if err != nil {
  213. return err
  214. }
  215. network.Policies = append(network.Policies, vlanPolicy)
  216. }
  217. if config.VSID != 0 {
  218. vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
  219. Type: "VSID",
  220. VSID: config.VSID,
  221. })
  222. if err != nil {
  223. return err
  224. }
  225. network.Policies = append(network.Policies, vsidPolicy)
  226. }
  227. if network.Name == "" {
  228. network.Name = id
  229. }
  230. configurationb, err := json.Marshal(network)
  231. if err != nil {
  232. return err
  233. }
  234. configuration := string(configurationb)
  235. logrus.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
  236. hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
  237. if err != nil {
  238. return err
  239. }
  240. config.HnsID = hnsresponse.Id
  241. genData[HNSID] = config.HnsID
  242. }
  243. return nil
  244. }
  245. func (d *driver) DeleteNetwork(nid string) error {
  246. n, err := d.getNetwork(nid)
  247. if err != nil {
  248. return types.InternalMaskableErrorf("%s", err)
  249. }
  250. n.Lock()
  251. config := n.config
  252. n.Unlock()
  253. // Cannot remove network if endpoints are still present
  254. if len(n.endpoints) != 0 {
  255. return fmt.Errorf("network %s has active endpoint", n.id)
  256. }
  257. _, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
  258. if err != nil {
  259. return err
  260. }
  261. d.Lock()
  262. delete(d.networks, nid)
  263. d.Unlock()
  264. return nil
  265. }
  266. func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error) {
  267. var qps []json.RawMessage
  268. // Enumerate through the qos policies specified by the user and convert
  269. // them into the internal structure matching the JSON blob that can be
  270. // understood by the HCS.
  271. for _, elem := range qosPolicies {
  272. encodedPolicy, err := json.Marshal(hcsshim.QosPolicy{
  273. Type: "QOS",
  274. MaximumOutgoingBandwidthInBytes: elem.MaxEgressBandwidth,
  275. })
  276. if err != nil {
  277. return nil, err
  278. }
  279. qps = append(qps, encodedPolicy)
  280. }
  281. return qps, nil
  282. }
  283. func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
  284. var pbs []json.RawMessage
  285. // Enumerate through the port bindings specified by the user and convert
  286. // them into the internal structure matching the JSON blob that can be
  287. // understood by the HCS.
  288. for _, elem := range portBindings {
  289. proto := strings.ToUpper(elem.Proto.String())
  290. if proto != "TCP" && proto != "UDP" {
  291. return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
  292. }
  293. if elem.HostPort != elem.HostPortEnd {
  294. return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
  295. }
  296. if len(elem.HostIP) != 0 {
  297. return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
  298. }
  299. encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
  300. Type: "NAT",
  301. ExternalPort: elem.HostPort,
  302. InternalPort: elem.Port,
  303. Protocol: elem.Proto.String(),
  304. })
  305. if err != nil {
  306. return nil, err
  307. }
  308. pbs = append(pbs, encodedPolicy)
  309. }
  310. return pbs, nil
  311. }
  312. func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
  313. var bindings []types.PortBinding
  314. hcsPolicy := &hcsshim.NatPolicy{}
  315. for _, elem := range policies {
  316. if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
  317. continue
  318. }
  319. binding := types.PortBinding{
  320. HostPort: hcsPolicy.ExternalPort,
  321. HostPortEnd: hcsPolicy.ExternalPort,
  322. Port: hcsPolicy.InternalPort,
  323. Proto: types.ParseProtocol(hcsPolicy.Protocol),
  324. HostIP: net.IPv4(0, 0, 0, 0),
  325. }
  326. bindings = append(bindings, binding)
  327. }
  328. return bindings, nil
  329. }
  330. func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
  331. if epOptions == nil {
  332. return nil, nil
  333. }
  334. ec := &endpointOption{}
  335. if opt, ok := epOptions[netlabel.MacAddress]; ok {
  336. if mac, ok := opt.(net.HardwareAddr); ok {
  337. ec.MacAddress = mac
  338. } else {
  339. return nil, fmt.Errorf("Invalid endpoint configuration")
  340. }
  341. }
  342. if opt, ok := epOptions[QosPolicies]; ok {
  343. if policies, ok := opt.([]types.QosPolicy); ok {
  344. ec.QosPolicies = policies
  345. } else {
  346. return nil, fmt.Errorf("Invalid endpoint configuration")
  347. }
  348. }
  349. if opt, ok := epOptions[netlabel.DNSServers]; ok {
  350. if dns, ok := opt.([]string); ok {
  351. ec.DNSServers = dns
  352. } else {
  353. return nil, fmt.Errorf("Invalid endpoint configuration")
  354. }
  355. }
  356. if opt, ok := epOptions[DisableICC]; ok {
  357. if disableICC, ok := opt.(bool); ok {
  358. ec.DisableICC = disableICC
  359. } else {
  360. return nil, fmt.Errorf("Invalid endpoint configuration")
  361. }
  362. }
  363. if opt, ok := epOptions[DisableDNS]; ok {
  364. if disableDNS, ok := opt.(bool); ok {
  365. ec.DisableDNS = disableDNS
  366. } else {
  367. return nil, fmt.Errorf("Invalid endpoint configuration")
  368. }
  369. }
  370. return ec, nil
  371. }
  372. func parseEndpointConnectivity(epOptions map[string]interface{}) (*endpointConnectivity, error) {
  373. if epOptions == nil {
  374. return nil, nil
  375. }
  376. ec := &endpointConnectivity{}
  377. if opt, ok := epOptions[netlabel.PortMap]; ok {
  378. if bs, ok := opt.([]types.PortBinding); ok {
  379. ec.PortBindings = bs
  380. } else {
  381. return nil, fmt.Errorf("Invalid endpoint configuration")
  382. }
  383. }
  384. if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
  385. if ports, ok := opt.([]types.TransportPort); ok {
  386. ec.ExposedPorts = ports
  387. } else {
  388. return nil, fmt.Errorf("Invalid endpoint configuration")
  389. }
  390. }
  391. return ec, nil
  392. }
  393. func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
  394. n, err := d.getNetwork(nid)
  395. if err != nil {
  396. return err
  397. }
  398. // Check if endpoint id is good and retrieve corresponding endpoint
  399. ep, err := n.getEndpoint(eid)
  400. if err == nil && ep != nil {
  401. return driverapi.ErrEndpointExists(eid)
  402. }
  403. endpointStruct := &hcsshim.HNSEndpoint{
  404. VirtualNetwork: n.config.HnsID,
  405. }
  406. epOption, err := parseEndpointOptions(epOptions)
  407. epConnectivity, err := parseEndpointConnectivity(epOptions)
  408. macAddress := ifInfo.MacAddress()
  409. // Use the macaddress if it was provided
  410. if macAddress != nil {
  411. endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
  412. }
  413. endpointStruct.Policies, err = convertPortBindings(epConnectivity.PortBindings)
  414. if err != nil {
  415. return err
  416. }
  417. qosPolicies, err := convertQosPolicies(epOption.QosPolicies)
  418. if err != nil {
  419. return err
  420. }
  421. endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...)
  422. if ifInfo.Address() != nil {
  423. endpointStruct.IPAddress = ifInfo.Address().IP
  424. }
  425. endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
  426. if n.driver.name == "nat" && !epOption.DisableDNS {
  427. endpointStruct.EnableInternalDNS = true
  428. }
  429. endpointStruct.DisableICC = epOption.DisableICC
  430. configurationb, err := json.Marshal(endpointStruct)
  431. if err != nil {
  432. return err
  433. }
  434. hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
  435. if err != nil {
  436. return err
  437. }
  438. mac, err := net.ParseMAC(hnsresponse.MacAddress)
  439. if err != nil {
  440. return err
  441. }
  442. // TODO For now the ip mask is not in the info generated by HNS
  443. endpoint := &hnsEndpoint{
  444. id: eid,
  445. addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
  446. macAddress: mac,
  447. }
  448. if hnsresponse.GatewayAddress != "" {
  449. endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress)
  450. }
  451. endpoint.profileID = hnsresponse.Id
  452. endpoint.epConnectivity = epConnectivity
  453. endpoint.epOption = epOption
  454. endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies)
  455. if err != nil {
  456. hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
  457. return err
  458. }
  459. n.Lock()
  460. n.endpoints[eid] = endpoint
  461. n.Unlock()
  462. if ifInfo.Address() == nil {
  463. ifInfo.SetIPAddress(endpoint.addr)
  464. }
  465. if macAddress == nil {
  466. ifInfo.SetMacAddress(endpoint.macAddress)
  467. }
  468. return nil
  469. }
  470. func (d *driver) DeleteEndpoint(nid, eid string) error {
  471. n, err := d.getNetwork(nid)
  472. if err != nil {
  473. return types.InternalMaskableErrorf("%s", err)
  474. }
  475. ep, err := n.getEndpoint(eid)
  476. if err != nil {
  477. return err
  478. }
  479. n.Lock()
  480. delete(n.endpoints, eid)
  481. n.Unlock()
  482. _, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
  483. if err != nil {
  484. return err
  485. }
  486. return nil
  487. }
  488. func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
  489. network, err := d.getNetwork(nid)
  490. if err != nil {
  491. return nil, err
  492. }
  493. ep, err := network.getEndpoint(eid)
  494. if err != nil {
  495. return nil, err
  496. }
  497. data := make(map[string]interface{}, 1)
  498. if network.driver.name == "nat" {
  499. data["AllowUnqualifiedDNSQuery"] = true
  500. }
  501. data["hnsid"] = ep.profileID
  502. if ep.epConnectivity.ExposedPorts != nil {
  503. // Return a copy of the config data
  504. epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts))
  505. for _, tp := range ep.epConnectivity.ExposedPorts {
  506. epc = append(epc, tp.GetCopy())
  507. }
  508. data[netlabel.ExposedPorts] = epc
  509. }
  510. if ep.portMapping != nil {
  511. // Return a copy of the operational data
  512. pmc := make([]types.PortBinding, 0, len(ep.portMapping))
  513. for _, pm := range ep.portMapping {
  514. pmc = append(pmc, pm.GetCopy())
  515. }
  516. data[netlabel.PortMap] = pmc
  517. }
  518. if len(ep.macAddress) != 0 {
  519. data[netlabel.MacAddress] = ep.macAddress
  520. }
  521. return data, nil
  522. }
  523. // Join method is invoked when a Sandbox is attached to an endpoint.
  524. func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
  525. network, err := d.getNetwork(nid)
  526. if err != nil {
  527. return err
  528. }
  529. // Ensure that the endpoint exists
  530. endpoint, err := network.getEndpoint(eid)
  531. if err != nil {
  532. return err
  533. }
  534. err = jinfo.SetGateway(endpoint.gateway)
  535. if err != nil {
  536. return err
  537. }
  538. // This is just a stub for now
  539. jinfo.DisableGatewayService()
  540. return nil
  541. }
  542. // Leave method is invoked when a Sandbox detaches from an endpoint.
  543. func (d *driver) Leave(nid, eid string) error {
  544. network, err := d.getNetwork(nid)
  545. if err != nil {
  546. return types.InternalMaskableErrorf("%s", err)
  547. }
  548. // Ensure that the endpoint exists
  549. _, err = network.getEndpoint(eid)
  550. if err != nil {
  551. return err
  552. }
  553. // This is just a stub for now
  554. return nil
  555. }
  556. func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
  557. return nil
  558. }
  559. func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
  560. return nil
  561. }
  562. func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
  563. return nil, types.NotImplementedErrorf("not implemented")
  564. }
  565. func (d *driver) NetworkFree(id string) error {
  566. return types.NotImplementedErrorf("not implemented")
  567. }
  568. func (d *driver) Type() string {
  569. return d.name
  570. }
  571. func (d *driver) IsBuiltIn() bool {
  572. return true
  573. }
  574. // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
  575. func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
  576. return nil
  577. }
  578. // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
  579. func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
  580. return nil
  581. }