Skip to content

Commit

Permalink
feat: openstack dhcp-v6 types
Browse files Browse the repository at this point in the history
Support ipv6_dhcp-* types of network.
Apply static IPs in all supported network types.

Signed-off-by: Serge Logvinov <[email protected]>
Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
sergelogvinov authored and smira committed May 16, 2022
1 parent 5ec4e90 commit 63f23e9
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import (
"encoding/json"
stderrors "errors"
"fmt"
"net"
"strconv"
"strings"
"log"

"github.com/talos-systems/go-procfs/procfs"
"inet.af/netaddr"

"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/errors"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/utils"
"github.com/talos-systems/talos/pkg/machinery/nethelpers"
"github.com/talos-systems/talos/pkg/machinery/resources/network"
)
Expand Down Expand Up @@ -109,55 +108,45 @@ func (o *Openstack) ParseMetadata(unmarshalledMetadataConfig *MetadataConfig, un
},
ConfigLayer: network.ConfigPlatform,
})
case "ipv4", "ipv6":
var ipPrefix netaddr.IPPrefix
case "ipv6_dhcp", "ipv6_dhcpv6-stateless", "ipv6_dhcpv6-stateful":
networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{
Operator: network.OperatorDHCP6,
LinkName: iface,
RequireUp: true,
DHCP6: network.DHCP6OperatorSpec{
RouteMetric: 1024,
},
ConfigLayer: network.ConfigPlatform,
})
case "ipv4", "ipv6", "ipv6_slaac":
// FIXME: we need to switch on/off slaac here
default:
log.Printf("network type %s is not supported", ntwrk.Type)

continue
}

