github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/drivers/bridge/bridge.go (about) 1 //go:build linux 2 // +build linux 3 4 package bridge 5 6 import ( 7 "errors" 8 "fmt" 9 "net" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "strconv" 14 "sync" 15 "syscall" 16 17 "github.com/docker/docker/libnetwork/datastore" 18 "github.com/docker/docker/libnetwork/discoverapi" 19 "github.com/docker/docker/libnetwork/driverapi" 20 "github.com/docker/docker/libnetwork/iptables" 21 "github.com/docker/docker/libnetwork/netlabel" 22 "github.com/docker/docker/libnetwork/netutils" 23 "github.com/docker/docker/libnetwork/ns" 24 "github.com/docker/docker/libnetwork/options" 25 "github.com/docker/docker/libnetwork/osl" 26 "github.com/docker/docker/libnetwork/portmapper" 27 "github.com/docker/docker/libnetwork/types" 28 "github.com/sirupsen/logrus" 29 "github.com/vishvananda/netlink" 30 ) 31 32 const ( 33 networkType = "bridge" 34 vethPrefix = "veth" 35 vethLen = 7 36 defaultContainerVethPrefix = "eth" 37 maxAllocatePortAttempts = 10 38 ) 39 40 const ( 41 // DefaultGatewayV4AuxKey represents the default-gateway configured by the user 42 DefaultGatewayV4AuxKey = "DefaultGatewayIPv4" 43 // DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user 44 DefaultGatewayV6AuxKey = "DefaultGatewayIPv6" 45 ) 46 47 type defaultBridgeNetworkConflict struct { 48 ID string 49 } 50 51 func (d defaultBridgeNetworkConflict) Error() string { 52 return fmt.Sprintf("Stale default bridge network %s", d.ID) 53 } 54 55 type iptableCleanFunc func() error 56 type iptablesCleanFuncs []iptableCleanFunc 57 58 // configuration info for the "bridge" driver. 59 type configuration struct { 60 EnableIPForwarding bool 61 EnableIPTables bool 62 EnableIP6Tables bool 63 EnableUserlandProxy bool 64 UserlandProxyPath string 65 } 66 67 // networkConfiguration for network specific configuration 68 type networkConfiguration struct { 69 ID string 70 BridgeName string 71 EnableIPv6 bool 72 EnableIPMasquerade bool 73 EnableICC bool 74 InhibitIPv4 bool 75 Mtu int 76 DefaultBindingIP net.IP 77 DefaultBridge bool 78 HostIP net.IP 79 ContainerIfacePrefix string 80 // Internal fields set after ipam data parsing 81 AddressIPv4 *net.IPNet 82 AddressIPv6 *net.IPNet 83 DefaultGatewayIPv4 net.IP 84 DefaultGatewayIPv6 net.IP 85 dbIndex uint64 86 dbExists bool 87 Internal bool 88 89 BridgeIfaceCreator ifaceCreator 90 } 91 92 // ifaceCreator represents how the bridge interface was created 93 type ifaceCreator int8 94 95 const ( 96 ifaceCreatorUnknown ifaceCreator = iota 97 ifaceCreatedByLibnetwork 98 ifaceCreatedByUser 99 ) 100 101 // endpointConfiguration represents the user specified configuration for the sandbox endpoint 102 type endpointConfiguration struct { 103 MacAddress net.HardwareAddr 104 } 105 106 // containerConfiguration represents the user specified configuration for a container 107 type containerConfiguration struct { 108 ParentEndpoints []string 109 ChildEndpoints []string 110 } 111 112 // connectivityConfiguration represents the user specified configuration regarding the external connectivity 113 type connectivityConfiguration struct { 114 PortBindings []types.PortBinding 115 ExposedPorts []types.TransportPort 116 } 117 118 type bridgeEndpoint struct { 119 id string 120 nid string 121 srcName string 122 addr *net.IPNet 123 addrv6 *net.IPNet 124 macAddress net.HardwareAddr 125 config *endpointConfiguration // User specified parameters 126 containerConfig *containerConfiguration 127 extConnConfig *connectivityConfiguration 128 portMapping []types.PortBinding // Operation port bindings 129 dbIndex uint64 130 dbExists bool 131 } 132 133 type bridgeNetwork struct { 134 id string 135 bridge *bridgeInterface // The bridge's L3 interface 136 config *networkConfiguration 137 endpoints map[string]*bridgeEndpoint // key: endpoint id 138 portMapper *portmapper.PortMapper 139 portMapperV6 *portmapper.PortMapper 140 driver *driver // The network's driver 141 iptCleanFuncs iptablesCleanFuncs 142 sync.Mutex 143 } 144 145 type driver struct { 146 config *configuration 147 natChain *iptables.ChainInfo 148 filterChain *iptables.ChainInfo 149 isolationChain1 *iptables.ChainInfo 150 isolationChain2 *iptables.ChainInfo 151 natChainV6 *iptables.ChainInfo 152 filterChainV6 *iptables.ChainInfo 153 isolationChain1V6 *iptables.ChainInfo 154 isolationChain2V6 *iptables.ChainInfo 155 networks map[string]*bridgeNetwork 156 store datastore.DataStore 157 nlh *netlink.Handle 158 configNetwork sync.Mutex 159 sync.Mutex 160 } 161 162 // New constructs a new bridge driver 163 func newDriver() *driver { 164 return &driver{networks: map[string]*bridgeNetwork{}, config: &configuration{}} 165 } 166 167 // Init registers a new instance of bridge driver 168 func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { 169 d := newDriver() 170 if err := d.configure(config); err != nil { 171 return err 172 } 173 174 c := driverapi.Capability{ 175 DataScope: datastore.LocalScope, 176 ConnectivityScope: datastore.LocalScope, 177 } 178 return dc.RegisterDriver(networkType, d, c) 179 } 180 181 // Validate performs a static validation on the network configuration parameters. 182 // Whatever can be assessed a priori before attempting any programming. 183 func (c *networkConfiguration) Validate() error { 184 if c.Mtu < 0 { 185 return ErrInvalidMtu(c.Mtu) 186 } 187 188 // If bridge v4 subnet is specified 189 if c.AddressIPv4 != nil { 190 // If default gw is specified, it must be part of bridge subnet 191 if c.DefaultGatewayIPv4 != nil { 192 if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) { 193 return &ErrInvalidGateway{} 194 } 195 } 196 } 197 198 // If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet 199 if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil { 200 if c.AddressIPv6 == nil || !c.AddressIPv6.Contains(c.DefaultGatewayIPv6) { 201 return &ErrInvalidGateway{} 202 } 203 } 204 return nil 205 } 206 207 // Conflicts check if two NetworkConfiguration objects overlap 208 func (c *networkConfiguration) Conflicts(o *networkConfiguration) error { 209 if o == nil { 210 return errors.New("same configuration") 211 } 212 213 // Also empty, because only one network with empty name is allowed 214 if c.BridgeName == o.BridgeName { 215 return errors.New("networks have same bridge name") 216 } 217 218 // They must be in different subnets 219 if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) && 220 (c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) { 221 return errors.New("networks have overlapping IPv4") 222 } 223 224 // They must be in different v6 subnets 225 if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) && 226 (c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) { 227 return errors.New("networks have overlapping IPv6") 228 } 229 230 return nil 231 } 232 233 func (c *networkConfiguration) fromLabels(labels map[string]string) error { 234 var err error 235 for label, value := range labels { 236 switch label { 237 case BridgeName: 238 c.BridgeName = value 239 case netlabel.DriverMTU: 240 if c.Mtu, err = strconv.Atoi(value); err != nil { 241 return parseErr(label, value, err.Error()) 242 } 243 case netlabel.EnableIPv6: 244 if c.EnableIPv6, err = strconv.ParseBool(value); err != nil { 245 return parseErr(label, value, err.Error()) 246 } 247 case EnableIPMasquerade: 248 if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil { 249 return parseErr(label, value, err.Error()) 250 } 251 case EnableICC: 252 if c.EnableICC, err = strconv.ParseBool(value); err != nil { 253 return parseErr(label, value, err.Error()) 254 } 255 case InhibitIPv4: 256 if c.InhibitIPv4, err = strconv.ParseBool(value); err != nil { 257 return parseErr(label, value, err.Error()) 258 } 259 case DefaultBridge: 260 if c.DefaultBridge, err = strconv.ParseBool(value); err != nil { 261 return parseErr(label, value, err.Error()) 262 } 263 case DefaultBindingIP: 264 if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil { 265 return parseErr(label, value, "nil ip") 266 } 267 case netlabel.ContainerIfacePrefix: 268 c.ContainerIfacePrefix = value 269 case netlabel.HostIP: 270 if c.HostIP = net.ParseIP(value); c.HostIP == nil { 271 return parseErr(label, value, "nil ip") 272 } 273 } 274 } 275 276 return nil 277 } 278 279 func parseErr(label, value, errString string) error { 280 return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString) 281 } 282 283 func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) { 284 n.iptCleanFuncs = append(n.iptCleanFuncs, clean) 285 } 286 287 func (n *bridgeNetwork) getDriverChains(version iptables.IPVersion) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) { 288 n.Lock() 289 defer n.Unlock() 290 291 if n.driver == nil { 292 return nil, nil, nil, nil, types.BadRequestErrorf("no driver found") 293 } 294 295 if version == iptables.IPv6 { 296 return n.driver.natChainV6, n.driver.filterChainV6, n.driver.isolationChain1V6, n.driver.isolationChain2V6, nil 297 } 298 299 return n.driver.natChain, n.driver.filterChain, n.driver.isolationChain1, n.driver.isolationChain2, nil 300 } 301 302 func (n *bridgeNetwork) getNetworkBridgeName() string { 303 n.Lock() 304 config := n.config 305 n.Unlock() 306 307 return config.BridgeName 308 } 309 310 func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) { 311 n.Lock() 312 defer n.Unlock() 313 314 if eid == "" { 315 return nil, InvalidEndpointIDError(eid) 316 } 317 318 if ep, ok := n.endpoints[eid]; ok { 319 return ep, nil 320 } 321 322 return nil, nil 323 } 324 325 // Install/Removes the iptables rules needed to isolate this network 326 // from each of the other networks 327 func (n *bridgeNetwork) isolateNetwork(enable bool) error { 328 n.Lock() 329 thisConfig := n.config 330 n.Unlock() 331 332 if thisConfig.Internal { 333 return nil 334 } 335 336 // Install the rules to isolate this network against each of the other networks 337 if n.driver.config.EnableIP6Tables { 338 err := setINC(iptables.IPv6, thisConfig.BridgeName, enable) 339 if err != nil { 340 return err 341 } 342 } 343 344 if n.driver.config.EnableIPTables { 345 return setINC(iptables.IPv4, thisConfig.BridgeName, enable) 346 } 347 return nil 348 } 349 350 func (d *driver) configure(option map[string]interface{}) error { 351 var ( 352 config *configuration 353 err error 354 natChain *iptables.ChainInfo 355 filterChain *iptables.ChainInfo 356 isolationChain1 *iptables.ChainInfo 357 isolationChain2 *iptables.ChainInfo 358 natChainV6 *iptables.ChainInfo 359 filterChainV6 *iptables.ChainInfo 360 isolationChain1V6 *iptables.ChainInfo 361 isolationChain2V6 *iptables.ChainInfo 362 ) 363 364 genericData, ok := option[netlabel.GenericData] 365 if !ok || genericData == nil { 366 return nil 367 } 368 369 switch opt := genericData.(type) { 370 case options.Generic: 371 opaqueConfig, err := options.GenerateFromModel(opt, &configuration{}) 372 if err != nil { 373 return err 374 } 375 config = opaqueConfig.(*configuration) 376 case *configuration: 377 config = opt 378 default: 379 return &ErrInvalidDriverConfig{} 380 } 381 382 if config.EnableIPTables || config.EnableIP6Tables { 383 if _, err := os.Stat("/proc/sys/net/bridge"); err != nil { 384 if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil { 385 logrus.Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err) 386 } 387 } 388 } 389 390 if config.EnableIPTables { 391 removeIPChains(iptables.IPv4) 392 393 natChain, filterChain, isolationChain1, isolationChain2, err = setupIPChains(config, iptables.IPv4) 394 if err != nil { 395 return err 396 } 397 398 // Make sure on firewall reload, first thing being re-played is chains creation 399 iptables.OnReloaded(func() { 400 logrus.Debugf("Recreating iptables chains on firewall reload") 401 if _, _, _, _, err := setupIPChains(config, iptables.IPv4); err != nil { 402 logrus.WithError(err).Error("Error reloading iptables chains") 403 } 404 }) 405 } 406 407 if config.EnableIP6Tables { 408 removeIPChains(iptables.IPv6) 409 410 natChainV6, filterChainV6, isolationChain1V6, isolationChain2V6, err = setupIPChains(config, iptables.IPv6) 411 if err != nil { 412 return err 413 } 414 415 // Make sure on firewall reload, first thing being re-played is chains creation 416 iptables.OnReloaded(func() { 417 logrus.Debugf("Recreating ip6tables chains on firewall reload") 418 if _, _, _, _, err := setupIPChains(config, iptables.IPv6); err != nil { 419 logrus.WithError(err).Error("Error reloading ip6tables chains") 420 } 421 }) 422 } 423 424 if config.EnableIPForwarding { 425 err = setupIPForwarding(config.EnableIPTables, config.EnableIP6Tables) 426 if err != nil { 427 logrus.Warn(err) 428 return err 429 } 430 } 431 432 d.Lock() 433 d.natChain = natChain 434 d.filterChain = filterChain 435 d.isolationChain1 = isolationChain1 436 d.isolationChain2 = isolationChain2 437 d.natChainV6 = natChainV6 438 d.filterChainV6 = filterChainV6 439 d.isolationChain1V6 = isolationChain1V6 440 d.isolationChain2V6 = isolationChain2V6 441 d.config = config 442 d.Unlock() 443 444 err = d.initStore(option) 445 if err != nil { 446 return err 447 } 448 449 return nil 450 } 451 452 func (d *driver) getNetwork(id string) (*bridgeNetwork, error) { 453 d.Lock() 454 defer d.Unlock() 455 456 if id == "" { 457 return nil, types.BadRequestErrorf("invalid network id: %s", id) 458 } 459 460 if nw, ok := d.networks[id]; ok { 461 return nw, nil 462 } 463 464 return nil, types.NotFoundErrorf("network not found: %s", id) 465 } 466 467 func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error) { 468 var ( 469 err error 470 config *networkConfiguration 471 ) 472 473 switch opt := data.(type) { 474 case *networkConfiguration: 475 config = opt 476 case map[string]string: 477 config = &networkConfiguration{ 478 EnableICC: true, 479 EnableIPMasquerade: true, 480 } 481 err = config.fromLabels(opt) 482 case options.Generic: 483 var opaqueConfig interface{} 484 if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil { 485 config = opaqueConfig.(*networkConfiguration) 486 } 487 default: 488 err = types.BadRequestErrorf("do not recognize network configuration format: %T", opt) 489 } 490 491 return config, err 492 } 493 494 func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error { 495 if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 { 496 return types.ForbiddenErrorf("bridge driver doesn't support multiple subnets") 497 } 498 499 if len(ipamV4Data) == 0 { 500 return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id) 501 } 502 503 if ipamV4Data[0].Gateway != nil { 504 c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway) 505 } 506 507 if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok { 508 c.DefaultGatewayIPv4 = gw.IP 509 } 510 511 if len(ipamV6Data) > 0 { 512 c.AddressIPv6 = ipamV6Data[0].Pool 513 514 if ipamV6Data[0].Gateway != nil { 515 c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway) 516 } 517 518 if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok { 519 c.DefaultGatewayIPv6 = gw.IP 520 } 521 } 522 523 return nil 524 } 525 526 func parseNetworkOptions(id string, option options.Generic) (*networkConfiguration, error) { 527 var ( 528 err error 529 config = &networkConfiguration{} 530 ) 531 532 // Parse generic label first, config will be re-assigned 533 if genData, ok := option[netlabel.GenericData]; ok && genData != nil { 534 if config, err = parseNetworkGenericOptions(genData); err != nil { 535 return nil, err 536 } 537 } 538 539 // Process well-known labels next 540 if val, ok := option[netlabel.EnableIPv6]; ok { 541 config.EnableIPv6 = val.(bool) 542 } 543 544 if val, ok := option[netlabel.Internal]; ok { 545 if internal, ok := val.(bool); ok && internal { 546 config.Internal = true 547 } 548 } 549 550 // Finally validate the configuration 551 if err = config.Validate(); err != nil { 552 return nil, err 553 } 554 555 if config.BridgeName == "" && !config.DefaultBridge { 556 config.BridgeName = "br-" + id[:12] 557 } 558 559 exists, err := bridgeInterfaceExists(config.BridgeName) 560 if err != nil { 561 return nil, err 562 } 563 564 if !exists { 565 config.BridgeIfaceCreator = ifaceCreatedByLibnetwork 566 } else { 567 config.BridgeIfaceCreator = ifaceCreatedByUser 568 } 569 570 config.ID = id 571 return config, nil 572 } 573 574 // Return a slice of networks over which caller can iterate safely 575 func (d *driver) getNetworks() []*bridgeNetwork { 576 d.Lock() 577 defer d.Unlock() 578 579 ls := make([]*bridgeNetwork, 0, len(d.networks)) 580 for _, nw := range d.networks { 581 ls = append(ls, nw) 582 } 583 return ls 584 } 585 586 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 587 return nil, types.NotImplementedErrorf("not implemented") 588 } 589 590 func (d *driver) NetworkFree(id string) error { 591 return types.NotImplementedErrorf("not implemented") 592 } 593 594 func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { 595 } 596 597 func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) { 598 return "", nil 599 } 600 601 // Create a new network using bridge plugin 602 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 603 if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { 604 return types.BadRequestErrorf("ipv4 pool is empty") 605 } 606 // Sanity checks 607 d.Lock() 608 if _, ok := d.networks[id]; ok { 609 d.Unlock() 610 return types.ForbiddenErrorf("network %s exists", id) 611 } 612 d.Unlock() 613 614 // Parse and validate the config. It should not be conflict with existing networks' config 615 config, err := parseNetworkOptions(id, option) 616 if err != nil { 617 return err 618 } 619 620 if err = config.processIPAM(id, ipV4Data, ipV6Data); err != nil { 621 return err 622 } 623 624 // start the critical section, from this point onward we are dealing with the list of networks 625 // so to be consistent we cannot allow that the list changes 626 d.configNetwork.Lock() 627 defer d.configNetwork.Unlock() 628 629 // check network conflicts 630 if err = d.checkConflict(config); err != nil { 631 nerr, ok := err.(defaultBridgeNetworkConflict) 632 if !ok { 633 return err 634 } 635 // Got a conflict with a stale default network, clean that up and continue 636 logrus.Warn(nerr) 637 if err := d.deleteNetwork(nerr.ID); err != nil { 638 logrus.WithError(err).Debug("Error while cleaning up network on conflict") 639 } 640 } 641 642 // there is no conflict, now create the network 643 if err = d.createNetwork(config); err != nil { 644 return err 645 } 646 647 return d.storeUpdate(config) 648 } 649 650 func (d *driver) checkConflict(config *networkConfiguration) error { 651 networkList := d.getNetworks() 652 for _, nw := range networkList { 653 nw.Lock() 654 nwConfig := nw.config 655 nw.Unlock() 656 if err := nwConfig.Conflicts(config); err != nil { 657 if nwConfig.DefaultBridge { 658 // We encountered and identified a stale default network 659 // We must delete it as libnetwork is the source of truth 660 // The default network being created must be the only one 661 // This can happen only from docker 1.12 on ward 662 logrus.Infof("Found stale default bridge network %s (%s)", nwConfig.ID, nwConfig.BridgeName) 663 return defaultBridgeNetworkConflict{nwConfig.ID} 664 } 665 666 return types.ForbiddenErrorf("cannot create network %s (%s): conflicts with network %s (%s): %s", 667 config.ID, config.BridgeName, nwConfig.ID, nwConfig.BridgeName, err.Error()) 668 } 669 } 670 return nil 671 } 672 673 func (d *driver) createNetwork(config *networkConfiguration) (err error) { 674 defer osl.InitOSContext()() 675 676 // Initialize handle when needed 677 d.Lock() 678 if d.nlh == nil { 679 d.nlh = ns.NlHandle() 680 } 681 d.Unlock() 682 683 // Create or retrieve the bridge L3 interface 684 bridgeIface, err := newInterface(d.nlh, config) 685 if err != nil { 686 return err 687 } 688 689 // Create and set network handler in driver 690 network := &bridgeNetwork{ 691 id: config.ID, 692 endpoints: make(map[string]*bridgeEndpoint), 693 config: config, 694 portMapper: portmapper.New(d.config.UserlandProxyPath), 695 portMapperV6: portmapper.New(d.config.UserlandProxyPath), 696 bridge: bridgeIface, 697 driver: d, 698 } 699 700 d.Lock() 701 d.networks[config.ID] = network 702 d.Unlock() 703 704 // On failure make sure to reset driver network handler to nil 705 defer func() { 706 if err != nil { 707 d.Lock() 708 delete(d.networks, config.ID) 709 d.Unlock() 710 } 711 }() 712 713 // Add inter-network communication rules. 714 setupNetworkIsolationRules := func(config *networkConfiguration, i *bridgeInterface) error { 715 if err := network.isolateNetwork(true); err != nil { 716 if err = network.isolateNetwork(false); err != nil { 717 logrus.Warnf("Failed on removing the inter-network iptables rules on cleanup: %v", err) 718 } 719 return err 720 } 721 // register the cleanup function 722 network.registerIptCleanFunc(func() error { 723 return network.isolateNetwork(false) 724 }) 725 return nil 726 } 727 728 // Prepare the bridge setup configuration 729 bridgeSetup := newBridgeSetup(config, bridgeIface) 730 731 // If the bridge interface doesn't exist, we need to start the setup steps 732 // by creating a new device and assigning it an IPv4 address. 733 bridgeAlreadyExists := bridgeIface.exists() 734 if !bridgeAlreadyExists { 735 bridgeSetup.queueStep(setupDevice) 736 bridgeSetup.queueStep(setupDefaultSysctl) 737 } 738 739 // For the default bridge, set expected sysctls 740 if config.DefaultBridge { 741 bridgeSetup.queueStep(setupDefaultSysctl) 742 } 743 744 // Even if a bridge exists try to setup IPv4. 745 bridgeSetup.queueStep(setupBridgeIPv4) 746 747 enableIPv6Forwarding := d.config.EnableIPForwarding && config.AddressIPv6 != nil 748 749 // Conditionally queue setup steps depending on configuration values. 750 for _, step := range []struct { 751 Condition bool 752 Fn setupStep 753 }{ 754 // Enable IPv6 on the bridge if required. We do this even for a 755 // previously existing bridge, as it may be here from a previous 756 // installation where IPv6 wasn't supported yet and needs to be 757 // assigned an IPv6 link-local address. 758 {config.EnableIPv6, setupBridgeIPv6}, 759 760 // We ensure that the bridge has the expectedIPv4 and IPv6 addresses in 761 // the case of a previously existing device. 762 {bridgeAlreadyExists && !config.InhibitIPv4, setupVerifyAndReconcile}, 763 764 // Enable IPv6 Forwarding 765 {enableIPv6Forwarding, setupIPv6Forwarding}, 766 767 // Setup Loopback Addresses Routing 768 {!d.config.EnableUserlandProxy, setupLoopbackAddressesRouting}, 769 770 // Setup IPTables. 771 {d.config.EnableIPTables, network.setupIP4Tables}, 772 773 // Setup IP6Tables. 774 {config.EnableIPv6 && d.config.EnableIP6Tables, network.setupIP6Tables}, 775 776 // We want to track firewalld configuration so that 777 // if it is started/reloaded, the rules can be applied correctly 778 {d.config.EnableIPTables, network.setupFirewalld}, 779 // same for IPv6 780 {config.EnableIPv6 && d.config.EnableIP6Tables, network.setupFirewalld6}, 781 782 // Setup DefaultGatewayIPv4 783 {config.DefaultGatewayIPv4 != nil, setupGatewayIPv4}, 784 785 // Setup DefaultGatewayIPv6 786 {config.DefaultGatewayIPv6 != nil, setupGatewayIPv6}, 787 788 // Add inter-network communication rules. 789 {d.config.EnableIPTables, setupNetworkIsolationRules}, 790 791 // Configure bridge networking filtering if ICC is off and IP tables are enabled 792 {!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering}, 793 } { 794 if step.Condition { 795 bridgeSetup.queueStep(step.Fn) 796 } 797 } 798 799 // Apply the prepared list of steps, and abort at the first error. 800 bridgeSetup.queueStep(setupDeviceUp) 801 return bridgeSetup.apply() 802 } 803 804 func (d *driver) DeleteNetwork(nid string) error { 805 d.configNetwork.Lock() 806 defer d.configNetwork.Unlock() 807 808 return d.deleteNetwork(nid) 809 } 810 811 func (d *driver) deleteNetwork(nid string) error { 812 var err error 813 814 defer osl.InitOSContext()() 815 // Get network handler and remove it from driver 816 d.Lock() 817 n, ok := d.networks[nid] 818 d.Unlock() 819 820 if !ok { 821 return types.InternalMaskableErrorf("network %s does not exist", nid) 822 } 823 824 n.Lock() 825 config := n.config 826 n.Unlock() 827 828 // delele endpoints belong to this network 829 for _, ep := range n.endpoints { 830 if err := n.releasePorts(ep); err != nil { 831 logrus.Warn(err) 832 } 833 if link, err := d.nlh.LinkByName(ep.srcName); err == nil { 834 if err := d.nlh.LinkDel(link); err != nil { 835 logrus.WithError(err).Errorf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id) 836 } 837 } 838 839 if err := d.storeDelete(ep); err != nil { 840 logrus.Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err) 841 } 842 } 843 844 d.Lock() 845 delete(d.networks, nid) 846 d.Unlock() 847 848 // On failure set network handler back in driver, but 849 // only if is not already taken over by some other thread 850 defer func() { 851 if err != nil { 852 d.Lock() 853 if _, ok := d.networks[nid]; !ok { 854 d.networks[nid] = n 855 } 856 d.Unlock() 857 } 858 }() 859 860 switch config.BridgeIfaceCreator { 861 case ifaceCreatedByLibnetwork, ifaceCreatorUnknown: 862 // We only delete the bridge if it was created by the bridge driver and 863 // it is not the default one (to keep the backward compatible behavior.) 864 if !config.DefaultBridge { 865 if err := d.nlh.LinkDel(n.bridge.Link); err != nil { 866 logrus.Warnf("Failed to remove bridge interface %s on network %s delete: %v", config.BridgeName, nid, err) 867 } 868 } 869 case ifaceCreatedByUser: 870 // Don't delete the bridge interface if it was not created by libnetwork. 871 } 872 873 // clean all relevant iptables rules 874 for _, cleanFunc := range n.iptCleanFuncs { 875 if errClean := cleanFunc(); errClean != nil { 876 logrus.Warnf("Failed to clean iptables rules for bridge network: %v", errClean) 877 } 878 } 879 return d.storeDelete(config) 880 } 881 882 func addToBridge(nlh *netlink.Handle, ifaceName, bridgeName string) error { 883 link, err := nlh.LinkByName(ifaceName) 884 if err != nil { 885 return fmt.Errorf("could not find interface %s: %v", ifaceName, err) 886 } 887 if err = nlh.LinkSetMaster(link, 888 &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}}); err != nil { 889 logrus.Debugf("Failed to add %s to bridge via netlink.Trying ioctl: %v", ifaceName, err) 890 iface, err := net.InterfaceByName(ifaceName) 891 if err != nil { 892 return fmt.Errorf("could not find network interface %s: %v", ifaceName, err) 893 } 894 895 master, err := net.InterfaceByName(bridgeName) 896 if err != nil { 897 return fmt.Errorf("could not find bridge %s: %v", bridgeName, err) 898 } 899 900 return ioctlAddToBridge(iface, master) 901 } 902 return nil 903 } 904 905 func setHairpinMode(nlh *netlink.Handle, link netlink.Link, enable bool) error { 906 err := nlh.LinkSetHairpin(link, enable) 907 if err != nil && err != syscall.EINVAL { 908 // If error is not EINVAL something else went wrong, bail out right away 909 return fmt.Errorf("unable to set hairpin mode on %s via netlink: %v", 910 link.Attrs().Name, err) 911 } 912 913 // Hairpin mode successfully set up 914 if err == nil { 915 return nil 916 } 917 918 // The netlink method failed with EINVAL which is probably because of an older 919 // kernel. Try one more time via the sysfs method. 920 path := filepath.Join("/sys/class/net", link.Attrs().Name, "brport/hairpin_mode") 921 922 var val []byte 923 if enable { 924 val = []byte{'1', '\n'} 925 } else { 926 val = []byte{'0', '\n'} 927 } 928 929 if err := os.WriteFile(path, val, 0644); err != nil { 930 return fmt.Errorf("unable to set hairpin mode on %s via sysfs: %v", link.Attrs().Name, err) 931 } 932 933 return nil 934 } 935 936 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { 937 defer osl.InitOSContext()() 938 939 if ifInfo == nil { 940 return errors.New("invalid interface info passed") 941 } 942 943 // Get the network handler and make sure it exists 944 d.Lock() 945 n, ok := d.networks[nid] 946 dconfig := d.config 947 d.Unlock() 948 949 if !ok { 950 return types.NotFoundErrorf("network %s does not exist", nid) 951 } 952 if n == nil { 953 return driverapi.ErrNoNetwork(nid) 954 } 955 956 // Sanity check 957 n.Lock() 958 if n.id != nid { 959 n.Unlock() 960 return InvalidNetworkIDError(nid) 961 } 962 n.Unlock() 963 964 // Check if endpoint id is good and retrieve correspondent endpoint 965 ep, err := n.getEndpoint(eid) 966 if err != nil { 967 return err 968 } 969 970 // Endpoint with that id exists either on desired or other sandbox 971 if ep != nil { 972 return driverapi.ErrEndpointExists(eid) 973 } 974 975 // Try to convert the options to endpoint configuration 976 epConfig, err := parseEndpointOptions(epOptions) 977 if err != nil { 978 return err 979 } 980 981 // Create and add the endpoint 982 n.Lock() 983 endpoint := &bridgeEndpoint{id: eid, nid: nid, config: epConfig} 984 n.endpoints[eid] = endpoint 985 n.Unlock() 986 987 // On failure make sure to remove the endpoint 988 defer func() { 989 if err != nil { 990 n.Lock() 991 delete(n.endpoints, eid) 992 n.Unlock() 993 } 994 }() 995 996 // Generate a name for what will be the host side pipe interface 997 hostIfName, err := netutils.GenerateIfaceName(d.nlh, vethPrefix, vethLen) 998 if err != nil { 999 return err 1000 } 1001 1002 // Generate a name for what will be the sandbox side pipe interface 1003 containerIfName, err := netutils.GenerateIfaceName(d.nlh, vethPrefix, vethLen) 1004 if err != nil { 1005 return err 1006 } 1007 1008 // Generate and add the interface pipe host <-> sandbox 1009 veth := &netlink.Veth{ 1010 LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, 1011 PeerName: containerIfName} 1012 if err = d.nlh.LinkAdd(veth); err != nil { 1013 return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) 1014 } 1015 1016 // Get the host side pipe interface handler 1017 host, err := d.nlh.LinkByName(hostIfName) 1018 if err != nil { 1019 return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) 1020 } 1021 defer func() { 1022 if err != nil { 1023 if err := d.nlh.LinkDel(host); err != nil { 1024 logrus.WithError(err).Warnf("Failed to delete host side interface (%s)'s link", hostIfName) 1025 } 1026 } 1027 }() 1028 1029 // Get the sandbox side pipe interface handler 1030 sbox, err := d.nlh.LinkByName(containerIfName) 1031 if err != nil { 1032 return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) 1033 } 1034 defer func() { 1035 if err != nil { 1036 if err := d.nlh.LinkDel(sbox); err != nil { 1037 logrus.WithError(err).Warnf("Failed to delete sandbox side interface (%s)'s link", containerIfName) 1038 } 1039 } 1040 }() 1041 1042 n.Lock() 1043 config := n.config 1044 n.Unlock() 1045 1046 // Add bridge inherited attributes to pipe interfaces 1047 if config.Mtu != 0 { 1048 err = d.nlh.LinkSetMTU(host, config.Mtu) 1049 if err != nil { 1050 return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) 1051 } 1052 err = d.nlh.LinkSetMTU(sbox, config.Mtu) 1053 if err != nil { 1054 return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) 1055 } 1056 } 1057 1058 // Attach host side pipe interface into the bridge 1059 if err = addToBridge(d.nlh, hostIfName, config.BridgeName); err != nil { 1060 return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) 1061 } 1062 1063 if !dconfig.EnableUserlandProxy { 1064 err = setHairpinMode(d.nlh, host, true) 1065 if err != nil { 1066 return err 1067 } 1068 } 1069 1070 // Store the sandbox side pipe interface parameters 1071 endpoint.srcName = containerIfName 1072 endpoint.macAddress = ifInfo.MacAddress() 1073 endpoint.addr = ifInfo.Address() 1074 endpoint.addrv6 = ifInfo.AddressIPv6() 1075 1076 // Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP. 1077 if endpoint.macAddress == nil { 1078 endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) 1079 if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil { 1080 return err 1081 } 1082 } 1083 1084 // Up the host interface after finishing all netlink configuration 1085 if err = d.nlh.LinkSetUp(host); err != nil { 1086 return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) 1087 } 1088 1089 if endpoint.addrv6 == nil && config.EnableIPv6 { 1090 var ip6 net.IP 1091 network := n.bridge.bridgeIPv6 1092 if config.AddressIPv6 != nil { 1093 network = config.AddressIPv6 1094 } 1095 1096 ones, _ := network.Mask.Size() 1097 if ones > 80 { 1098 err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) 1099 return err 1100 } 1101 1102 ip6 = make(net.IP, len(network.IP)) 1103 copy(ip6, network.IP) 1104 for i, h := range endpoint.macAddress { 1105 ip6[i+10] = h 1106 } 1107 1108 endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} 1109 if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil { 1110 return err 1111 } 1112 } 1113 1114 if err = d.storeUpdate(endpoint); err != nil { 1115 return fmt.Errorf("failed to save bridge endpoint %.7s to store: %v", endpoint.id, err) 1116 } 1117 1118 return nil 1119 } 1120 1121 func (d *driver) DeleteEndpoint(nid, eid string) error { 1122 var err error 1123 1124 defer osl.InitOSContext()() 1125 1126 // Get the network handler and make sure it exists 1127 d.Lock() 1128 n, ok := d.networks[nid] 1129 d.Unlock() 1130 1131 if !ok { 1132 return types.InternalMaskableErrorf("network %s does not exist", nid) 1133 } 1134 if n == nil { 1135 return driverapi.ErrNoNetwork(nid) 1136 } 1137 1138 // Sanity Check 1139 n.Lock() 1140 if n.id != nid { 1141 n.Unlock() 1142 return InvalidNetworkIDError(nid) 1143 } 1144 n.Unlock() 1145 1146 // Check endpoint id and if an endpoint is actually there 1147 ep, err := n.getEndpoint(eid) 1148 if err != nil { 1149 return err 1150 } 1151 if ep == nil { 1152 return EndpointNotFoundError(eid) 1153 } 1154 1155 // Remove it 1156 n.Lock() 1157 delete(n.endpoints, eid) 1158 n.Unlock() 1159 1160 // On failure make sure to set back ep in n.endpoints, but only 1161 // if it hasn't been taken over already by some other thread. 1162 defer func() { 1163 if err != nil { 1164 n.Lock() 1165 if _, ok := n.endpoints[eid]; !ok { 1166 n.endpoints[eid] = ep 1167 } 1168 n.Unlock() 1169 } 1170 }() 1171 1172 // Try removal of link. Discard error: it is a best effort. 1173 // Also make sure defer does not see this error either. 1174 if link, err := d.nlh.LinkByName(ep.srcName); err == nil { 1175 if err := d.nlh.LinkDel(link); err != nil { 1176 logrus.WithError(err).Errorf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id) 1177 } 1178 } 1179 1180 if err := d.storeDelete(ep); err != nil { 1181 logrus.Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err) 1182 } 1183 1184 return nil 1185 } 1186 1187 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { 1188 // Get the network handler and make sure it exists 1189 d.Lock() 1190 n, ok := d.networks[nid] 1191 d.Unlock() 1192 if !ok { 1193 return nil, types.NotFoundErrorf("network %s does not exist", nid) 1194 } 1195 if n == nil { 1196 return nil, driverapi.ErrNoNetwork(nid) 1197 } 1198 1199 // Sanity check 1200 n.Lock() 1201 if n.id != nid { 1202 n.Unlock() 1203 return nil, InvalidNetworkIDError(nid) 1204 } 1205 n.Unlock() 1206 1207 // Check if endpoint id is good and retrieve correspondent endpoint 1208 ep, err := n.getEndpoint(eid) 1209 if err != nil { 1210 return nil, err 1211 } 1212 if ep == nil { 1213 return nil, driverapi.ErrNoEndpoint(eid) 1214 } 1215 1216 m := make(map[string]interface{}) 1217 1218 if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil { 1219 // Return a copy of the config data 1220 epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts)) 1221 for _, tp := range ep.extConnConfig.ExposedPorts { 1222 epc = append(epc, tp.GetCopy()) 1223 } 1224 m[netlabel.ExposedPorts] = epc 1225 } 1226 1227 if ep.portMapping != nil { 1228 // Return a copy of the operational data 1229 pmc := make([]types.PortBinding, 0, len(ep.portMapping)) 1230 for _, pm := range ep.portMapping { 1231 pmc = append(pmc, pm.GetCopy()) 1232 } 1233 m[netlabel.PortMap] = pmc 1234 } 1235 1236 if len(ep.macAddress) != 0 { 1237 m[netlabel.MacAddress] = ep.macAddress 1238 } 1239 1240 return m, nil 1241 } 1242 1243 // Join method is invoked when a Sandbox is attached to an endpoint. 1244 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 1245 defer osl.InitOSContext()() 1246 1247 network, err := d.getNetwork(nid) 1248 if err != nil { 1249 return err 1250 } 1251 1252 endpoint, err := network.getEndpoint(eid) 1253 if err != nil { 1254 return err 1255 } 1256 1257 if endpoint == nil { 1258 return EndpointNotFoundError(eid) 1259 } 1260 1261 endpoint.containerConfig, err = parseContainerOptions(options) 1262 if err != nil { 1263 return err 1264 } 1265 1266 iNames := jinfo.InterfaceName() 1267 containerVethPrefix := defaultContainerVethPrefix 1268 if network.config.ContainerIfacePrefix != "" { 1269 containerVethPrefix = network.config.ContainerIfacePrefix 1270 } 1271 err = iNames.SetNames(endpoint.srcName, containerVethPrefix) 1272 if err != nil { 1273 return err 1274 } 1275 1276 err = jinfo.SetGateway(network.bridge.gatewayIPv4) 1277 if err != nil { 1278 return err 1279 } 1280 1281 err = jinfo.SetGatewayIPv6(network.bridge.gatewayIPv6) 1282 if err != nil { 1283 return err 1284 } 1285 1286 return nil 1287 } 1288 1289 // Leave method is invoked when a Sandbox detaches from an endpoint. 1290 func (d *driver) Leave(nid, eid string) error { 1291 defer osl.InitOSContext()() 1292 1293 network, err := d.getNetwork(nid) 1294 if err != nil { 1295 return types.InternalMaskableErrorf("%s", err) 1296 } 1297 1298 endpoint, err := network.getEndpoint(eid) 1299 if err != nil { 1300 return err 1301 } 1302 1303 if endpoint == nil { 1304 return EndpointNotFoundError(eid) 1305 } 1306 1307 if !network.config.EnableICC { 1308 if err = d.link(network, endpoint, false); err != nil { 1309 return err 1310 } 1311 } 1312 1313 return nil 1314 } 1315 1316 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 1317 defer osl.InitOSContext()() 1318 1319 network, err := d.getNetwork(nid) 1320 if err != nil { 1321 return err 1322 } 1323 1324 endpoint, err := network.getEndpoint(eid) 1325 if err != nil { 1326 return err 1327 } 1328 1329 if endpoint == nil { 1330 return EndpointNotFoundError(eid) 1331 } 1332 1333 endpoint.extConnConfig, err = parseConnectivityOptions(options) 1334 if err != nil { 1335 return err 1336 } 1337 1338 // Program any required port mapping and store them in the endpoint 1339 endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIP, d.config.EnableUserlandProxy) 1340 if err != nil { 1341 return err 1342 } 1343 1344 defer func() { 1345 if err != nil { 1346 if e := network.releasePorts(endpoint); e != nil { 1347 logrus.Errorf("Failed to release ports allocated for the bridge endpoint %s on failure %v because of %v", 1348 eid, err, e) 1349 } 1350 endpoint.portMapping = nil 1351 } 1352 }() 1353 1354 // Clean the connection tracker state of the host for the specific endpoint. This is needed because some flows may 1355 // be bound to the local proxy, or to the host (for UDP packets), and won't be redirected to the new endpoints. 1356 clearConntrackEntries(d.nlh, endpoint) 1357 1358 if err = d.storeUpdate(endpoint); err != nil { 1359 return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) 1360 } 1361 1362 if !network.config.EnableICC { 1363 return d.link(network, endpoint, true) 1364 } 1365 1366 return nil 1367 } 1368 1369 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 1370 defer osl.InitOSContext()() 1371 1372 network, err := d.getNetwork(nid) 1373 if err != nil { 1374 return err 1375 } 1376 1377 endpoint, err := network.getEndpoint(eid) 1378 if err != nil { 1379 return err 1380 } 1381 1382 if endpoint == nil { 1383 return EndpointNotFoundError(eid) 1384 } 1385 1386 err = network.releasePorts(endpoint) 1387 if err != nil { 1388 logrus.Warn(err) 1389 } 1390 1391 endpoint.portMapping = nil 1392 1393 // Clean the connection tracker state of the host for the specific endpoint. This is a precautionary measure to 1394 // avoid new endpoints getting the same IP address to receive unexpected packets due to bad conntrack state leading 1395 // to bad NATing. 1396 clearConntrackEntries(d.nlh, endpoint) 1397 1398 if err = d.storeUpdate(endpoint); err != nil { 1399 return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) 1400 } 1401 1402 return nil 1403 } 1404 1405 func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error { 1406 var err error 1407 1408 cc := endpoint.containerConfig 1409 if cc == nil { 1410 return nil 1411 } 1412 ec := endpoint.extConnConfig 1413 if ec == nil { 1414 return nil 1415 } 1416 1417 if ec.ExposedPorts != nil { 1418 for _, p := range cc.ParentEndpoints { 1419 var parentEndpoint *bridgeEndpoint 1420 parentEndpoint, err = network.getEndpoint(p) 1421 if err != nil { 1422 return err 1423 } 1424 if parentEndpoint == nil { 1425 err = InvalidEndpointIDError(p) 1426 return err 1427 } 1428 1429 l := newLink(parentEndpoint.addr.IP.String(), 1430 endpoint.addr.IP.String(), 1431 ec.ExposedPorts, network.config.BridgeName) 1432 if enable { 1433 err = l.Enable() 1434 if err != nil { 1435 return err 1436 } 1437 defer func() { 1438 if err != nil { 1439 l.Disable() 1440 } 1441 }() 1442 } else { 1443 l.Disable() 1444 } 1445 } 1446 } 1447 1448 for _, c := range cc.ChildEndpoints { 1449 var childEndpoint *bridgeEndpoint 1450 childEndpoint, err = network.getEndpoint(c) 1451 if err != nil { 1452 return err 1453 } 1454 if childEndpoint == nil { 1455 err = InvalidEndpointIDError(c) 1456 return err 1457 } 1458 if childEndpoint.extConnConfig == nil || childEndpoint.extConnConfig.ExposedPorts == nil { 1459 continue 1460 } 1461 1462 l := newLink(endpoint.addr.IP.String(), 1463 childEndpoint.addr.IP.String(), 1464 childEndpoint.extConnConfig.ExposedPorts, network.config.BridgeName) 1465 if enable { 1466 err = l.Enable() 1467 if err != nil { 1468 return err 1469 } 1470 defer func() { 1471 if err != nil { 1472 l.Disable() 1473 } 1474 }() 1475 } else { 1476 l.Disable() 1477 } 1478 } 1479 1480 return nil 1481 } 1482 1483 func (d *driver) Type() string { 1484 return networkType 1485 } 1486 1487 func (d *driver) IsBuiltIn() bool { 1488 return true 1489 } 1490 1491 // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster 1492 func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { 1493 return nil 1494 } 1495 1496 // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster 1497 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { 1498 return nil 1499 } 1500 1501 func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) { 1502 if epOptions == nil { 1503 return nil, nil 1504 } 1505 1506 ec := &endpointConfiguration{} 1507 1508 if opt, ok := epOptions[netlabel.MacAddress]; ok { 1509 if mac, ok := opt.(net.HardwareAddr); ok { 1510 ec.MacAddress = mac 1511 } else { 1512 return nil, &ErrInvalidEndpointConfig{} 1513 } 1514 } 1515 1516 return ec, nil 1517 } 1518 1519 func parseContainerOptions(cOptions map[string]interface{}) (*containerConfiguration, error) { 1520 if cOptions == nil { 1521 return nil, nil 1522 } 1523 genericData := cOptions[netlabel.GenericData] 1524 if genericData == nil { 1525 return nil, nil 1526 } 1527 switch opt := genericData.(type) { 1528 case options.Generic: 1529 opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{}) 1530 if err != nil { 1531 return nil, err 1532 } 1533 return opaqueConfig.(*containerConfiguration), nil 1534 case *containerConfiguration: 1535 return opt, nil 1536 default: 1537 return nil, nil 1538 } 1539 } 1540 1541 func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) { 1542 if cOptions == nil { 1543 return nil, nil 1544 } 1545 1546 cc := &connectivityConfiguration{} 1547 1548 if opt, ok := cOptions[netlabel.PortMap]; ok { 1549 if pb, ok := opt.([]types.PortBinding); ok { 1550 cc.PortBindings = pb 1551 } else { 1552 return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt) 1553 } 1554 } 1555 1556 if opt, ok := cOptions[netlabel.ExposedPorts]; ok { 1557 if ports, ok := opt.([]types.TransportPort); ok { 1558 cc.ExposedPorts = ports 1559 } else { 1560 return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt) 1561 } 1562 } 1563 1564 return cc, nil 1565 } 1566 1567 func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr { 1568 if epConfig != nil && epConfig.MacAddress != nil { 1569 return epConfig.MacAddress 1570 } 1571 return netutils.GenerateMACFromIP(ip) 1572 }