Skip to content

Commit

Permalink
Sync MTU and check MTU valid values
Browse files Browse the repository at this point in the history
Signed-off-by: Jian Wang <jian.wang@suse.com>
  • Loading branch information
w13915984028 committed Sep 11, 2024
1 parent 9892fc1 commit b4cf3fd
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 7 deletions.
59 changes: 58 additions & 1 deletion pkg/controller/manager/nad/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import (
ctlcniv1 "github.com/harvester/harvester/pkg/generated/controllers/k8s.cni.cncf.io/v1"
cniv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
ctlbatchv1 "github.com/rancher/wrangler/pkg/generated/controllers/batch/v1"
"github.com/tidwall/sjson"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog/v2"

"github.com/harvester/harvester-network-controller/pkg/apis/network.harvesterhci.io"
Expand Down Expand Up @@ -89,10 +91,65 @@ func Register(ctx context.Context, management *config.Management) error {

nads.OnChange(ctx, ControllerName, handler.OnChange)
nads.OnRemove(ctx, ControllerName, handler.OnRemove)

cns.OnChange(ctx, ControllerName, handler.OnCNChange)
return nil
}

func (h Handler) OnCNChange(_ string, cn *networkv1.ClusterNetwork) (*networkv1.ClusterNetwork, error) {
if cn == nil || cn.DeletionTimestamp != nil {
return nil, nil
}

// MTU label is not set
curLbMTU := cn.Labels[utils.KeyUplinkMTU]
if curLbMTU == "" {
return nil, nil
}
MTU, err := strconv.Atoi(curLbMTU)
if err != nil {
return nil, fmt.Errorf("cluster network %v has an invalid label %v/%v, error %w", cn.Name, utils.KeyUplinkMTU, curLbMTU, err)
}
// skip
if MTU <= 0 {
klog.Infof("cluster network %v has an unexpected label %v/%v, skip to sync with nad", cn.Name, utils.KeyUplinkMTU, curLbMTU)
return nil, nil
}

nads, err := h.nadCache.List("", labels.Set(map[string]string{
utils.KeyClusterNetworkLabel: cn.Name,
}).AsSelector())
if err != nil {
return nil, fmt.Errorf("failed to list cluster network %v related nads, error %w", cn.Name, err)
}

// sync with the possible new MTU
for _, nad := range nads {
netConf := &utils.NetConf{}
if err := json.Unmarshal([]byte(nad.Spec.Config), netConf); err != nil {
return nil, fmt.Errorf("failed to Unmarshal nad %v config %v error %w", nad.Name, nad.Spec.Config, err)
}

// default value or equal
if (MTU == utils.MTUDefault && netConf.MTU == 0) || MTU == netConf.MTU {
continue
}

// Don't modify the unmarshalled structure and marshal it again because some fields may be lost during unmarshalling.
newConfig, err := sjson.Set(nad.Spec.Config, "mtu", MTU)
if err != nil {
return nil, fmt.Errorf("failed to set nad %v with new MTU %v error %w", nad.Name, MTU, err)
}
nadCopy := nad.DeepCopy()
nadCopy.Spec.Config = newConfig
if _, err := h.nadClient.Update(nadCopy); err != nil {
return nil, err
}
klog.Infof("sync cluster network %v label mtu %v/%v to nad %v", cn.Name, utils.KeyUplinkMTU, curLbMTU, nad.Name)
}

return nil, nil
}

func (h Handler) OnChange(_ string, nad *cniv1.NetworkAttachmentDefinition) (*cniv1.NetworkAttachmentDefinition, error) {
if nad == nil || nad.DeletionTimestamp != nil {
return nil, nil
Expand Down
41 changes: 36 additions & 5 deletions pkg/controller/manager/vlanconfig/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (h Handler) EnsureClusterNetwork(_ string, vc *networkv1.VlanConfig) (*netw

klog.Infof("vlan config %s has been changed, spec: %+v", vc.Name, vc.Spec)

if err := h.ensureClusterNetwork(vc.Spec.ClusterNetwork); err != nil {
if err := h.ensureClusterNetwork(vc); err != nil {
return nil, err
}
return vc, nil
Expand Down Expand Up @@ -83,16 +83,47 @@ func (h Handler) SetClusterNetworkUnready(_ string, vs *networkv1.VlanStatus) (*
return vs, nil
}

func (h Handler) ensureClusterNetwork(name string) error {
if _, err := h.cnCache.Get(name); err != nil && !apierrors.IsNotFound(err) {
func (h Handler) ensureClusterNetwork(vc *networkv1.VlanConfig) error {
name := vc.Spec.ClusterNetwork
curCn, err := h.cnCache.Get(name)
if err != nil && !apierrors.IsNotFound(err) {
return err
} else if err == nil {
}

MTU := utils.MTUDefault
if vc.Spec.Uplink.LinkAttrs.MTU != 0 && MTU != vc.Spec.Uplink.LinkAttrs.MTU {
MTU = vc.Spec.Uplink.LinkAttrs.MTU
}
targetLbMTU := fmt.Sprintf("%v", MTU)

// check if the configured VC MTU value is updated to ClusterNetwork label
if curCn != nil {
curLbMTU := curCn.Labels[utils.KeyUplinkMTU]
if curLbMTU == targetLbMTU {
return nil
}
// update the new MTU
cnCopy := curCn.DeepCopy()
if cnCopy.Labels == nil {
cnCopy.Labels = make(map[string]string, 2)
}
cnCopy.Labels[utils.KeyUplinkMTU] = targetLbMTU
cnCopy.Labels[utils.KeyMTUSourceVlanConfig] = vc.Name
if _, err := h.cnClient.Update(cnCopy); err != nil {
return fmt.Errorf("failed to update cluster network %s label %s with MTU %s error %w", name, utils.KeyUplinkMTU, targetLbMTU, err)
}
return nil
}

// if cn is not existing
cn := &networkv1.ClusterNetwork{
ObjectMeta: metav1.ObjectMeta{Name: name},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
utils.KeyUplinkMTU: targetLbMTU,
utils.KeyMTUSourceVlanConfig: vc.Name,
},
},
}
if _, err := h.cnClient.Create(cn); err != nil {
return err
Expand Down
7 changes: 7 additions & 0 deletions pkg/utils/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package utils

const (
MTUDefault = 1500
MTUMax = 9000
MTUMin = 1280 // IPv4 does not define; IPv6 requires >= 1280
)
2 changes: 2 additions & 0 deletions pkg/utils/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const (
KeyLastNetworkType = network.GroupName + "/last-type"
KeyNetworkReady = network.GroupName + "/ready"
KeyNetworkRoute = network.GroupName + "/route"
KeyMTUSourceVlanConfig = network.GroupName + "/mtu-source-vc" // the VC which syncs MTU to CN
KeyUplinkMTU = network.GroupName + "/uplink-mtu" // configured MTU on the VC'uplink

KeyMatchedNodes = network.GroupName + "/matched-nodes"

Expand Down
7 changes: 6 additions & 1 deletion pkg/webhook/vlanconfig/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,14 @@ func (v *Validator) validateMTU(current *networkv1.VlanConfig) error {
continue
}
if current.Spec.Uplink.LinkAttrs.MTU != vc.Spec.Uplink.LinkAttrs.MTU {
return fmt.Errorf("the MTU is different from network config %s", vc.Name)
return fmt.Errorf("the MTU %v is different from network config %s %v", current.Spec.Uplink.LinkAttrs.MTU, vc.Name, vc.Spec.Uplink.LinkAttrs.MTU)
}
}

// MTU can be 0, it means user does not input it and the default value is used
if (current.Spec.Uplink.LinkAttrs.MTU < utils.MTUMin && current.Spec.Uplink.LinkAttrs.MTU != 0) || current.Spec.Uplink.LinkAttrs.MTU > utils.MTUMax {
return fmt.Errorf("the MTU %v is out of range [0, %v..%v]", current.Spec.Uplink.LinkAttrs.MTU, utils.MTUMin, utils.MTUMax)
}

return nil
}

0 comments on commit b4cf3fd

Please sign in to comment.