func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { n, err := d.getNetwork(nid) if err != nil { return err } // Check if endpoint id is good and retrieve corresponding endpoint ep, err := n.getEndpoint(eid) if err == nil && ep != nil { return driverapi.ErrEndpointExists(eid) } endpointStruct := &hcsshim.HNSEndpoint{ VirtualNetwork: n.config.HnsID, } // Convert the port mapping for the network if opt, ok := epOptions[netlabel.PortMap]; ok { if bs, ok := opt.([]types.PortBinding); ok { endpointStruct.Policies, err = convertPortBindings(bs) if err != nil { return err } } else { return fmt.Errorf("Invalid endpoint configuration for endpoint id%s", eid) } } configurationb, err := json.Marshal(endpointStruct) if err != nil { return err } hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb)) if err != nil { return err } mac, err := net.ParseMAC(hnsresponse.MacAddress) if err != nil { return err } // TODO For now the ip mask is not in the info generated by HNS endpoint := &hnsEndpoint{ id: eid, addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()}, macAddress: mac, } endpoint.profileID = hnsresponse.Id n.Lock() n.endpoints[eid] = endpoint n.Unlock() ifInfo.SetIPAddress(endpoint.addr) ifInfo.SetMacAddress(endpoint.macAddress) return nil }
// CreateEndpoint assigns the mac, ip and endpoint id for the new container func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if err := validateID(nid, eid); err != nil { return err } n, err := d.getNetwork(nid) if err != nil { return fmt.Errorf("network id %q not found", nid) } ep := &endpoint{ id: eid, nid: nid, addr: ifInfo.Address(), addrv6: ifInfo.AddressIPv6(), mac: ifInfo.MacAddress(), } if ep.addr == nil { return fmt.Errorf("create endpoint was not passed an IP address") } if ep.mac == nil { ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) if err := ifInfo.SetMacAddress(ep.mac); err != nil { return err } } // disallow portmapping -p if opt, ok := epOptions[netlabel.PortMap]; ok { if _, ok := opt.([]types.PortBinding); ok { if len(opt.([]types.PortBinding)) > 0 { logrus.Warnf("%s driver does not support port mappings", macvlanType) } } } // disallow port exposure --expose if opt, ok := epOptions[netlabel.ExposedPorts]; ok { if _, ok := opt.([]types.TransportPort); ok { if len(opt.([]types.TransportPort)) > 0 { logrus.Warnf("%s driver does not support port exposures", macvlanType) } } } if err := d.storeUpdate(ep); err != nil { return fmt.Errorf("failed to save macvlan endpoint %s to store: %v", ep.id[0:7], err) } n.addEndpoint(ep) return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { if err := validateID(nid, eid); err != nil { return err } n := d.network(nid) if n == nil { return fmt.Errorf("network id %q not found", nid) } ep := &endpoint{ id: eid, addr: ifInfo.Address(), mac: ifInfo.MacAddress(), } if ep.addr == nil { return fmt.Errorf("create endpoint was not passed interface IP address") } if ep.mac == nil { ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) if err := ifInfo.SetMacAddress(ep.mac); err != nil { return err } } n.addEndpoint(ep) return nil }
// CreateEndpoint assigns the mac, ip and endpoint id for the new container func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if err := validateID(nid, eid); err != nil { return err } n, err := d.getNetwork(nid) if err != nil { return fmt.Errorf("network id %q not found", nid) } if ifInfo.MacAddress() != nil { return fmt.Errorf("%s interfaces do not support custom mac address assigment", ipvlanType) } ep := &endpoint{ id: eid, addr: ifInfo.Address(), addrv6: ifInfo.AddressIPv6(), mac: ifInfo.MacAddress(), } if ep.addr == nil { return fmt.Errorf("create endpoint was not passed an IP address") } // disallow port mapping -p if opt, ok := epOptions[netlabel.PortMap]; ok { if _, ok := opt.([]types.PortBinding); ok { if len(opt.([]types.PortBinding)) > 0 { logrus.Warnf("%s driver does not support port mappings", ipvlanType) } } } // disallow port exposure --expose if opt, ok := epOptions[netlabel.ExposedPorts]; ok { if _, ok := opt.([]types.TransportPort); ok { if len(opt.([]types.TransportPort)) > 0 { logrus.Warnf("%s driver does not support port exposures", ipvlanType) } } } n.addEndpoint(ep) return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { var err error if err = validateID(nid, eid); err != nil { return err } // Since we perform lazy configuration make sure we try // configuring the driver when we enter CreateEndpoint since // CreateNetwork may not be called in every node. if err := d.configure(); err != nil { return err } n := d.network(nid) if n == nil { return fmt.Errorf("network id %q not found", nid) } ep := &endpoint{ id: eid, nid: n.id, addr: ifInfo.Address(), mac: ifInfo.MacAddress(), } if ep.addr == nil { return fmt.Errorf("create endpoint was not passed interface IP address") } if s := n.getSubnetforIP(ep.addr); s == nil { return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid) } if ep.mac == nil { ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) if err := ifInfo.SetMacAddress(ep.mac); err != nil { return err } } n.addEndpoint(ep) if err := d.writeEndpointToStore(ep); err != nil { return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err) } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { if ifInfo == nil { return errors.New("must not be called with nil InterfaceInfo") } reqIface := &api.EndpointInterface{} if ifInfo.Address() != nil { reqIface.Address = ifInfo.Address().String() } if ifInfo.AddressIPv6() != nil { reqIface.AddressIPv6 = ifInfo.AddressIPv6().String() } if ifInfo.MacAddress() != nil { reqIface.MacAddress = ifInfo.MacAddress().String() } create := &api.CreateEndpointRequest{ NetworkID: nid, EndpointID: eid, Interface: reqIface, Options: epOptions, } var res api.CreateEndpointResponse if err := d.call("CreateEndpoint", create, &res); err != nil { return err } inIface, err := parseInterface(res) if err != nil { return err } if inIface == nil { // Remote driver did not set any field return nil } if inIface.MacAddress != nil { if err := ifInfo.SetMacAddress(inIface.MacAddress); err != nil { return errorWithRollback(fmt.Sprintf("driver modified interface MAC address: %v", err), d.DeleteEndpoint(nid, eid)) } } if inIface.Address != nil { if err := ifInfo.SetIPAddress(inIface.Address); err != nil { return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid)) } } if inIface.AddressIPv6 != nil { if err := ifInfo.SetIPAddress(inIface.AddressIPv6); err != nil { return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid)) } } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // Store the sandbox side pipe interface parameters endpoint.srcName = containerIfName endpoint.macAddress = ifInfo.MacAddress() endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() // Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP. if endpoint.macAddress == nil { endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil { return err } } // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } if endpoint.addrv6 == nil && config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.AddressIPv6 != nil { network = config.AddressIPv6 } ones, _ := network.Mask.Size() if ones > 80 { err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) return err } ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range endpoint.macAddress { ip6[i+10] = h } endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil { return err } } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { n, err := d.getNetwork(nid) if err != nil { return err } // Check if endpoint id is good and retrieve corresponding endpoint ep, err := n.getEndpoint(eid) if err == nil && ep != nil { return driverapi.ErrEndpointExists(eid) } endpointStruct := &hcsshim.HNSEndpoint{ VirtualNetwork: n.config.HnsID, } ec, err := parseEndpointOptions(epOptions) macAddress := ifInfo.MacAddress() // Use the macaddress if it was provided if macAddress != nil { endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1) } endpointStruct.Policies, err = convertPortBindings(ec.PortBindings) if err != nil { return err } qosPolicies, err := convertQosPolicies(ec.QosPolicies) if err != nil { return err } endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...) if ifInfo.Address() != nil { endpointStruct.IPAddress = ifInfo.Address().IP } configurationb, err := json.Marshal(endpointStruct) if err != nil { return err } hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb)) if err != nil { return err } mac, err := net.ParseMAC(hnsresponse.MacAddress) if err != nil { return err } // TODO For now the ip mask is not in the info generated by HNS endpoint := &hnsEndpoint{ id: eid, addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()}, macAddress: mac, } endpoint.profileID = hnsresponse.Id endpoint.config = ec endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies) if err != nil { hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "") return err } n.Lock() n.endpoints[eid] = endpoint n.Unlock() if ifInfo.Address() == nil { ifInfo.SetIPAddress(endpoint.addr) } if macAddress == nil { ifInfo.SetMacAddress(endpoint.macAddress) } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { if ifInfo == nil { return errors.New("invalid interface passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Create the sandbox side pipe interface if ifInfo.MacAddress() == nil { // No MAC address assigned to interface. Generate a random MAC to assign endpoint.macAddress = netutils.GenerateRandomMAC() if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { logrus.Warnf("Unable to set mac address: %s to endpoint: %s", endpoint.macAddress.String(), endpoint.id) return err } } else { endpoint.macAddress = ifInfo.MacAddress() } endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() c := n.config // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(endpoint, c.DefaultBindingIntf, c.DefaultBindingIP, true) if err != nil { return err } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { var ( ipv6Addr *net.IPNet err error ) defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // v4 address for the sandbox side pipe interface ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil) if err != nil { return err } ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask} // Down the interface before configuring mac address. if err = netlink.LinkSetDown(sbox); err != nil { return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err) } // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP. mac := electMacAddress(epConfig, ip4) err = netlink.LinkSetHardwareAddr(sbox, mac) if err != nil { return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err) } endpoint.macAddress = mac // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } // v6 address for the sandbox side pipe interface ipv6Addr = &net.IPNet{} if config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.FixedCIDRv6 != nil { network = config.FixedCIDRv6 } ones, _ := network.Mask.Size() if ones <= 80 { ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range mac { ip6[i+10] = h } } ip6, err := ipAllocator.RequestIP(network, ip6) if err != nil { return err } ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask} } // Create the sandbox side pipe interface endpoint.srcName = containerIfName endpoint.addr = ipv4Addr if config.EnableIPv6 { endpoint.addrv6 = ipv6Addr } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy) if err != nil { return err } err = ifInfo.SetMacAddress(endpoint.macAddress) if err != nil { return err } err = ifInfo.SetIPAddress(ipv4Addr) if err != nil { return err } if config.EnableIPv6 { err = ifInfo.SetIPAddress(ipv6Addr) if err != nil { return err } } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { var err error if err = validateID(nid, eid); err != nil { return err } // Since we perform lazy configuration make sure we try // configuring the driver when we enter CreateEndpoint since // CreateNetwork may not be called in every node. if err := d.configure(); err != nil { return err } n := d.network(nid) if n == nil { return fmt.Errorf("network id %q not found", nid) } ep := &endpoint{ id: eid, nid: n.id, addr: ifInfo.Address(), mac: ifInfo.MacAddress(), } if ep.addr == nil { return fmt.Errorf("create endpoint was not passed interface IP address") } if s := n.getSubnetforIP(ep.addr); s == nil { return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid) } // Todo: Add port bindings and qos policies here hnsEndpoint := &hcsshim.HNSEndpoint{ VirtualNetwork: n.hnsId, IPAddress: ep.addr.IP, EnableInternalDNS: true, } if ep.mac != nil { hnsEndpoint.MacAddress = ep.mac.String() } paPolicy, err := json.Marshal(hcsshim.PaPolicy{ Type: "PA", PA: n.providerAddress, }) if err != nil { return err } hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy) configurationb, err := json.Marshal(hnsEndpoint) if err != nil { return err } hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb)) if err != nil { return err } ep.profileId = hnsresponse.Id if ep.mac == nil { ep.mac, err = net.ParseMAC(hnsresponse.MacAddress) if err != nil { return err } if err := ifInfo.SetMacAddress(ep.mac); err != nil { return err } } n.addEndpoint(ep) if err := d.writeEndpointToStore(ep); err != nil { return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err) } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // Create the sandbox side pipe interface endpoint.srcName = containerIfName endpoint.macAddress = ifInfo.MacAddress() endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() // Down the interface before configuring mac address. if err = netlink.LinkSetDown(sbox); err != nil { return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err) } // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP. if endpoint.macAddress == nil { endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { return err } } err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress) if err != nil { return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err) } // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } if endpoint.addrv6 == nil && config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.AddressIPv6 != nil { network = config.AddressIPv6 } ones, _ := network.Mask.Size() if ones > 80 { err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) return err } ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range endpoint.macAddress { ip6[i+10] = h } endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil { return err } } // Add a neighbor proxy if using NDP proxying if config.NDPProxyInterface != "" && config.EnableIPv6 { link, err := netlink.LinkByName(config.NDPProxyInterface) if err != nil { return err } neighbor := netlink.Neigh{ LinkIndex: link.Attrs().Index, Family: netlink.FAMILY_V6, State: netlink.NUD_PERMANENT, Type: netlink.NDA_UNSPEC, Flags: netlink.NTF_PROXY, IP: endpoint.addrv6.IP, HardwareAddr: endpoint.macAddress, } if err := netlink.NeighAdd(&neighbor); err != nil { logrus.Warnf("could not add the neighbor proxy: %v", err) return err } if endpoint.config != nil { for _, port := range endpoint.config.ExposedPorts { insert := []string{ string(iptables.Insert), DockerChain, "-p", port.Proto.String(), "-d", endpoint.addrv6.String(), "--dport", strconv.Itoa(int(port.Port)), "-j", "ACCEPT", } iptables.Raw(iptables.IP6Tables, insert...) } } } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy) if err != nil { return err } return nil }