if ntwrk.Address != "" {
ipPrefix, err := utils.IPPrefixFrom(ntwrk.Address, ntwrk.Netmask)
if err != nil {
return nil, fmt.Errorf("failed to parse ip address: %w", err)
}

family := nethelpers.FamilyInet4
if ntwrk.Type == "ipv6" {
if ipPrefix.IP().Is6() {
family = nethelpers.FamilyInet6
}

if ntwrk.Address != "" {
cidr := strings.SplitN(ntwrk.Address, "/", 2)
if len(cidr) == 1 {
ip, err := netaddr.ParseIP(ntwrk.Address)
if err != nil {
return nil, fmt.Errorf("failed to parse ip address: %w", err)
}

bits, err := strconv.Atoi(ntwrk.Netmask)
if err != nil {
netmask, err := netaddr.ParseIP(ntwrk.Netmask)
if err != nil {
return nil, fmt.Errorf("failed to parse ip netmask: %w", err)
}

mask, _ := netmask.MarshalBinary() //nolint:errcheck // never fails
ones, _ := net.IPMask(mask).Size()
ipPrefix = netaddr.IPPrefixFrom(ip, uint8(ones))
} else {
ipPrefix = netaddr.IPPrefixFrom(ip, uint8(bits))
}
} else {
var err error

ipPrefix, err = netaddr.ParseIPPrefix(ntwrk.Address)
if err != nil {
return nil, fmt.Errorf("failed to parse ipPrefix: %w", err)
}
}

networkConfig.Addresses = append(networkConfig.Addresses,
network.AddressSpecSpec{
ConfigLayer: network.ConfigPlatform,
LinkName: iface,
Address: ipPrefix,
Scope: nethelpers.ScopeGlobal,
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
Family: family,
},
)
}
networkConfig.Addresses = append(networkConfig.Addresses,
network.AddressSpecSpec{
ConfigLayer: network.ConfigPlatform,
LinkName: iface,
Address: ipPrefix,
Scope: nethelpers.ScopeGlobal,
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
Family: family,
},
)

if ntwrk.Gateway != "" {
gw, err := netaddr.ParseIP(ntwrk.Gateway)
Expand All @@ -176,71 +165,43 @@ func (o *Openstack) ParseMetadata(unmarshalledMetadataConfig *MetadataConfig, un
Priority: 1024,
}

if family == nethelpers.FamilyInet6 {
route.Priority = 2048
}

route.Normalize()

networkConfig.Routes = append(networkConfig.Routes, route)
}
}

for _, route := range ntwrk.Routes {
gw, err := netaddr.ParseIP(route.Gateway)
if err != nil {
return nil, fmt.Errorf("failed to parse route gateway: %w", err)
}

destIP, err := netaddr.ParseIP(route.Network)
if err != nil {
return nil, fmt.Errorf("failed to parse route network: %w", err)
}

var dest netaddr.IPPrefix
for _, route := range ntwrk.Routes {
gw, err := netaddr.ParseIP(route.Gateway)
if err != nil {
return nil, fmt.Errorf("failed to parse route gateway: %w", err)
}

bits, err := strconv.Atoi(route.Netmask)
if err != nil {
var maskIP netaddr.IP

maskIP, err = netaddr.ParseIP(route.Netmask)
if err != nil {
return nil, fmt.Errorf("failed to parse route netmask: %w", err)
}

mask, _ := maskIP.MarshalBinary() //nolint:errcheck

dest, err = destIP.Netmask(mask)
if err != nil {
return nil, fmt.Errorf("failed to parse route dest netmask digits: %w", err)
}
} else {
dest, err = destIP.Prefix(uint8(bits))
if err != nil {
return nil, fmt.Errorf("failed to parse route dest netmask digits: %w", err)
}
}
dest, err := utils.IPPrefixFrom(route.Network, route.Netmask)
if err != nil {
return nil, fmt.Errorf("failed to parse route network: %w", err)
}

family := nethelpers.FamilyInet4
if destIP.Is6() {
family = nethelpers.FamilyInet6
}
family := nethelpers.FamilyInet4
if dest.IP().Is6() {
family = nethelpers.FamilyInet6
}

route := network.RouteSpecSpec{
ConfigLayer: network.ConfigPlatform,
Destination: dest,
Gateway: gw,
OutLinkName: iface,
Table: nethelpers.TableMain,
Protocol: nethelpers.ProtocolStatic,
Type: nethelpers.TypeUnicast,
Family: family,
Priority: 1024,
}
route := network.RouteSpecSpec{
ConfigLayer: network.ConfigPlatform,
Destination: dest,
Gateway: gw,
OutLinkName: iface,
Table: nethelpers.TableMain,
Protocol: nethelpers.ProtocolStatic,
Type: nethelpers.TypeUnicast,
Family: family,
Priority: 1024,
}

route.Normalize()
route.Normalize()

networkConfig.Routes = append(networkConfig.Routes, route)
}
networkConfig.Routes = append(networkConfig.Routes, route)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ addresses:
scope: global
flags: permanent
layer: platform
- address: fd60:172:16:84:f816:3eff:fe73:5901/64
linkName: eth2
family: inet6
scope: global
flags: permanent
layer: platform
links:
- name: eth0
logical: false
Expand All @@ -32,14 +38,21 @@ links:
kind: ""
type: netrom
layer: platform
- name: eth2
logical: false
up: true
mtu: 0
kind: ""
type: netrom
layer: platform
routes:
- family: inet6
dst: ""
src: ""
gateway: 2000:0:100:2fff:ff:ff:ff:ff
outLinkName: eth0
table: main
priority: 2048
priority: 1024
scope: global
type: unicast
flags: ""
Expand Down Expand Up @@ -110,5 +123,11 @@ operators:
dhcp4:
routeMetric: 1024
layer: platform
- operator: dhcp6
linkName: eth2
requireUp: true
dhcp6:
routeMetric: 1024
layer: platform
externalIPs:
- 1.2.3.4
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"type": "ovs",
"mtu": 9000,
"vif_id": "c816df7e-7bcc-45ca-9eb2-3d3d3dca0639"
},
{
"ethernet_mac_address": "A4:BF:00:10:20:33",
"id": "aae16046-6c74-4f33-acf2-a16e9ab093ed",
"type": "vif",
"vif_id": "c816df7e-7bcc-45ca-9eb2-3d3d3dca063a"
}
],
"networks": [
Expand Down Expand Up @@ -74,6 +80,15 @@
"gateway": "fd00::1"
}
]
},
{
"id": "privatnet-ipv6-2",
"link": "aae16046-6c74-4f33-acf2-a16e9ab093ed",
"network_id": "66374c4d-5123-4f11-8fa9-8a6dea2b4fe7",
"type": "ipv6_dhcpv6-stateless",
"ip_address": "fd60:172:16:84:f816:3eff:fe73:5901",
"netmask": "ffff:ffff:ffff:ffff::",
"routes": []
}
],
"services": [
Expand Down
57 changes: 57 additions & 0 deletions internal/app/machined/pkg/runtime/v1alpha1/platform/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package utils

import (
"fmt"
"net"
"strconv"
"strings"

"inet.af/netaddr"
)

// IPPrefixFrom make netaddr.IPPrefix from cidr-address and netmask strings.
// address can be IP or CIDR (1.1.1.1 or 1.1.1.1/8 or 1.1.1.1/255.0.0.0)
// netmask can be IP or number (255.255.255.0 or 24 or empty).
func IPPrefixFrom(address, netmask string) (netaddr.IPPrefix, error) {
cidr := strings.SplitN(address, "/", 2)
if len(cidr) == 1 {
address = cidr[0]
} else {
address = cidr[0]
netmask = cidr[1]
}

ip, err := netaddr.ParseIP(address)
if err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to parse ip address: %w", err)
}

if netmask == "" {
if ip.Is4() {
netmask = "32"
} else {
netmask = "128"
}
}

bits, err := strconv.Atoi(netmask)
if err != nil {
netmask, err := netaddr.ParseIP(netmask)
if err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to parse netmask: %w", err)
}

mask, _ := netmask.MarshalBinary() //nolint:errcheck // never fails
bits, _ = net.IPMask(mask).Size()
}

if ip.Is4() && bits > 32 {
return netaddr.IPPrefix{}, fmt.Errorf("failed netmask should be the same address family")
}

return netaddr.IPPrefixFrom(ip, uint8(bits)), nil
}

0 comments on commit 63f23e9

Please sign in to comment.