Skip to content

Commit

Permalink
check microshift configured ip_family strategy
Browse files Browse the repository at this point in the history
Signed-off-by: Evgeny Slutsky <[email protected]>
  • Loading branch information
eslutsky committed Jan 20, 2025
1 parent f6c4f8a commit 864423c
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 24 deletions.
12 changes: 11 additions & 1 deletion pkg/components/networking.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/openshift/microshift/pkg/assets"
"github.com/openshift/microshift/pkg/config"
"github.com/openshift/microshift/pkg/config/ovn"
"github.com/vishvananda/netlink"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -52,7 +53,16 @@ func startCNIPlugin(ctx context.Context, cfg *config.Config, kubeconfigPath stri
}
}

ovnConfig, err := ovn.NewOVNKubernetesConfigFromFileOrDefault(filepath.Dir(config.ConfigFile), cfg.MultiNode.Enabled)
ip_family := netlink.FAMILY_ALL
if cfg.IsIPv4() && !cfg.IsIPv6() {
ip_family = netlink.FAMILY_V4
}

if cfg.IsIPv6() && !cfg.IsIPv4() {
ip_family = netlink.FAMILY_V6
}

ovnConfig, err := ovn.NewOVNKubernetesConfigFromFileOrDefault(filepath.Dir(config.ConfigFile), cfg.MultiNode.Enabled, ip_family)
if err != nil {
return fmt.Errorf("failed to create OVN-K configuration from %q: %w", config.ConfigFile, err)
}
Expand Down
42 changes: 28 additions & 14 deletions pkg/config/ovn/ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"regexp"

