diff --git a/pkg/admission/webhook/workload.go b/pkg/admission/webhook/workload.go index 9453dbf..d412e4d 100644 --- a/pkg/admission/webhook/workload.go +++ b/pkg/admission/webhook/workload.go @@ -285,7 +285,7 @@ func checkMACsIsInUsed(macs []net.HardwareAddr, subnet *flv1.FlatNetworkSubnet) for _, m := range macs { s := m.String() for _, um := range subnet.Status.UsedMAC { - if um.String() == s { + if um == s { return fmt.Errorf("mac %v is already in use", s) } } diff --git a/pkg/apis/flatnetwork.pandaria.io/v1/types.go b/pkg/apis/flatnetwork.pandaria.io/v1/types.go index 945bdd8..35ed3b0 100644 --- a/pkg/apis/flatnetwork.pandaria.io/v1/types.go +++ b/pkg/apis/flatnetwork.pandaria.io/v1/types.go @@ -55,7 +55,7 @@ type IPSpec struct { Addrs []net.IP `json:"addrs"` // MACs is the user specified MAC addresses (optional). - MACs []net.HardwareAddr `json:"macs"` + MACs []string `json:"macs"` // PodID is the Pod metadata.UID PodID string `json:"podId"` @@ -70,7 +70,7 @@ type IPStatus struct { // MAC is actual allocated MAC address by CNI // can be random in auto mode, or specidied by user. - MAC net.HardwareAddr `json:"mac"` + MAC string `json:"mac"` } //////////////////// @@ -131,7 +131,7 @@ type SubnetStatus struct { UsedIPCount int `json:"usedIPCount"` // UsedMAC is the **USER SPECIFIED** used MAC address. - UsedMAC []net.HardwareAddr `json:"usedMac"` + UsedMAC []string `json:"usedMac"` } // Example: ip route add dev via src metrics diff --git a/pkg/apis/flatnetwork.pandaria.io/v1/zz_generated_deepcopy.go b/pkg/apis/flatnetwork.pandaria.io/v1/zz_generated_deepcopy.go index 3527aa4..a13f5c1 100644 --- a/pkg/apis/flatnetwork.pandaria.io/v1/zz_generated_deepcopy.go +++ b/pkg/apis/flatnetwork.pandaria.io/v1/zz_generated_deepcopy.go @@ -191,14 +191,8 @@ func (in *IPSpec) DeepCopyInto(out *IPSpec) { } if in.MACs != nil { in, out := &in.MACs, &out.MACs - *out = make([]net.HardwareAddr, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = make(net.HardwareAddr, len(*in)) - copy(*out, *in) - } - } + *out = make([]string, len(*in)) + copy(*out, *in) } return } @@ -221,11 +215,6 @@ func (in *IPStatus) DeepCopyInto(out *IPStatus) { *out = make(net.IP, len(*in)) copy(*out, *in) } - if in.MAC != nil { - in, out := &in.MAC, &out.MAC - *out = make(net.HardwareAddr, len(*in)) - copy(*out, *in) - } return } @@ -334,14 +323,8 @@ func (in *SubnetStatus) DeepCopyInto(out *SubnetStatus) { } if in.UsedMAC != nil { in, out := &in.UsedMAC, &out.UsedMAC - *out = make([]net.HardwareAddr, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = make(net.HardwareAddr, len(*in)) - copy(*out, *in) - } - } + *out = make([]string, len(*in)) + copy(*out, *in) } return } diff --git a/pkg/cni/commands/add.go b/pkg/cni/commands/add.go index 81aea48..cef2ea5 100644 --- a/pkg/cni/commands/add.go +++ b/pkg/cni/commands/add.go @@ -179,11 +179,7 @@ func Add(args *skel.CmdArgs) error { } flatNetworkIP = flatNetworkIP.DeepCopy() - flatNetworkIP.Status.MAC, err = net.ParseMAC(iface.Mac) - if err != nil { - logrus.Errorf("failed to parse created iface MAC address: %v", err) - return err - } + flatNetworkIP.Status.MAC = iface.Mac flatNetworkIP, err = client.UpdateIPStatus(context.TODO(), podNamespace, flatNetworkIP) return err }); err != nil { @@ -197,7 +193,7 @@ func Add(args *skel.CmdArgs) error { return err } logrus.Infof("update flatNetwork IP status MAC [%v]", - flatNetworkIP.Status.MAC.String()) + flatNetworkIP.Status.MAC) // Delete link if err to avoid link leak in this ns defer func() { diff --git a/pkg/cni/ipvlan/ipvlan.go b/pkg/cni/ipvlan/ipvlan.go index 75fceb6..02b8dd9 100644 --- a/pkg/cni/ipvlan/ipvlan.go +++ b/pkg/cni/ipvlan/ipvlan.go @@ -18,7 +18,7 @@ type Options struct { MTU int IfName string NetNS ns.NetNS - MAC net.HardwareAddr + MAC string } func Create(o *Options) (*types100.Interface, error) { @@ -39,21 +39,27 @@ func Create(o *Options) (*types100.Interface, error) { if err != nil { return nil, err } - + var mac net.HardwareAddr + if o.MAC != "" { + mac, err = net.ParseMAC(o.MAC) + if err != nil { + return nil, fmt.Errorf("failed to parse MAC %q: %w", o.MAC, err) + } + } iv := &netlink.IPVlan{ LinkAttrs: netlink.LinkAttrs{ - MTU: o.MTU, - Name: tmpName, - ParentIndex: m.Attrs().Index, - Namespace: netlink.NsFd(int(o.NetNS.Fd())), + MTU: o.MTU, + Name: tmpName, + ParentIndex: m.Attrs().Index, + Namespace: netlink.NsFd(int(o.NetNS.Fd())), + HardwareAddr: mac, }, Mode: mode, } - if err := netlink.LinkAdd(iv); err != nil { return nil, fmt.Errorf("failed to create ipvlan: %v", err) } - + logrus.Debugf("created ipvlan iface: %v", utils.Print(iv)) var result *types100.Interface if err := o.NetNS.Do(func(_ ns.NetNS) error { err := ip.RenameLink(tmpName, o.IfName) diff --git a/pkg/cni/macvlan/macvlan.go b/pkg/cni/macvlan/macvlan.go index 172222f..7913094 100644 --- a/pkg/cni/macvlan/macvlan.go +++ b/pkg/cni/macvlan/macvlan.go @@ -18,7 +18,7 @@ type Options struct { MTU int IfName string NetNS ns.NetNS - MAC net.HardwareAddr + MAC string } func Create(o *Options) (*types100.Interface, error) { @@ -38,13 +38,20 @@ func Create(o *Options) (*types100.Interface, error) { if err != nil { return nil, err } + var mac net.HardwareAddr + if o.MAC != "" { + mac, err = net.ParseMAC(o.MAC) + if err != nil { + return nil, fmt.Errorf("failed to parse MAC %q: %w", o.MAC, err) + } + } mv := &netlink.Macvlan{ LinkAttrs: netlink.LinkAttrs{ MTU: o.MTU, Name: tmpName, ParentIndex: master.Attrs().Index, Namespace: netlink.NsFd(int(o.NetNS.Fd())), - HardwareAddr: o.MAC, + HardwareAddr: mac, }, Mode: mode, } diff --git a/pkg/controller/flatnetworkip/flatnetworkip.go b/pkg/controller/flatnetworkip/flatnetworkip.go index f112527..837261f 100644 --- a/pkg/controller/flatnetworkip/flatnetworkip.go +++ b/pkg/controller/flatnetworkip/flatnetworkip.go @@ -3,7 +3,6 @@ package flatnetworkip import ( "context" "fmt" - "net" "slices" "sync" "time" @@ -200,8 +199,9 @@ func (h *handler) onIPCreate(ip *flv1.FlatNetworkIP) (*flv1.FlatNetworkIP, error result = result.DeepCopy() result.Status.UsedIP = ipcalc.AddIPToRange(allocatedIP, result.Status.UsedIP) result.Status.UsedIPCount++ - if allocatedMAC != nil { + if allocatedMAC != "" { result.Status.UsedMAC = append(result.Status.UsedMAC, allocatedMAC) + slices.Sort(result.Status.UsedMAC) } result, err = h.subnetClient.UpdateStatus(result) if err != nil { @@ -241,8 +241,8 @@ func (h *handler) onIPCreate(ip *flv1.FlatNetworkIP) (*flv1.FlatNetworkIP, error subnet.Status.UsedIP = ipcalc.RemoveIPFromRange(allocatedIP, subnet.Status.UsedIP) subnet.Status.UsedIPCount-- if len(allocatedMAC) != 0 && len(subnet.Status.UsedMAC) != 0 { - subnet.Status.UsedMAC = slices.DeleteFunc(subnet.Status.UsedMAC, func(a net.HardwareAddr) bool { - return a.String() == allocatedIP.String() + subnet.Status.UsedMAC = slices.DeleteFunc(subnet.Status.UsedMAC, func(s string) bool { + return s == allocatedMAC }) } subnet, err = h.subnetClient.UpdateStatus(subnet) @@ -255,7 +255,7 @@ func (h *handler) onIPCreate(ip *flv1.FlatNetworkIP) (*flv1.FlatNetworkIP, error ip.Namespace, ip.Name, err) } - macString := ip.Status.MAC.String() + macString := ip.Status.MAC if macString == "" { macString = flv1.AllocateModeAuto } diff --git a/pkg/controller/flatnetworkip/flatnetworkip_test.go b/pkg/controller/flatnetworkip/flatnetworkip_test.go index 6085900..e4522d7 100644 --- a/pkg/controller/flatnetworkip/flatnetworkip_test.go +++ b/pkg/controller/flatnetworkip/flatnetworkip_test.go @@ -184,7 +184,7 @@ func Test_allocateIP(t *testing.T) { func Test_alreadyAllocatedMAC(t *testing.T) { ip := &flv1.FlatNetworkIP{ Spec: flv1.IPSpec{ - MACs: []net.HardwareAddr{}, + MACs: []string{}, }, Status: flv1.IPStatus{}, } diff --git a/pkg/controller/flatnetworkip/mac.go b/pkg/controller/flatnetworkip/mac.go index 060f073..0049d69 100644 --- a/pkg/controller/flatnetworkip/mac.go +++ b/pkg/controller/flatnetworkip/mac.go @@ -1,9 +1,7 @@ package flatnetworkip import ( - "bytes" "fmt" - "net" "slices" flv1 "github.com/cnrancher/rancher-flat-network/pkg/apis/flatnetwork.pandaria.io/v1" @@ -21,9 +19,9 @@ func alreadyAllocatedMAC(ip *flv1.FlatNetworkIP) bool { if len(ip.Status.MAC) == 0 { return len(ip.Spec.MACs) == 0 } - allocatedMAC := ip.Status.MAC.String() + allocatedMAC := ip.Status.MAC for _, m := range ip.Spec.MACs { - if m.String() == allocatedMAC { + if m == allocatedMAC { return true } } @@ -32,10 +30,10 @@ func alreadyAllocatedMAC(ip *flv1.FlatNetworkIP) bool { func allocateMAC( ip *flv1.FlatNetworkIP, subnet *flv1.FlatNetworkSubnet, -) (net.HardwareAddr, error) { +) (string, error) { if len(ip.Spec.MACs) == 0 { // User does not specify custom MAC address, return directly. - return nil, nil + return "", nil } if alreadyAllocatedMAC(ip) { return ip.Status.MAC, nil @@ -43,14 +41,12 @@ func allocateMAC( // Use custom MAC from multiple addresses. for _, m := range ip.Spec.MACs { - _, ok := slices.BinarySearchFunc(subnet.Status.UsedMAC, m, func(a, b net.HardwareAddr) int { - return bytes.Compare(a, b) - }) + _, ok := slices.BinarySearch(subnet.Status.UsedMAC, m) if !ok { // Select the unused mac address from multi-mac addresses. return m, nil } } - return nil, fmt.Errorf("allocateMAC: no available MAC address from MACs %v: %w", + return "", fmt.Errorf("allocateMAC: no available MAC address from MACs %v: %w", ip.Spec.MACs, ipcalc.ErrNoAvailableMac) } diff --git a/pkg/controller/flatnetworkip/remove.go b/pkg/controller/flatnetworkip/remove.go index c328e1f..8931ff6 100644 --- a/pkg/controller/flatnetworkip/remove.go +++ b/pkg/controller/flatnetworkip/remove.go @@ -1,9 +1,7 @@ package flatnetworkip import ( - "bytes" "fmt" - "net" "slices" "time" @@ -66,9 +64,10 @@ func (h *handler) handleIPRemove(_ string, ip *flv1.FlatNetworkIP) (*flv1.FlatNe result.Status.UsedIP = ipcalc.RemoveIPFromRange(ip.Status.Addr, result.Status.UsedIP) result.Status.UsedIPCount-- if len(ip.Status.MAC) != 0 { - result.Status.UsedMAC = slices.DeleteFunc(result.Status.UsedMAC, func(m net.HardwareAddr) bool { - return bytes.Equal(m, ip.Status.MAC) + result.Status.UsedMAC = slices.DeleteFunc(result.Status.UsedMAC, func(m string) bool { + return m == ip.Status.MAC }) + slices.Sort(result.Status.UsedMAC) } _, err = h.subnetClient.UpdateStatus(result) return err @@ -77,7 +76,7 @@ func (h *handler) handleIPRemove(_ string, ip *flv1.FlatNetworkIP) (*flv1.FlatNe logrus.WithFields(fieldsIP(ip)). Errorf("failed to remove usedIP & usedMAC from subnet: %v", err) } - if ip.Status.MAC != nil { + if ip.Status.MAC != "" { logrus.WithFields(fieldsIP(ip)). Infof("remove IP [%v] MAC [%v] from subnet [%v]", ip.Status.Addr, ip.Status.MAC, ip.Spec.Subnet) diff --git a/pkg/controller/pod/pod.go b/pkg/controller/pod/pod.go index 33c478a..e915bae 100644 --- a/pkg/controller/pod/pod.go +++ b/pkg/controller/pod/pod.go @@ -183,8 +183,8 @@ func (h *handler) updatePodLabel(pod *corev1.Pod, ip *flv1.FlatNetworkIP) error s := ip.Status.Addr.String() labels[flv1.LabelSelectedIP] = strings.ReplaceAll(s, ":", ".") } - if ip.Status.MAC != nil && annotationMac != "" { - labels[flv1.LabelSelectedMac] = strings.ReplaceAll(ip.Status.MAC.String(), ":", "_") + if ip.Status.MAC != "" && annotationMac != "" { + labels[flv1.LabelSelectedMac] = strings.ReplaceAll(ip.Status.MAC, ":", "") } if annotationIP == flv1.AllocateModeAuto { labels[flv1.LabelFlatNetworkIPType] = flv1.AllocateModeAuto diff --git a/pkg/controller/pod/utils.go b/pkg/controller/pod/utils.go index 53e639a..220b7f7 100644 --- a/pkg/controller/pod/utils.go +++ b/pkg/controller/pod/utils.go @@ -23,7 +23,7 @@ func (h *handler) newFlatNetworkIP(pod *corev1.Pod) (*flv1.FlatNetworkIP, error) var ( ipAddrs []net.IP - macAddrs []net.HardwareAddr + macAddrs []string ) switch annotationIP { case flv1.AllocateModeAuto: @@ -47,7 +47,7 @@ func (h *handler) newFlatNetworkIP(pod *corev1.Pod) (*flv1.FlatNetworkIP, error) return nil, fmt.Errorf("newFlatNetworkIP: invalid annotation [%v: %v]", flv1.AnnotationMac, annotationMAC) } - macAddrs = append(macAddrs, a) + macAddrs = append(macAddrs, a.String()) } } subnet, err := h.subnetCache.Get(flv1.SubnetNamespace, annotationSubnet)