bridge.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. package bridge
  2. import (
  3. "net"
  4. "strings"
  5. "sync"
  6. "github.com/docker/libnetwork/driverapi"
  7. "github.com/docker/libnetwork/ipallocator"
  8. "github.com/docker/libnetwork/netutils"
  9. "github.com/docker/libnetwork/pkg/options"
  10. "github.com/docker/libnetwork/portmapper"
  11. "github.com/docker/libnetwork/sandbox"
  12. "github.com/docker/libnetwork/types"
  13. "github.com/vishvananda/netlink"
  14. )
  15. const (
  16. networkType = "bridge"
  17. vethPrefix = "veth"
  18. vethLen = 7
  19. containerVeth = "eth0"
  20. maxAllocatePortAttempts = 10
  21. )
  22. var (
  23. ipAllocator *ipallocator.IPAllocator
  24. portMapper *portmapper.PortMapper
  25. )
  26. // Configuration info for the "bridge" driver.
  27. type Configuration struct {
  28. BridgeName string
  29. AddressIPv4 *net.IPNet
  30. FixedCIDR *net.IPNet
  31. FixedCIDRv6 *net.IPNet
  32. EnableIPv6 bool
  33. EnableIPTables bool
  34. EnableIPMasquerade bool
  35. EnableICC bool
  36. EnableIPForwarding bool
  37. AllowNonDefaultBridge bool
  38. Mtu int
  39. DefaultGatewayIPv4 net.IP
  40. DefaultGatewayIPv6 net.IP
  41. DefaultBindingIP net.IP
  42. }
  43. // EndpointConfiguration represents the user specified configuration for the sandbox endpoint
  44. type EndpointConfiguration struct {
  45. MacAddress net.HardwareAddr
  46. PortBindings []netutils.PortBinding
  47. }
  48. // ContainerConfiguration represents the user specified configuration for a container
  49. type ContainerConfiguration struct {
  50. parentEndpoints []types.UUID
  51. childEndpoints []types.UUID
  52. }
  53. type bridgeEndpoint struct {
  54. id types.UUID
  55. intf *sandbox.Interface
  56. config *EndpointConfiguration // User specified parameters
  57. portMapping []netutils.PortBinding // Operation port bindings
  58. }
  59. type bridgeNetwork struct {
  60. id types.UUID
  61. bridge *bridgeInterface // The bridge's L3 interface
  62. endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
  63. sync.Mutex
  64. }
  65. type driver struct {
  66. config *Configuration
  67. network *bridgeNetwork
  68. sync.Mutex
  69. }
  70. func init() {
  71. ipAllocator = ipallocator.New()
  72. portMapper = portmapper.New()
  73. }
  74. // New provides a new instance of bridge driver
  75. func New() (string, driverapi.Driver) {
  76. return networkType, &driver{}
  77. }
  78. // Validate performs a static validation on the configuration parameters.
  79. // Whatever can be assessed a priori before attempting any programming.
  80. func (c *Configuration) Validate() error {
  81. if c.Mtu < 0 {
  82. return ErrInvalidMtu
  83. }
  84. // If bridge v4 subnet is specified
  85. if c.AddressIPv4 != nil {
  86. // If Container restricted subnet is specified, it must be a subset of bridge subnet
  87. if c.FixedCIDR != nil {
  88. // Check Network address
  89. if !c.AddressIPv4.Contains(c.FixedCIDR.IP) {
  90. return ErrInvalidContainerSubnet
  91. }
  92. // Check it is effectively a subset
  93. brNetLen, _ := c.AddressIPv4.Mask.Size()
  94. cnNetLen, _ := c.FixedCIDR.Mask.Size()
  95. if brNetLen > cnNetLen {
  96. return ErrInvalidContainerSubnet
  97. }
  98. }
  99. // If default gw is specified, it must be part of bridge subnet
  100. if c.DefaultGatewayIPv4 != nil {
  101. if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
  102. return ErrInvalidGateway
  103. }
  104. }
  105. }
  106. // If default v6 gw is specified, FixedCIDRv6 must be specified and gw must belong to FixedCIDRv6 subnet
  107. if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil {
  108. if c.FixedCIDRv6 == nil || !c.FixedCIDRv6.Contains(c.DefaultGatewayIPv6) {
  109. return ErrInvalidGateway
  110. }
  111. }
  112. return nil
  113. }
  114. func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
  115. n.Lock()
  116. defer n.Unlock()
  117. if eid == "" {
  118. return nil, InvalidEndpointIDError(eid)
  119. }
  120. if ep, ok := n.endpoints[eid]; ok {
  121. return ep, nil
  122. }
  123. return nil, nil
  124. }
  125. func (d *driver) Config(option map[string]interface{}) error {
  126. var config *Configuration
  127. d.Lock()
  128. defer d.Unlock()
  129. if d.config != nil {
  130. return ErrConfigExists
  131. }
  132. genericData := option[options.GenericData]
  133. if genericData != nil {
  134. switch opt := genericData.(type) {
  135. case options.Generic:
  136. opaqueConfig, err := options.GenerateFromModel(opt, &Configuration{})
  137. if err != nil {
  138. return err
  139. }
  140. config = opaqueConfig.(*Configuration)
  141. case *Configuration:
  142. config = opt
  143. default:
  144. return ErrInvalidDriverConfig
  145. }
  146. if err := config.Validate(); err != nil {
  147. return err
  148. }
  149. d.config = config
  150. }
  151. return nil
  152. }
  153. func (d *driver) getNetwork(id types.UUID) (*bridgeNetwork, error) {
  154. // Just a dummy function to return the only network managed by Bridge driver.
  155. // But this API makes the caller code unchanged when we move to support multiple networks.
  156. return d.network, nil
  157. }
  158. // Create a new network using bridge plugin
  159. func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
  160. var err error
  161. // Driver must be configured
  162. d.Lock()
  163. if d.config == nil {
  164. d.Unlock()
  165. return ErrInvalidNetworkConfig
  166. }
  167. config := d.config
  168. // Sanity checks
  169. if d.network != nil {
  170. d.Unlock()
  171. return ErrNetworkExists
  172. }
  173. // Create and set network handler in driver
  174. d.network = &bridgeNetwork{id: id, endpoints: make(map[types.UUID]*bridgeEndpoint)}
  175. d.Unlock()
  176. // On failure make sure to reset driver network handler to nil
  177. defer func() {
  178. if err != nil {
  179. d.Lock()
  180. d.network = nil
  181. d.Unlock()
  182. }
  183. }()
  184. // Create or retrieve the bridge L3 interface
  185. bridgeIface := newInterface(config)
  186. d.network.bridge = bridgeIface
  187. // Prepare the bridge setup configuration
  188. bridgeSetup := newBridgeSetup(config, bridgeIface)
  189. // If the bridge interface doesn't exist, we need to start the setup steps
  190. // by creating a new device and assigning it an IPv4 address.
  191. bridgeAlreadyExists := bridgeIface.exists()
  192. if !bridgeAlreadyExists {
  193. bridgeSetup.queueStep(setupDevice)
  194. bridgeSetup.queueStep(setupBridgeIPv4)
  195. }
  196. // Conditionnally queue setup steps depending on configuration values.
  197. for _, step := range []struct {
  198. Condition bool
  199. Fn setupStep
  200. }{
  201. // Enable IPv6 on the bridge if required. We do this even for a
  202. // previously existing bridge, as it may be here from a previous
  203. // installation where IPv6 wasn't supported yet and needs to be
  204. // assigned an IPv6 link-local address.
  205. {config.EnableIPv6, setupBridgeIPv6},
  206. // We ensure that the bridge has the expectedIPv4 and IPv6 addresses in
  207. // the case of a previously existing device.
  208. {bridgeAlreadyExists, setupVerifyAndReconcile},
  209. // Setup the bridge to allocate containers IPv4 addresses in the
  210. // specified subnet.
  211. {config.FixedCIDR != nil, setupFixedCIDRv4},
  212. // Setup the bridge to allocate containers global IPv6 addresses in the
  213. // specified subnet.
  214. {config.FixedCIDRv6 != nil, setupFixedCIDRv6},
  215. // Setup IPTables.
  216. {config.EnableIPTables, setupIPTables},
  217. // Setup IP forwarding.
  218. {config.EnableIPForwarding, setupIPForwarding},
  219. // Setup DefaultGatewayIPv4
  220. {config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
  221. // Setup DefaultGatewayIPv6
  222. {config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},
  223. } {
  224. if step.Condition {
  225. bridgeSetup.queueStep(step.Fn)
  226. }
  227. }
  228. // Apply the prepared list of steps, and abort at the first error.
  229. bridgeSetup.queueStep(setupDeviceUp)
  230. if err = bridgeSetup.apply(); err != nil {
  231. return err
  232. }
  233. return nil
  234. }
  235. func (d *driver) DeleteNetwork(nid types.UUID) error {
  236. var err error
  237. // Get network handler and remove it from driver
  238. d.Lock()
  239. n := d.network
  240. d.network = nil
  241. d.Unlock()
  242. // On failure set network handler back in driver, but
  243. // only if is not already taken over by some other thread
  244. defer func() {
  245. if err != nil {
  246. d.Lock()
  247. if d.network == nil {
  248. d.network = n
  249. }
  250. d.Unlock()
  251. }
  252. }()
  253. // Sanity check
  254. if n == nil {
  255. err = driverapi.ErrNoNetwork
  256. return err
  257. }
  258. // Cannot remove network if endpoints are still present
  259. if len(n.endpoints) != 0 {
  260. err = ActiveEndpointsError(n.id)
  261. return err
  262. }
  263. // Programming
  264. err = netlink.LinkDel(n.bridge.Link)
  265. return err
  266. }
  267. func (d *driver) CreateEndpoint(nid, eid types.UUID, epOptions map[string]interface{}) (*sandbox.Info, error) {
  268. var (
  269. ipv6Addr *net.IPNet
  270. err error
  271. )
  272. // Get the network handler and make sure it exists
  273. d.Lock()
  274. n := d.network
  275. config := d.config
  276. d.Unlock()
  277. if n == nil {
  278. return nil, driverapi.ErrNoNetwork
  279. }
  280. // Sanity check
  281. n.Lock()
  282. if n.id != nid {
  283. n.Unlock()
  284. return nil, InvalidNetworkIDError(nid)
  285. }
  286. n.Unlock()
  287. // Check if endpoint id is good and retrieve correspondent endpoint
  288. ep, err := n.getEndpoint(eid)
  289. if err != nil {
  290. return nil, err
  291. }
  292. // Endpoint with that id exists either on desired or other sandbox
  293. if ep != nil {
  294. return nil, driverapi.ErrEndpointExists
  295. }
  296. // Try to convert the options to endpoint configuration
  297. epConfig, err := parseEndpointOptions(epOptions)
  298. if err != nil {
  299. return nil, err
  300. }
  301. // Create and add the endpoint
  302. n.Lock()
  303. endpoint := &bridgeEndpoint{id: eid, config: epConfig}
  304. n.endpoints[eid] = endpoint
  305. n.Unlock()
  306. // On failure make sure to remove the endpoint
  307. defer func() {
  308. if err != nil {
  309. n.Lock()
  310. delete(n.endpoints, eid)
  311. n.Unlock()
  312. }
  313. }()
  314. // Generate a name for what will be the host side pipe interface
  315. name1, err := generateIfaceName()
  316. if err != nil {
  317. return nil, err
  318. }
  319. // Generate a name for what will be the sandbox side pipe interface
  320. name2, err := generateIfaceName()
  321. if err != nil {
  322. return nil, err
  323. }
  324. // Generate and add the interface pipe host <-> sandbox
  325. veth := &netlink.Veth{
  326. LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
  327. PeerName: name2}
  328. if err = netlink.LinkAdd(veth); err != nil {
  329. return nil, err
  330. }
  331. // Get the host side pipe interface handler
  332. host, err := netlink.LinkByName(name1)
  333. if err != nil {
  334. return nil, err
  335. }
  336. defer func() {
  337. if err != nil {
  338. netlink.LinkDel(host)
  339. }
  340. }()
  341. // Get the sandbox side pipe interface handler
  342. sbox, err := netlink.LinkByName(name2)
  343. if err != nil {
  344. return nil, err
  345. }
  346. defer func() {
  347. if err != nil {
  348. netlink.LinkDel(sbox)
  349. }
  350. }()
  351. // Set the sbox's MAC. If specified, use the one configured by user, otherwise use a random one
  352. mac := electMacAddress(epConfig)
  353. err = netlink.LinkSetHardwareAddr(sbox, mac)
  354. if err != nil {
  355. return nil, err
  356. }
  357. // Add bridge inherited attributes to pipe interfaces
  358. if config.Mtu != 0 {
  359. err = netlink.LinkSetMTU(host, config.Mtu)
  360. if err != nil {
  361. return nil, err
  362. }
  363. err = netlink.LinkSetMTU(sbox, config.Mtu)
  364. if err != nil {
  365. return nil, err
  366. }
  367. }
  368. // Attach host side pipe interface into the bridge
  369. if err = netlink.LinkSetMaster(host,
  370. &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil {
  371. return nil, err
  372. }
  373. // v4 address for the sandbox side pipe interface
  374. ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
  375. if err != nil {
  376. return nil, err
  377. }
  378. ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
  379. // v6 address for the sandbox side pipe interface
  380. if config.EnableIPv6 {
  381. var ip6 net.IP
  382. network := n.bridge.bridgeIPv6
  383. if config.FixedCIDRv6 != nil {
  384. network = config.FixedCIDRv6
  385. }
  386. ones, _ := network.Mask.Size()
  387. if ones <= 80 {
  388. ip6 = make(net.IP, len(network.IP))
  389. copy(ip6, network.IP)
  390. for i, h := range mac {
  391. ip6[i+10] = h
  392. }
  393. }
  394. ip6, err := ipAllocator.RequestIP(network, ip6)
  395. if err != nil {
  396. return nil, err
  397. }
  398. ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask}
  399. }
  400. // Create the sandbox side pipe interface
  401. intf := &sandbox.Interface{}
  402. intf.SrcName = name2
  403. intf.DstName = containerVeth
  404. intf.Address = ipv4Addr
  405. // Store the interface in endpoint, this is needed for cleanup on DeleteEndpoint()
  406. endpoint.intf = intf
  407. // Generate the sandbox info to return
  408. sinfo := &sandbox.Info{Interfaces: []*sandbox.Interface{intf}}
  409. // Set the default gateway(s) for the sandbox
  410. sinfo.Gateway = n.bridge.gatewayIPv4
  411. if config.EnableIPv6 {
  412. intf.AddressIPv6 = ipv6Addr
  413. sinfo.GatewayIPv6 = n.bridge.gatewayIPv6
  414. }
  415. // Program any required port mapping and store them in the endpoint
  416. endpoint.portMapping, err = allocatePorts(epConfig, sinfo, config.DefaultBindingIP)
  417. if err != nil {
  418. return nil, err
  419. }
  420. return sinfo, nil
  421. }
  422. func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
  423. var err error
  424. // Get the network handler and make sure it exists
  425. d.Lock()
  426. n := d.network
  427. config := d.config
  428. d.Unlock()
  429. if n == nil {
  430. return driverapi.ErrNoNetwork
  431. }
  432. // Sanity Check
  433. n.Lock()
  434. if n.id != nid {
  435. n.Unlock()
  436. return InvalidNetworkIDError(nid)
  437. }
  438. n.Unlock()
  439. // Check endpoint id and if an endpoint is actually there
  440. ep, err := n.getEndpoint(eid)
  441. if err != nil {
  442. return err
  443. }
  444. if ep == nil {
  445. return EndpointNotFoundError(eid)
  446. }
  447. // Remove it
  448. n.Lock()
  449. delete(n.endpoints, eid)
  450. n.Unlock()
  451. // On failure make sure to set back ep in n.endpoints, but only
  452. // if it hasn't been taken over already by some other thread.
  453. defer func() {
  454. if err != nil {
  455. n.Lock()
  456. if _, ok := n.endpoints[eid]; !ok {
  457. n.endpoints[eid] = ep
  458. }
  459. n.Unlock()
  460. }
  461. }()
  462. // Remove port mappings. Do not stop endpoint delete on unmap failure
  463. releasePorts(ep)
  464. // Release the v4 address allocated to this endpoint's sandbox interface
  465. err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.intf.Address.IP)
  466. if err != nil {
  467. return err
  468. }
  469. // Release the v6 address allocated to this endpoint's sandbox interface
  470. if config.EnableIPv6 {
  471. err := ipAllocator.ReleaseIP(n.bridge.bridgeIPv6, ep.intf.AddressIPv6.IP)
  472. if err != nil {
  473. return err
  474. }
  475. }
  476. // Try removal of link. Discard error: link pair might have
  477. // already been deleted by sandbox delete.
  478. link, err := netlink.LinkByName(ep.intf.SrcName)
  479. if err == nil {
  480. netlink.LinkDel(link)
  481. }
  482. return nil
  483. }
  484. func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
  485. // Get the network handler and make sure it exists
  486. d.Lock()
  487. n := d.network
  488. d.Unlock()
  489. if n == nil {
  490. return nil, driverapi.ErrNoNetwork
  491. }
  492. // Sanity check
  493. n.Lock()
  494. if n.id != nid {
  495. n.Unlock()
  496. return nil, InvalidNetworkIDError(nid)
  497. }
  498. n.Unlock()
  499. // Check if endpoint id is good and retrieve correspondent endpoint
  500. ep, err := n.getEndpoint(eid)
  501. if err != nil {
  502. return nil, err
  503. }
  504. if ep == nil {
  505. return nil, driverapi.ErrNoEndpoint
  506. }
  507. m := make(map[string]interface{})
  508. if ep.portMapping != nil {
  509. // Return a copy of the operational data
  510. pmc := make([]netutils.PortBinding, 0, len(ep.portMapping))
  511. for _, pm := range ep.portMapping {
  512. pmc = append(pmc, pm.GetCopy())
  513. }
  514. m[options.PortMap] = pmc
  515. }
  516. return m, nil
  517. }
  518. // Join method is invoked when a Sandbox is attached to an endpoint.
  519. func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error {
  520. var err error
  521. if !d.config.EnableICC {
  522. err = d.link(nid, eid, options, true)
  523. }
  524. return err
  525. }
  526. // Leave method is invoked when a Sandbox detaches from an endpoint.
  527. func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) error {
  528. var err error
  529. if !d.config.EnableICC {
  530. err = d.link(nid, eid, options, false)
  531. }
  532. return err
  533. }
  534. func (d *driver) link(nid, eid types.UUID, options map[string]interface{}, enable bool) error {
  535. network, err := d.getNetwork(nid)
  536. if err != nil {
  537. return err
  538. }
  539. endpoint, err := network.getEndpoint(eid)
  540. if err != nil {
  541. return err
  542. }
  543. if endpoint == nil {
  544. return EndpointNotFoundError(eid)
  545. }
  546. cc, err := parseContainerOptions(options)
  547. if err != nil {
  548. return err
  549. }
  550. if cc == nil {
  551. return nil
  552. }
  553. if endpoint.config != nil && endpoint.config.PortBindings != nil {
  554. for _, p := range cc.parentEndpoints {
  555. var parentEndpoint *bridgeEndpoint
  556. parentEndpoint, err = network.getEndpoint(p)
  557. if err != nil {
  558. return err
  559. }
  560. if parentEndpoint == nil {
  561. err = InvalidEndpointIDError(string(p))
  562. return err
  563. }
  564. l := newLink(parentEndpoint.intf.Address.IP.String(),
  565. endpoint.intf.Address.IP.String(),
  566. endpoint.config.PortBindings, d.config.BridgeName)
  567. if enable {
  568. err = l.Enable()
  569. if err != nil {
  570. return err
  571. }
  572. defer func() {
  573. if err != nil {
  574. l.Disable()
  575. }
  576. }()
  577. } else {
  578. l.Disable()
  579. }
  580. }
  581. }
  582. for _, c := range cc.childEndpoints {
  583. var childEndpoint *bridgeEndpoint
  584. childEndpoint, err = network.getEndpoint(c)
  585. if err != nil {
  586. return err
  587. }
  588. if childEndpoint == nil {
  589. err = InvalidEndpointIDError(string(c))
  590. return err
  591. }
  592. if childEndpoint.config == nil || childEndpoint.config.PortBindings == nil {
  593. continue
  594. }
  595. l := newLink(endpoint.intf.Address.IP.String(),
  596. childEndpoint.intf.Address.IP.String(),
  597. childEndpoint.config.PortBindings, d.config.BridgeName)
  598. if enable {
  599. err = l.Enable()
  600. if err != nil {
  601. return err
  602. }
  603. defer func() {
  604. if err != nil {
  605. l.Disable()
  606. }
  607. }()
  608. } else {
  609. l.Disable()
  610. }
  611. }
  612. return nil
  613. }
  614. func (d *driver) Type() string {
  615. return networkType
  616. }
  617. func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfiguration, error) {
  618. if epOptions == nil {
  619. return nil, nil
  620. }
  621. ec := &EndpointConfiguration{}
  622. if opt, ok := epOptions[options.MacAddress]; ok {
  623. if mac, ok := opt.(net.HardwareAddr); ok {
  624. ec.MacAddress = mac
  625. } else {
  626. return nil, ErrInvalidEndpointConfig
  627. }
  628. }
  629. if opt, ok := epOptions[options.PortMap]; ok {
  630. if bs, ok := opt.([]netutils.PortBinding); ok {
  631. ec.PortBindings = bs
  632. } else {
  633. return nil, ErrInvalidEndpointConfig
  634. }
  635. }
  636. return ec, nil
  637. }
  638. func parseContainerOptions(cOptions map[string]interface{}) (*ContainerConfiguration, error) {
  639. if cOptions == nil {
  640. return nil, nil
  641. }
  642. genericData := cOptions[options.GenericData]
  643. if genericData == nil {
  644. return nil, nil
  645. }
  646. switch opt := genericData.(type) {
  647. case options.Generic:
  648. opaqueConfig, err := options.GenerateFromModel(opt, &ContainerConfiguration{})
  649. if err != nil {
  650. return nil, err
  651. }
  652. return opaqueConfig.(*ContainerConfiguration), nil
  653. case *ContainerConfiguration:
  654. return opt, nil
  655. default:
  656. return nil, nil
  657. }
  658. }
  659. func electMacAddress(epConfig *EndpointConfiguration) net.HardwareAddr {
  660. if epConfig != nil && epConfig.MacAddress != nil {
  661. return epConfig.MacAddress
  662. }
  663. return netutils.GenerateRandomMAC()
  664. }
  665. // Generates a name to be used for a virtual ethernet
  666. // interface. The name is constructed by 'veth' appended
  667. // by a randomly generated hex value. (example: veth0f60e2c)
  668. func generateIfaceName() (string, error) {
  669. for i := 0; i < 3; i++ {
  670. name, err := netutils.GenerateRandomName(vethPrefix, vethLen)
  671. if err != nil {
  672. continue
  673. }
  674. if _, err := net.InterfaceByName(name); err != nil {
  675. if strings.Contains(err.Error(), "no such") {
  676. return name, nil
  677. }
  678. return "", err
  679. }
  680. }
  681. return "", ErrIfaceName
  682. }