macvlan_network.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //go:build linux
  2. // +build linux
  3. package macvlan
  4. import (
  5. "fmt"
  6. "github.com/docker/docker/libnetwork/driverapi"
  7. "github.com/docker/docker/libnetwork/netlabel"
  8. "github.com/docker/docker/libnetwork/ns"
  9. "github.com/docker/docker/libnetwork/options"
  10. "github.com/docker/docker/libnetwork/osl"
  11. "github.com/docker/docker/libnetwork/types"
  12. "github.com/docker/docker/pkg/stringid"
  13. "github.com/sirupsen/logrus"
  14. )
  15. // CreateNetwork the network for the specified driver type
  16. func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
  17. defer osl.InitOSContext()()
  18. // reject a null v4 network
  19. if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
  20. return fmt.Errorf("ipv4 pool is empty")
  21. }
  22. // parse and validate the config and bind to networkConfiguration
  23. config, err := parseNetworkOptions(nid, option)
  24. if err != nil {
  25. return err
  26. }
  27. config.processIPAM(ipV4Data, ipV6Data)
  28. // if parent interface not specified, create a dummy type link to use named dummy+net_id
  29. if config.Parent == "" {
  30. config.Parent = getDummyName(stringid.TruncateID(config.ID))
  31. }
  32. foundExisting, err := d.createNetwork(config)
  33. if err != nil {
  34. return err
  35. }
  36. if foundExisting {
  37. return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
  38. }
  39. // update persistent db, rollback on fail
  40. err = d.storeUpdate(config)
  41. if err != nil {
  42. d.deleteNetwork(config.ID)
  43. logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
  44. return err
  45. }
  46. return nil
  47. }
  48. // createNetwork is used by new network callbacks and persistent network cache
  49. func (d *driver) createNetwork(config *configuration) (bool, error) {
  50. foundExisting := false
  51. networkList := d.getNetworks()
  52. for _, nw := range networkList {
  53. if config.Parent == nw.config.Parent {
  54. if config.ID != nw.config.ID {
  55. return false, fmt.Errorf("network %s is already using parent interface %s",
  56. getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
  57. }
  58. logrus.Debugf("Create Network for the same ID %s\n", config.ID)
  59. foundExisting = true
  60. break
  61. }
  62. }
  63. if !parentExists(config.Parent) {
  64. // Create a dummy link if a dummy name is set for parent
  65. if dummyName := getDummyName(stringid.TruncateID(config.ID)); dummyName == config.Parent {
  66. err := createDummyLink(config.Parent, dummyName)
  67. if err != nil {
  68. return false, err
  69. }
  70. config.CreatedSlaveLink = true
  71. // notify the user in logs that they have limited communications
  72. logrus.Debugf("Empty -o parent= limit communications to other containers inside of network: %s",
  73. config.Parent)
  74. } else {
  75. // if the subinterface parent_iface.vlan_id checks do not pass, return err.
  76. // a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
  77. err := createVlanLink(config.Parent)
  78. if err != nil {
  79. return false, err
  80. }
  81. // if driver created the networks slave link, record it for future deletion
  82. config.CreatedSlaveLink = true
  83. }
  84. }
  85. if !foundExisting {
  86. n := &network{
  87. id: config.ID,
  88. driver: d,
  89. endpoints: endpointTable{},
  90. config: config,
  91. }
  92. // add the network
  93. d.addNetwork(n)
  94. }
  95. return foundExisting, nil
  96. }
  97. // DeleteNetwork deletes the network for the specified driver type
  98. func (d *driver) DeleteNetwork(nid string) error {
  99. defer osl.InitOSContext()()
  100. n := d.network(nid)
  101. if n == nil {
  102. return fmt.Errorf("network id %s not found", nid)
  103. }
  104. // if the driver created the slave interface, delete it, otherwise leave it
  105. if ok := n.config.CreatedSlaveLink; ok {
  106. // if the interface exists, only delete if it matches iface.vlan or dummy.net_id naming
  107. if ok := parentExists(n.config.Parent); ok {
  108. // only delete the link if it is named the net_id
  109. if n.config.Parent == getDummyName(stringid.TruncateID(nid)) {
  110. err := delDummyLink(n.config.Parent)
  111. if err != nil {
  112. logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
  113. n.config.Parent, err)
  114. }
  115. } else {
  116. // only delete the link if it matches iface.vlan naming
  117. err := delVlanLink(n.config.Parent)
  118. if err != nil {
  119. logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
  120. n.config.Parent, err)
  121. }
  122. }
  123. }
  124. }
  125. for _, ep := range n.endpoints {
  126. if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
  127. if err := ns.NlHandle().LinkDel(link); err != nil {
  128. logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
  129. }
  130. }
  131. if err := d.storeDelete(ep); err != nil {
  132. logrus.Warnf("Failed to remove macvlan endpoint %.7s from store: %v", ep.id, err)
  133. }
  134. }
  135. // delete the *network
  136. d.deleteNetwork(nid)
  137. // delete the network record from persistent cache
  138. err := d.storeDelete(n.config)
  139. if err != nil {
  140. return fmt.Errorf("error deleting deleting id %s from datastore: %v", nid, err)
  141. }
  142. return nil
  143. }
  144. // parseNetworkOptions parses docker network options
  145. func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
  146. var (
  147. err error
  148. config = &configuration{}
  149. )
  150. // parse generic labels first
  151. if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
  152. if config, err = parseNetworkGenericOptions(genData); err != nil {
  153. return nil, err
  154. }
  155. }
  156. if val, ok := option[netlabel.Internal]; ok {
  157. if internal, ok := val.(bool); ok && internal {
  158. config.Internal = true
  159. }
  160. }
  161. // verify the macvlan mode from -o macvlan_mode option
  162. switch config.MacvlanMode {
  163. case "":
  164. // default to macvlan bridge mode if -o macvlan_mode is empty
  165. config.MacvlanMode = modeBridge
  166. case modeBridge, modePrivate, modePassthru, modeVepa:
  167. // valid option
  168. default:
  169. return nil, fmt.Errorf("requested macvlan mode '%s' is not valid, 'bridge' mode is the macvlan driver default", config.MacvlanMode)
  170. }
  171. // loopback is not a valid parent link
  172. if config.Parent == "lo" {
  173. return nil, fmt.Errorf("loopback interface is not a valid macvlan parent link")
  174. }
  175. config.ID = id
  176. return config, nil
  177. }
  178. // parseNetworkGenericOptions parses generic driver docker network options
  179. func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
  180. switch opt := data.(type) {
  181. case *configuration:
  182. return opt, nil
  183. case map[string]string:
  184. return newConfigFromLabels(opt), nil
  185. case options.Generic:
  186. var config *configuration
  187. opaqueConfig, err := options.GenerateFromModel(opt, config)
  188. if err != nil {
  189. return nil, err
  190. }
  191. return opaqueConfig.(*configuration), nil
  192. default:
  193. return nil, types.BadRequestErrorf("unrecognized network configuration format: %v", opt)
  194. }
  195. }
  196. // newConfigFromLabels creates a new configuration from the given labels.
  197. func newConfigFromLabels(labels map[string]string) *configuration {
  198. config := &configuration{}
  199. for label, value := range labels {
  200. switch label {
  201. case parentOpt:
  202. // parse driver option '-o parent'
  203. config.Parent = value
  204. case driverModeOpt:
  205. // parse driver option '-o macvlan_mode'
  206. config.MacvlanMode = value
  207. }
  208. }
  209. return config
  210. }
  211. // processIPAM parses v4 and v6 IP information and binds it to the network configuration
  212. func (config *configuration) processIPAM(ipamV4Data, ipamV6Data []driverapi.IPAMData) {
  213. for _, ipd := range ipamV4Data {
  214. config.Ipv4Subnets = append(config.Ipv4Subnets, &ipSubnet{
  215. SubnetIP: ipd.Pool.String(),
  216. GwIP: ipd.Gateway.String(),
  217. })
  218. }
  219. for _, ipd := range ipamV6Data {
  220. config.Ipv6Subnets = append(config.Ipv6Subnets, &ipSubnet{
  221. SubnetIP: ipd.Pool.String(),
  222. GwIP: ipd.Gateway.String(),
  223. })
  224. }
  225. }