"github.com/openshift/microshift/pkg/util"
"github.com/vishvananda/netlink"
"k8s.io/klog/v2"
"sigs.k8s.io/yaml"
)
Expand Down Expand Up @@ -55,16 +56,29 @@ func (o *OVNKubernetesConfig) validateOVSBridge() error {

// getClusterMTU retrieves MTU from the default route network interface,
// and falls back to use 1500 when unable to get the mtu or less than 0.
func (o *OVNKubernetesConfig) getClusterMTU(multinode bool) {
func (o *OVNKubernetesConfig) getClusterMTU(multinode bool, ip_family int) {
klog.Infof("getClusterMTU: finding default route interface")
link, err := util.FindDefaultRouteIface()
o.MTU = defaultMTU

// if configure both IPV4 and IPV6 check the smallest
//nolint:nestif
if ip_family == netlink.FAMILY_ALL {
mtu, err := util.FindDefaultRouteMinMTU()
if err == nil {
o.MTU = mtu
} else {
klog.Infof("getClusterMTU: error %s.", err)
}
klog.Infof("getClusterMTU: using Dual stack MTU discovery found - %d", mtu)

if err == nil && link.MTU > 0 {
klog.Infof("getClusterMTU: Using Interface %s with MTU %d as source default route.", link.Name, link.MTU)
o.MTU = link.MTU
} else {
klog.Infof("getClusterMTU: Couldnt extract MTU from the default route interface , Using Default MTU.")
o.MTU = defaultMTU
mtu, err := util.FindDefaultRouteMTU(ip_family)
if err == nil {
o.MTU = mtu
} else {
klog.Infof("getClusterMTU: error %s.", err)
}
klog.Infof("getClusterMTU: using ip version: %d stack MTU discovery found - with MTU %d", ip_family, mtu)
}

if multinode {
Expand All @@ -73,12 +87,12 @@ func (o *OVNKubernetesConfig) getClusterMTU(multinode bool) {
}

// withDefaults returns the default values when ovn.yaml is not provided
func (o *OVNKubernetesConfig) withDefaults(multinode bool) *OVNKubernetesConfig {
o.getClusterMTU(multinode)
func (o *OVNKubernetesConfig) withDefaults(multinode bool, ip_family int) *OVNKubernetesConfig {
o.getClusterMTU(multinode, ip_family)
return o
}

func newOVNKubernetesConfigFromFile(path string, multinode bool) (*OVNKubernetesConfig, error) {
func newOVNKubernetesConfigFromFile(path string, multinode bool, ip_family int) (*OVNKubernetesConfig, error) {
o := new(OVNKubernetesConfig)
buf, err := os.ReadFile(path)
if err != nil {
Expand All @@ -91,24 +105,24 @@ func newOVNKubernetesConfigFromFile(path string, multinode bool) (*OVNKubernetes
}
// in case mtu is not defined
if o.MTU == 0 {
o.getClusterMTU(multinode)
o.getClusterMTU(multinode, ip_family)
}
klog.Infof("parsed OVNKubernetes config from file %q: %+v", path, o)

return o, nil
}

func NewOVNKubernetesConfigFromFileOrDefault(dir string, multinode bool) (*OVNKubernetesConfig, error) {
func NewOVNKubernetesConfigFromFileOrDefault(dir string, multinode bool, ip_family int) (*OVNKubernetesConfig, error) {
path := filepath.Join(dir, ovnConfigFileName)
if _, err := os.Stat(path); err != nil {
if errors.Is(err, os.ErrNotExist) {
klog.Infof("OVNKubernetes config file not found, assuming default values")
return new(OVNKubernetesConfig).withDefaults(multinode), nil
return new(OVNKubernetesConfig).withDefaults(multinode, ip_family), nil
}
return nil, fmt.Errorf("failed to get OVNKubernetes config file: %v", err)
}

o, err := newOVNKubernetesConfigFromFile(path, multinode)
o, err := newOVNKubernetesConfigFromFile(path, multinode, ip_family)
if err == nil {
return o, nil
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/config/ovn/ovn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ovn

import (
"testing"

"github.com/vishvananda/netlink"
)

// tests to make sure that the config file is parsed correctly
Expand All @@ -15,7 +17,7 @@ func TestNewOVNKubernetesConfigFromFileOrDefault(t *testing.T) {
}

for _, tt := range ttests {
_, err := NewOVNKubernetesConfigFromFileOrDefault(tt.configFile, false)
_, err := NewOVNKubernetesConfigFromFileOrDefault(tt.configFile, false, netlink.FAMILY_V4)
if (err != nil) != (tt.err != nil) {
t.Errorf("NewOVNKubernetesConfigFromFileOrDefault() error = %v, wantErr %v", err, tt.err)
}
Expand Down
41 changes: 33 additions & 8 deletions pkg/util/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
tcpnet "net"
"net/http"
"os"
"slices"
"sort"
"strings"
"time"
Expand Down Expand Up @@ -275,16 +276,40 @@ func GetHostIPv6(ipHint string) (string, error) {
return "", fmt.Errorf("unable to find host IPv6 address")
}

// Find the Default route Interface based on ipv4 or ipv6 routes.
func FindDefaultRouteIface() (iface *tcpnet.Interface, err error) {
// first try IPv4
parsedStruct, err := findDefaultRouteForFamily(netlink.FAMILY_V4)
if err != nil {
// then try IPv6
parsedStruct, err = findDefaultRouteForFamily(netlink.FAMILY_V6)
func FindDefaultRouteMinMTU() (mtu int, err error) {
ip_families := []int{netlink.FAMILY_V4, netlink.FAMILY_V6}

mtu_slice := []int{}

for _, ip_family := range ip_families {
new_mtu, err := FindDefaultRouteMTU(ip_family)
if err != nil {
return nil, err
continue
}
mtu_slice = append(mtu_slice, new_mtu)
}
if len(mtu_slice) > 0 {
return slices.Min(mtu_slice), nil
}
return 0, fmt.Errorf("could not find minimal MTU")
}

func FindDefaultRouteMTU(ip_family int) (mtu int, err error) {
link, err := FindDefaultRouteIface(ip_family)
if err != nil && link.MTU == 0 {
return 0, err
}

klog.Infof("using IP %d on Interface %s with MTU %d ", ip_family, link.Name, link.MTU)

return link.MTU, nil
}

// Find the Default route Interface based on ipv4 or ipv6 routes.
func FindDefaultRouteIface(ip_family int) (iface *tcpnet.Interface, err error) {
parsedStruct, err := findDefaultRouteForFamily(ip_family)
if err != nil {
return nil, err
}

iface, err = tcpnet.InterfaceByName(parsedStruct.Iface)
Expand Down

0 comments on commit 864423c

Please sign in to comment.