mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #1228 from aboch/ll
Allow to program Endpoint link-local addresses
This commit is contained in:
commit
4c1ed2010b
7 changed files with 87 additions and 2 deletions
|
@ -852,11 +852,25 @@ func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
linkLocalMask = net.CIDRMask(16, 32)
|
||||||
|
linkLocalMaskIPv6 = net.CIDRMask(64, 128)
|
||||||
|
)
|
||||||
|
|
||||||
// CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint
|
// CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint
|
||||||
func CreateOptionIpam(ipV4, ipV6 net.IP, ipamOptions map[string]string) EndpointOption {
|
func CreateOptionIpam(ipV4, ipV6 net.IP, llIPs []net.IP, ipamOptions map[string]string) EndpointOption {
|
||||||
return func(ep *endpoint) {
|
return func(ep *endpoint) {
|
||||||
ep.prefAddress = ipV4
|
ep.prefAddress = ipV4
|
||||||
ep.prefAddressV6 = ipV6
|
ep.prefAddressV6 = ipV6
|
||||||
|
if len(llIPs) != 0 {
|
||||||
|
for _, ip := range llIPs {
|
||||||
|
nw := &net.IPNet{IP: ip, Mask: linkLocalMask}
|
||||||
|
if ip.To4() == nil {
|
||||||
|
nw.Mask = linkLocalMaskIPv6
|
||||||
|
}
|
||||||
|
ep.iface.llAddrs = append(ep.iface.llAddrs, nw)
|
||||||
|
}
|
||||||
|
}
|
||||||
ep.ipamOptions = ipamOptions
|
ep.ipamOptions = ipamOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,16 @@ type InterfaceInfo interface {
|
||||||
|
|
||||||
// AddressIPv6 returns the IPv6 address assigned to the endpoint.
|
// AddressIPv6 returns the IPv6 address assigned to the endpoint.
|
||||||
AddressIPv6() *net.IPNet
|
AddressIPv6() *net.IPNet
|
||||||
|
|
||||||
|
// LinkLocalAddresses returns the list of link-local (IPv4/IPv6) addresses assigned to the endpoint.
|
||||||
|
LinkLocalAddresses() []*net.IPNet
|
||||||
}
|
}
|
||||||
|
|
||||||
type endpointInterface struct {
|
type endpointInterface struct {
|
||||||
mac net.HardwareAddr
|
mac net.HardwareAddr
|
||||||
addr *net.IPNet
|
addr *net.IPNet
|
||||||
addrv6 *net.IPNet
|
addrv6 *net.IPNet
|
||||||
|
llAddrs []*net.IPNet
|
||||||
srcName string
|
srcName string
|
||||||
dstPrefix string
|
dstPrefix string
|
||||||
routes []*net.IPNet
|
routes []*net.IPNet
|
||||||
|
@ -67,6 +71,13 @@ func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
|
||||||
if epi.addrv6 != nil {
|
if epi.addrv6 != nil {
|
||||||
epMap["addrv6"] = epi.addrv6.String()
|
epMap["addrv6"] = epi.addrv6.String()
|
||||||
}
|
}
|
||||||
|
if len(epi.llAddrs) != 0 {
|
||||||
|
list := make([]string, 0, len(epi.llAddrs))
|
||||||
|
for _, ll := range epi.llAddrs {
|
||||||
|
list = append(list, ll.String())
|
||||||
|
}
|
||||||
|
epMap["llAddrs"] = list
|
||||||
|
}
|
||||||
epMap["srcName"] = epi.srcName
|
epMap["srcName"] = epi.srcName
|
||||||
epMap["dstPrefix"] = epi.dstPrefix
|
epMap["dstPrefix"] = epi.dstPrefix
|
||||||
var routes []string
|
var routes []string
|
||||||
|
@ -102,7 +113,17 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
|
||||||
return types.InternalErrorf("failed to decode endpoint interface ipv6 address after json unmarshal: %v", err)
|
return types.InternalErrorf("failed to decode endpoint interface ipv6 address after json unmarshal: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if v, ok := epMap["llAddrs"]; ok {
|
||||||
|
list := v.([]string)
|
||||||
|
epi.llAddrs = make([]*net.IPNet, 0, len(list))
|
||||||
|
for _, llS := range list {
|
||||||
|
ll, err := types.ParseCIDR(llS)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalErrorf("failed to decode endpoint interface link-local address (%s) after json unmarshal: %v", llS, err)
|
||||||
|
}
|
||||||
|
epi.llAddrs = append(epi.llAddrs, ll)
|
||||||
|
}
|
||||||
|
}
|
||||||
epi.srcName = epMap["srcName"].(string)
|
epi.srcName = epMap["srcName"].(string)
|
||||||
epi.dstPrefix = epMap["dstPrefix"].(string)
|
epi.dstPrefix = epMap["dstPrefix"].(string)
|
||||||
|
|
||||||
|
@ -131,6 +152,12 @@ func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error {
|
||||||
dstEpi.dstPrefix = epi.dstPrefix
|
dstEpi.dstPrefix = epi.dstPrefix
|
||||||
dstEpi.v4PoolID = epi.v4PoolID
|
dstEpi.v4PoolID = epi.v4PoolID
|
||||||
dstEpi.v6PoolID = epi.v6PoolID
|
dstEpi.v6PoolID = epi.v6PoolID
|
||||||
|
if len(epi.llAddrs) != 0 {
|
||||||
|
dstEpi.llAddrs = make([]*net.IPNet, 0, len(epi.llAddrs))
|
||||||
|
for _, ll := range epi.llAddrs {
|
||||||
|
dstEpi.llAddrs = append(dstEpi.llAddrs, ll)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, route := range epi.routes {
|
for _, route := range epi.routes {
|
||||||
dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route))
|
dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route))
|
||||||
|
@ -266,6 +293,10 @@ func (epi *endpointInterface) AddressIPv6() *net.IPNet {
|
||||||
return types.GetIPNetCopy(epi.addrv6)
|
return types.GetIPNetCopy(epi.addrv6)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (epi *endpointInterface) LinkLocalAddresses() []*net.IPNet {
|
||||||
|
return epi.llAddrs
|
||||||
|
}
|
||||||
|
|
||||||
func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error {
|
func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error {
|
||||||
epi.srcName = srcName
|
epi.srcName = srcName
|
||||||
epi.dstPrefix = dstPrefix
|
epi.dstPrefix = dstPrefix
|
||||||
|
|
|
@ -837,6 +837,12 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
|
||||||
|
|
||||||
ep.processOptions(options...)
|
ep.processOptions(options...)
|
||||||
|
|
||||||
|
for _, llIPNet := range ep.Iface().LinkLocalAddresses() {
|
||||||
|
if !llIPNet.IP.IsLinkLocalUnicast() {
|
||||||
|
return nil, types.BadRequestErrorf("invalid link local IP address: %v", llIPNet.IP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if opt, ok := ep.generic[netlabel.MacAddress]; ok {
|
if opt, ok := ep.generic[netlabel.MacAddress]; ok {
|
||||||
if mac, ok := opt.(net.HardwareAddr); ok {
|
if mac, ok := opt.(net.HardwareAddr); ok {
|
||||||
ep.iface.mac = mac
|
ep.iface.mac = mac
|
||||||
|
|
|
@ -24,6 +24,7 @@ type nwIface struct {
|
||||||
mac net.HardwareAddr
|
mac net.HardwareAddr
|
||||||
address *net.IPNet
|
address *net.IPNet
|
||||||
addressIPv6 *net.IPNet
|
addressIPv6 *net.IPNet
|
||||||
|
llAddrs []*net.IPNet
|
||||||
routes []*net.IPNet
|
routes []*net.IPNet
|
||||||
bridge bool
|
bridge bool
|
||||||
ns *networkNamespace
|
ns *networkNamespace
|
||||||
|
@ -86,6 +87,13 @@ func (i *nwIface) AddressIPv6() *net.IPNet {
|
||||||
return types.GetIPNetCopy(i.addressIPv6)
|
return types.GetIPNetCopy(i.addressIPv6)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *nwIface) LinkLocalAddresses() []*net.IPNet {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
|
||||||
|
return i.llAddrs
|
||||||
|
}
|
||||||
|
|
||||||
func (i *nwIface) Routes() []*net.IPNet {
|
func (i *nwIface) Routes() []*net.IPNet {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
defer i.Unlock()
|
defer i.Unlock()
|
||||||
|
@ -316,6 +324,7 @@ func configureInterface(iface netlink.Link, i *nwIface) error {
|
||||||
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %v", ifaceName, i.Address())},
|
{setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %v", ifaceName, i.Address())},
|
||||||
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
|
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
|
||||||
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
||||||
|
{setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, config := range ifaceConfigurators {
|
for _, config := range ifaceConfigurators {
|
||||||
|
@ -359,6 +368,16 @@ func setInterfaceIPv6(iface netlink.Link, i *nwIface) error {
|
||||||
return netlink.AddrAdd(iface, ipAddr)
|
return netlink.AddrAdd(iface, ipAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setInterfaceLinkLocalIPs(iface netlink.Link, i *nwIface) error {
|
||||||
|
for _, llIP := range i.LinkLocalAddresses() {
|
||||||
|
ipAddr := &netlink.Addr{IPNet: llIP}
|
||||||
|
if err := netlink.AddrAdd(iface, ipAddr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func setInterfaceName(iface netlink.Link, i *nwIface) error {
|
func setInterfaceName(iface netlink.Link, i *nwIface) error {
|
||||||
return netlink.LinkSetName(iface, i.DstName())
|
return netlink.LinkSetName(iface, i.DstName())
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,12 @@ func (n *networkNamespace) AddressIPv6(addr *net.IPNet) IfaceOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *networkNamespace) LinkLocalAddresses(list []*net.IPNet) IfaceOption {
|
||||||
|
return func(i *nwIface) {
|
||||||
|
i.llAddrs = list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption {
|
func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption {
|
||||||
return func(i *nwIface) {
|
return func(i *nwIface) {
|
||||||
i.routes = routes
|
i.routes = routes
|
||||||
|
|
|
@ -85,6 +85,9 @@ type IfaceOptionSetter interface {
|
||||||
// Address returns an option setter to set IPv6 address.
|
// Address returns an option setter to set IPv6 address.
|
||||||
AddressIPv6(*net.IPNet) IfaceOption
|
AddressIPv6(*net.IPNet) IfaceOption
|
||||||
|
|
||||||
|
// LinkLocalAddresses returns an option setter to set the link-local IP addresses.
|
||||||
|
LinkLocalAddresses([]*net.IPNet) IfaceOption
|
||||||
|
|
||||||
// Master returns an option setter to set the master interface if any for this
|
// Master returns an option setter to set the master interface if any for this
|
||||||
// interface. The master interface name should refer to the srcname of a
|
// interface. The master interface name should refer to the srcname of a
|
||||||
// previously added interface of type bridge.
|
// previously added interface of type bridge.
|
||||||
|
@ -138,6 +141,9 @@ type Interface interface {
|
||||||
// IPv6 address for the interface.
|
// IPv6 address for the interface.
|
||||||
AddressIPv6() *net.IPNet
|
AddressIPv6() *net.IPNet
|
||||||
|
|
||||||
|
// LinkLocalAddresses returns the link-local IP addresses assigned to the interface.
|
||||||
|
LinkLocalAddresses() []*net.IPNet
|
||||||
|
|
||||||
// IP routes for the interface.
|
// IP routes for the interface.
|
||||||
Routes() []*net.IPNet
|
Routes() []*net.IPNet
|
||||||
|
|
||||||
|
|
|
@ -722,6 +722,9 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
||||||
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
|
||||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
|
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
|
||||||
}
|
}
|
||||||
|
if len(i.llAddrs) != 0 {
|
||||||
|
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs))
|
||||||
|
}
|
||||||
if i.mac != nil {
|
if i.mac != nil {
|
||||||
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
|
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue