netconfig: make forward error correction (FEC) configurable
This commit is contained in:
parent
caea507b86
commit
196e3f9fd7
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/google/nftables/binaryutil"
|
"github.com/google/nftables/binaryutil"
|
||||||
"github.com/google/nftables/expr"
|
"github.com/google/nftables/expr"
|
||||||
"github.com/google/renameio"
|
"github.com/google/renameio"
|
||||||
|
"github.com/mdlayher/ethtool"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
@ -269,6 +270,13 @@ type InterfaceDetails struct {
|
|||||||
ExtraAddrs []string `json:"extra_addrs"` // e.g. ["192.168.23.1/24"]
|
ExtraAddrs []string `json:"extra_addrs"` // e.g. ["192.168.23.1/24"]
|
||||||
ExtraRoutes []Route `json:"extra_routes"`
|
ExtraRoutes []Route `json:"extra_routes"`
|
||||||
MTU int `json:"mtu"` // e.g. 1492 for PPPoE connections
|
MTU int `json:"mtu"` // e.g. 1492 for PPPoE connections
|
||||||
|
// FEC optionally allows configuring forward error correction, e.g. RS for
|
||||||
|
// reed-solomon forward error correction, or Off to disable.
|
||||||
|
//
|
||||||
|
// Some network card and SFP module combinations (e.g. Mellanox ConnectX-4
|
||||||
|
// with a Flexoptix P.B1625G.10.AD) need to explicitly be configured to use
|
||||||
|
// RS forward error correction, otherwise they won’t link.
|
||||||
|
FEC string `json:"fec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BridgeDetails struct {
|
type BridgeDetails struct {
|
||||||
@ -371,6 +379,63 @@ func applyBridges(cfg *InterfaceConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyInterfaceFEC(details InterfaceDetails) error {
|
||||||
|
if details.FEC == "" {
|
||||||
|
return nil // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
desired := ethtool.FECModes(unix.ETHTOOL_FEC_RS)
|
||||||
|
switch strings.ToLower(details.FEC) {
|
||||||
|
case "rs":
|
||||||
|
desired = unix.ETHTOOL_FEC_RS
|
||||||
|
case "baser":
|
||||||
|
desired = unix.ETHTOOL_FEC_BASER
|
||||||
|
case "off":
|
||||||
|
desired = unix.ETHTOOL_FEC_OFF
|
||||||
|
case "none":
|
||||||
|
desired = unix.ETHTOOL_FEC_NONE
|
||||||
|
case "llrs":
|
||||||
|
desired = unix.ETHTOOL_FEC_LLRS
|
||||||
|
case "auto":
|
||||||
|
desired = 0
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown FEC value %q, expected one of RS, BaseR, LLRS, Auto, None, Off", details.FEC)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl, err := ethtool.New()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cl.Close()
|
||||||
|
|
||||||
|
li, err := cl.LinkInfo(ethtool.Interface{Name: details.Name})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("LinkInfo(%s): %v", details.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fec, err := cl.FEC(li.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("FEC(%s): %v", li.Interface.Name, err)
|
||||||
|
}
|
||||||
|
log.Printf("FEC supported/configured: [%v], active: %v", fec.Supported(), fec.Active)
|
||||||
|
// fec.Active is not set when there is no link, so we compare
|
||||||
|
// supported/configured instead.
|
||||||
|
if fec.Supported() == desired {
|
||||||
|
return nil // already matching the desired configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("setting FEC to %v", desired)
|
||||||
|
if err := cl.SetFEC(ethtool.FEC{
|
||||||
|
Interface: li.Interface,
|
||||||
|
Modes: desired,
|
||||||
|
Auto: strings.ToLower(details.FEC) == "auto",
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func applyInterfaces(dir, root string, cfg InterfaceConfig) error {
|
func applyInterfaces(dir, root string, cfg InterfaceConfig) error {
|
||||||
byName := make(map[string]InterfaceDetails)
|
byName := make(map[string]InterfaceDetails)
|
||||||
byHardwareAddr := make(map[string]InterfaceDetails)
|
byHardwareAddr := make(map[string]InterfaceDetails)
|
||||||
@ -439,6 +504,11 @@ func applyInterfaces(dir, root string, cfg InterfaceConfig) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := applyInterfaceFEC(details); err != nil {
|
||||||
|
// TODO: turn this into returning an error once proven stable
|
||||||
|
log.Printf("applyInterfaceFEC: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if attr.OperState != netlink.OperUp {
|
if attr.OperState != netlink.OperUp {
|
||||||
// Set the interface to up, which is required by all other configuration.
|
// Set the interface to up, which is required by all other configuration.
|
||||||
if err := netlink.LinkSetUp(l); err != nil {
|
if err := netlink.LinkSetUp(l); err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user