Skip to content
This repository has been archived by the owner on Aug 19, 2023. It is now read-only.

Commit

Permalink
feat: support ipv6 routes
Browse files Browse the repository at this point in the history
While IPv6 were mostly supported already, there was a single segment in
the interface setup which forced everything into an IPv4 route.
This limitation has been removed.

In so doing, route metrics have been cleaned up a small amount.
This change allows the specification of the route metric from the
config.

Fixes siderolabs#2772

Signed-off-by: Seán C McCord <[email protected]>
  • Loading branch information
Ulexus authored and talos-bot committed Nov 17, 2020
1 parent 6d83244 commit 5d4d179
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 31 deletions.
19 changes: 16 additions & 3 deletions internal/app/networkd/pkg/address/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"context"
"net"
"time"

"github.com/insomniacslk/dhcp/dhcpv4"
)

// Addressing provides an interface for abstracting the underlying network
Expand All @@ -32,4 +30,19 @@ type Addressing interface {
}

// Route is a representation of a network route.
type Route = dhcpv4.Route
type Route struct {
// Destination is the destination network this route provides.
Destination *net.IPNet

// Gateway is the router through which the destination may be reached.
// This option is exclusive of Interface
Gateway net.IP

// Interface indicates the route is an interface route, and traffic destinted for the Gateway should be sent through the given network interface.
// This option is exclusive of Gateway.
Interface string

// Metric indicates the "distance" to the destination through this route.
// This is an integer which allows the control of priority in the case of multiple routes to the same destination.
Metric uint32
}
37 changes: 32 additions & 5 deletions internal/app/networkd/pkg/address/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"github.com/talos-systems/talos/pkg/machinery/constants"
)

const dhcpReceivedRouteMetric uint32 = 1024

