diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index af2a35d13..bbe52183d 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -202,6 +202,9 @@ func (src *Metal3DataTemplate) ConvertTo(dstRaw conversion.Hub) error { for k := range dst.Spec.NetworkData.Networks.IPv6 { dst.Spec.NetworkData.Networks.IPv6[k].FromPoolRef = restored.Spec.NetworkData.Networks.IPv6[k].FromPoolRef } + for k := range dst.Spec.NetworkData.Links.Bonds { + dst.Spec.NetworkData.Links.Bonds[k].BondXmitHashPolicy = restored.Spec.NetworkData.Links.Bonds[k].BondXmitHashPolicy + } } return nil @@ -231,6 +234,10 @@ func Convert_v1beta1_FromPool_To_v1alpha5_FromPool(in *v1beta1.FromPool, out *Fr return autoConvert_v1beta1_FromPool_To_v1alpha5_FromPool(in, out, s) } +func Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in *v1beta1.NetworkDataLinkBond, out *NetworkDataLinkBond, s apiconversion.Scope) error { + return autoConvert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in, out, s) +} + func (src *Metal3DataTemplateList) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*v1beta1.Metal3DataTemplateList) return Convert_v1alpha5_Metal3DataTemplateList_To_v1beta1_Metal3DataTemplateList(src, dst, nil) diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 402d51543..949f2be6d 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -553,11 +553,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1beta1.NetworkDataLinkBond)(nil), (*NetworkDataLinkBond)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(a.(*v1beta1.NetworkDataLinkBond), b.(*NetworkDataLinkBond), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*NetworkDataLinkEthernet)(nil), (*v1beta1.NetworkDataLinkEthernet)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha5_NetworkDataLinkEthernet_To_v1beta1_NetworkDataLinkEthernet(a.(*NetworkDataLinkEthernet), b.(*v1beta1.NetworkDataLinkEthernet), scope) }); err != nil { @@ -703,6 +698,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta1.NetworkDataLinkBond)(nil), (*NetworkDataLinkBond)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(a.(*v1beta1.NetworkDataLinkBond), b.(*NetworkDataLinkBond), scope) + }); err != nil { + return err + } return nil } @@ -2209,7 +2209,17 @@ func Convert_v1beta1_NetworkDataIPv6DHCP_To_v1alpha5_NetworkDataIPv6DHCP(in *v1b func autoConvert_v1alpha5_NetworkDataLink_To_v1beta1_NetworkDataLink(in *NetworkDataLink, out *v1beta1.NetworkDataLink, s conversion.Scope) error { out.Ethernets = *(*[]v1beta1.NetworkDataLinkEthernet)(unsafe.Pointer(&in.Ethernets)) - out.Bonds = *(*[]v1beta1.NetworkDataLinkBond)(unsafe.Pointer(&in.Bonds)) + if in.Bonds != nil { + in, out := &in.Bonds, &out.Bonds + *out = make([]v1beta1.NetworkDataLinkBond, len(*in)) + for i := range *in { + if err := Convert_v1alpha5_NetworkDataLinkBond_To_v1beta1_NetworkDataLinkBond(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Bonds = nil + } out.Vlans = *(*[]v1beta1.NetworkDataLinkVlan)(unsafe.Pointer(&in.Vlans)) return nil } @@ -2221,7 +2231,17 @@ func Convert_v1alpha5_NetworkDataLink_To_v1beta1_NetworkDataLink(in *NetworkData func autoConvert_v1beta1_NetworkDataLink_To_v1alpha5_NetworkDataLink(in *v1beta1.NetworkDataLink, out *NetworkDataLink, s conversion.Scope) error { out.Ethernets = *(*[]NetworkDataLinkEthernet)(unsafe.Pointer(&in.Ethernets)) - out.Bonds = *(*[]NetworkDataLinkBond)(unsafe.Pointer(&in.Bonds)) + if in.Bonds != nil { + in, out := &in.Bonds, &out.Bonds + *out = make([]NetworkDataLinkBond, len(*in)) + for i := range *in { + if err := Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Bonds = nil + } out.Vlans = *(*[]NetworkDataLinkVlan)(unsafe.Pointer(&in.Vlans)) return nil } @@ -2247,6 +2267,7 @@ func Convert_v1alpha5_NetworkDataLinkBond_To_v1beta1_NetworkDataLinkBond(in *Net func autoConvert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in *v1beta1.NetworkDataLinkBond, out *NetworkDataLinkBond, s conversion.Scope) error { out.BondMode = in.BondMode + // WARNING: in.BondXmitHashPolicy requires manual conversion: does not exist in peer-type out.Id = in.Id out.MTU = in.MTU out.MACAddress = (*NetworkLinkEthernetMac)(unsafe.Pointer(in.MACAddress)) @@ -2254,11 +2275,6 @@ func autoConvert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in return nil } -// Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond is an autogenerated conversion function. -func Convert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in *v1beta1.NetworkDataLinkBond, out *NetworkDataLinkBond, s conversion.Scope) error { - return autoConvert_v1beta1_NetworkDataLinkBond_To_v1alpha5_NetworkDataLinkBond(in, out, s) -} - func autoConvert_v1alpha5_NetworkDataLinkEthernet_To_v1beta1_NetworkDataLinkEthernet(in *NetworkDataLinkEthernet, out *v1beta1.NetworkDataLinkEthernet, s conversion.Scope) error { out.Type = in.Type out.Id = in.Id diff --git a/api/v1beta1/metal3datatemplate_types.go b/api/v1beta1/metal3datatemplate_types.go index a83b74eb9..efd408189 100644 --- a/api/v1beta1/metal3datatemplate_types.go +++ b/api/v1beta1/metal3datatemplate_types.go @@ -231,6 +231,11 @@ type NetworkDataLinkBond struct { // balance-rr, active-backup, balance-xor, broadcast, balance-tlb, balance-alb, 802.3ad BondMode string `json:"bondMode"` + // +kubebuilder:validation:Enum="layer2";"layer3+4";"layer2+3" + // Selects the transmit hash policy used for port selection in balance-xor and 802.3ad modes + // +optional + BondXmitHashPolicy string `json:"bondXmitHashPolicy"` + // Id is the ID of the interface (used for naming) Id string `json:"id"` //nolint:revive,stylecheck @@ -245,6 +250,7 @@ type NetworkDataLinkBond struct { MACAddress *NetworkLinkEthernetMac `json:"macAddress"` // BondLinks is the list of links that are part of the bond. + // +optional BondLinks []string `json:"bondLinks"` } diff --git a/baremetal/metal3data_manager.go b/baremetal/metal3data_manager.go index 39dccb855..329de1e52 100644 --- a/baremetal/metal3data_manager.go +++ b/baremetal/metal3data_manager.go @@ -981,33 +981,34 @@ func renderNetworkServices(services infrav1.NetworkDataService, poolAddresses ma func renderNetworkLinks(networkLinks infrav1.NetworkDataLink, bmh *bmov1alpha1.BareMetalHost) ([]interface{}, error) { data := []interface{}{} - // Ethernet links - for _, link := range networkLinks.Ethernets { + // Bond links + for _, link := range networkLinks.Bonds { macAddress, err := getLinkMacAddress(link.MACAddress, bmh) if err != nil { return nil, err } data = append(data, map[string]interface{}{ - "type": link.Type, - "id": link.Id, - "mtu": link.MTU, - "ethernet_mac_address": macAddress, + "type": "bond", + "id": link.Id, + "mtu": link.MTU, + "ethernet_mac_address": macAddress, + "bond_mode": link.BondMode, + "bond_xmit_hash_policy": link.BondXmitHashPolicy, + "bond_links": link.BondLinks, }) } - // Bond links - for _, link := range networkLinks.Bonds { + // Ethernet links + for _, link := range networkLinks.Ethernets { macAddress, err := getLinkMacAddress(link.MACAddress, bmh) if err != nil { return nil, err } data = append(data, map[string]interface{}{ - "type": "bond", + "type": link.Type, "id": link.Id, "mtu": link.MTU, "ethernet_mac_address": macAddress, - "bond_mode": link.BondMode, - "bond_links": link.BondLinks, }) } diff --git a/baremetal/metal3data_manager_test.go b/baremetal/metal3data_manager_test.go index b45d05394..748e8ef72 100644 --- a/baremetal/metal3data_manager_test.go +++ b/baremetal/metal3data_manager_test.go @@ -2259,9 +2259,10 @@ var _ = Describe("Metal3Data manager", func() { links: infrav1.NetworkDataLink{ Bonds: []infrav1.NetworkDataLinkBond{ { - BondMode: "802.3ad", - Id: "bond0", - MTU: 1500, + BondMode: "802.3ad", + BondXmitHashPolicy: "layer3+4", + Id: "bond0", + MTU: 1500, MACAddress: &infrav1.NetworkLinkEthernetMac{ String: pointer.String("XX:XX:XX:XX:XX:XX"), }, @@ -2271,12 +2272,13 @@ var _ = Describe("Metal3Data manager", func() { }, expectedOutput: []interface{}{ map[string]interface{}{ - "type": "bond", - "id": "bond0", - "mtu": 1500, - "ethernet_mac_address": "XX:XX:XX:XX:XX:XX", - "bond_mode": "802.3ad", - "bond_links": []string{"eth0"}, + "type": "bond", + "id": "bond0", + "mtu": 1500, + "ethernet_mac_address": "XX:XX:XX:XX:XX:XX", + "bond_mode": "802.3ad", + "bond_xmit_hash_policy": "layer3+4", + "bond_links": []string{"eth0"}, }, }, }), diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3datatemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3datatemplates.yaml index c577ab0db..5967075e6 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3datatemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3datatemplates.yaml @@ -1196,6 +1196,14 @@ spec: - balance-alb - 802.3ad type: string + bondXmitHashPolicy: + description: Selects the transmit hash policy used for + port selection in balance-xor and 802.3ad modes + enum: + - layer2 + - layer3+4 + - layer2+3 + type: string id: description: Id is the ID of the interface (used for naming) @@ -1220,7 +1228,6 @@ spec: maximum: 9000 type: integer required: - - bondLinks - bondMode - id - macAddress