// DHCP implements the Addressing interface.
type DHCP struct {
Ack *dhcpv4.DHCPv4
Expand Down Expand Up @@ -116,26 +118,51 @@ func (d *DHCP) Valid() bool {
// If the DHCP server returns both a Classless Static Routes option and
// a Router option, the DHCP client MUST ignore the Router option.
func (d *DHCP) Routes() (routes []*Route) {
metric := dhcpReceivedRouteMetric

if d.DHCPOptions != nil && d.DHCPOptions.RouteMetric() != 0 {
metric = d.DHCPOptions.RouteMetric()
}

defRoute := &net.IPNet{
IP: net.IPv4zero,
Mask: net.IPv4Mask(0, 0, 0, 0),
}

for _, router := range d.Ack.Router() {
routes = append(routes, &Route{Router: router, Dest: defRoute})
routes = append(routes, &Route{
Destination: defRoute,
Gateway: router,
Metric: metric,
})
}

// overwrite router option if classless routes were provided.
if len(d.Ack.ClasslessStaticRoute()) > 0 {
routes = d.Ack.ClasslessStaticRoute()
routes = []*Route{}

for _, dhcpRoute := range d.Ack.ClasslessStaticRoute() {
routes = append(routes, &Route{
Destination: dhcpRoute.Dest,
Gateway: dhcpRoute.Router,
Metric: metric,
})
}
}

// append any routes that were provided in config
for _, route := range d.RouteList {
// nolint: errcheck
_, ipnet, _ := net.ParseCIDR(route.Network())
_, ipnet, err := net.ParseCIDR(route.Network())
if err != nil {
// TODO: we should at least log this failure
continue
}

routes = append(routes, &Route{Dest: ipnet, Router: net.ParseIP(route.Gateway())})
routes = append(routes, &Route{
Destination: ipnet,
Gateway: net.ParseIP(route.Gateway()),
Metric: staticRouteDefaultMetric,
})
}

return routes
Expand Down
23 changes: 19 additions & 4 deletions internal/app/networkd/pkg/address/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/talos-systems/talos/pkg/machinery/config"
)

const staticRouteDefaultMetric uint32 = 10

// Static implements the Addressing interface.
type Static struct {
CIDR string
Expand Down Expand Up @@ -98,10 +100,23 @@ func (s *Static) Scope() uint8 {
// TODO: do we need to be explicit on route vs gateway?
func (s *Static) Routes() (routes []*Route) {
for _, route := range s.RouteList {
// nolint: errcheck
_, ipnet, _ := net.ParseCIDR(route.Network())

routes = append(routes, &Route{Dest: ipnet, Router: net.ParseIP(route.Gateway())})
_, ipnet, err := net.ParseCIDR(route.Network())
if err != nil {
// TODO: we should at least log the error
continue
}

metric := staticRouteDefaultMetric

if route.Metric() != 0 {
metric = route.Metric()
}

routes = append(routes, &Route{
Destination: ipnet,
Gateway: net.ParseIP(route.Gateway()),
Metric: metric,
})
}

return routes
Expand Down
24 changes: 6 additions & 18 deletions internal/app/networkd/pkg/nic/nic.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,38 +378,26 @@ func (n *NetworkInterface) configureInterface(method address.Addressing, link *n
// Add any routes
for _, r := range method.Routes() {
// If gateway/router is 0.0.0.0 we'll set to nil so route scope decision will be correct
gw := r.Router
if net.IPv4zero.Equal(gw) {
gw := r.Gateway
if net.IPv4zero.Equal(gw) || net.IPv6zero.Equal(gw) {
gw = nil
}

src := method.Address()
// if destination is the ipv6 route,and gateway is LL do not pass a src address to set the default geteway
if net.IPv6zero.Equal(r.Dest.IP) && gw.IsLinkLocalUnicast() {
// if destination is the ipv6 default route,and gateway is LL do not pass a src address to set the default geteway
if net.IPv6zero.Equal(r.Destination.IP) && gw.IsLinkLocalUnicast() {
src = nil
}

attr := rtnetlink.RouteAttributes{
Dst: r.Dest.IP,
OutIface: uint32(method.Link().Index),
Priority: r.Metric,
}

if gw != nil {
attr.Gateway = gw
}

// Set DHCP specific options
if dhcpObj, ok := method.(*address.DHCP); ok {
if dhcpObj.DHCPOptions != nil {
attr.Priority = dhcpObj.DHCPOptions.RouteMetric()
}

if attr.Priority == uint32(0) {
attr.Priority = uint32(1024)
}
}

err = n.rtnlConn.RouteAdd(method.Link(), *r.Dest, gw, rtnl.WithRouteSrc(src), rtnl.WithRouteAttrs(attr))
err = n.rtnlConn.RouteAdd(method.Link(), *r.Destination, gw, rtnl.WithRouteSrc(src), rtnl.WithRouteAttrs(attr))
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/machinery/config/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ type Vlan interface {
type Route interface {
Network() string
Gateway() string
Metric() uint32
}

// Time defines the requirements for a config that pertains to time related
Expand Down
5 changes: 5 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,11 @@ func (r *Route) Gateway() string {
return r.RouteGateway
}

// Metric implements the MachineNetwork interface.
func (r *Route) Metric() uint32 {
return r.RouteMetric
}

// Interfaces implements the MachineNetwork interface.
func (b *Bond) Interfaces() []string {
if b == nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ var (
{
RouteNetwork: "0.0.0.0/0",
RouteGateway: "192.168.2.1",
RouteMetric: 1024,
},
},
},
Expand Down Expand Up @@ -1214,6 +1215,8 @@ type Route struct {
RouteNetwork string `yaml:"network"`
// description: The route's gateway.
RouteGateway string `yaml:"gateway"`
// description: The optional metric for the route.
RouteMetric uint32 `yaml:"metric,omitempty"`
}

// RegistryMirrorConfig represents mirror configuration for a registry.
Expand Down
7 changes: 6 additions & 1 deletion pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,7 @@ func init() {
FieldName: "routes",
},
}
RouteDoc.Fields = make([]encoder.Doc, 2)
RouteDoc.Fields = make([]encoder.Doc, 3)
RouteDoc.Fields[0].Name = "network"
RouteDoc.Fields[0].Type = "string"
RouteDoc.Fields[0].Note = ""
Expand All @@ -1234,6 +1234,11 @@ func init() {
RouteDoc.Fields[1].Note = ""
RouteDoc.Fields[1].Description = "The route's gateway."
RouteDoc.Fields[1].Comments[encoder.LineComment] = "The route's gateway."
RouteDoc.Fields[2].Name = "metric"
RouteDoc.Fields[2].Type = "uint32"
RouteDoc.Fields[2].Note = ""
RouteDoc.Fields[2].Description = "The optional metric for the route."
RouteDoc.Fields[2].Comments[encoder.LineComment] = "The optional metric for the route."

RegistryMirrorConfigDoc.Type = "RegistryMirrorConfig"
RegistryMirrorConfigDoc.Comments[encoder.LineComment] = "RegistryMirrorConfig represents mirror configuration for a registry."
Expand Down
17 changes: 17 additions & 0 deletions website/content/docs/v0.7/Reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ network:
routes:
- network: 0.0.0.0/0 # The route's network.
gateway: 192.168.2.1 # The route's gateway.
metric: 1024 # The optional metric for the route.
mtu: 1500 # The interface's MTU.
# # Bond specific options.
Expand Down Expand Up @@ -1228,6 +1229,7 @@ interfaces:
routes:
- network: 0.0.0.0/0 # The route's network.
gateway: 192.168.2.1 # The route's gateway.
metric: 1024 # The optional metric for the route.
mtu: 1500 # The interface's MTU.

# # Bond specific options.
Expand Down Expand Up @@ -1298,6 +1300,7 @@ interfaces:
routes:
- network: 0.0.0.0/0 # The route's network.
gateway: 192.168.2.1 # The route's gateway.
metric: 1024 # The optional metric for the route.
mtu: 1500 # The interface's MTU.

# # Bond specific options.
Expand Down Expand Up @@ -2633,6 +2636,7 @@ Appears in:
routes:
- network: 0.0.0.0/0 # The route's network.
gateway: 192.168.2.1 # The route's gateway.
metric: 1024 # The optional metric for the route.
mtu: 1500 # The interface's MTU.
# # Bond specific options.
Expand Down Expand Up @@ -3425,6 +3429,19 @@ The route's gateway.
<hr />
<div class="dd">
<code>metric</code> <i>uint32</i>
</div>
<div class="dt">
The optional metric for the route.
</div>
<hr />
Expand Down

0 comments on commit 5d4d179

Please sign in to comment.