Skip to content

Commit c7f30ed

Browse files
committed
fix pod mac may conflict with gateway mac
Signed-off-by: clyi <clyi@alauda.io>
1 parent 6f623e9 commit c7f30ed

6 files changed

Lines changed: 74 additions & 1 deletion

File tree

pkg/controller/subnet.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,18 @@ func (c *Controller) handleAddOrUpdateSubnet(key string) error {
705705
}
706706
}
707707

708+
// Record the gateway MAC in ipam if router port exists
709+
if needRouter {
710+
routerPortName := ovs.LogicalRouterPortName(vpc.Status.Router, subnet.Name)
711+
if mac, err := c.ovnClient.GetLogicalRouterPortMAC(routerPortName); err == nil {
712+
if err := c.ipam.RecordGatewayMAC(subnet.Name, mac); err != nil {
713+
klog.Warningf("failed to record gateway MAC %s for subnet %s: %v", mac, subnet.Name, err)
714+
}
715+
} else {
716+
klog.V(3).Infof("router port %s not found or has no MAC, skipping gateway MAC record", routerPortName)
717+
}
718+
}
719+
708720
var mtu int
709721
if subnet.Spec.Mtu > 0 {
710722
mtu = int(subnet.Spec.Mtu)

pkg/ipam/ipam.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,17 @@ func (ipam *IPAM) GetSubnetV4Mask(subnetName string) (string, error) {
277277
return "", ErrNoAvailable
278278
}
279279
}
280+
281+
func (ipam *IPAM) RecordGatewayMAC(subnetName, gatewayMAC string) error {
282+
ipam.mutex.Lock()
283+
defer ipam.mutex.Unlock()
284+
285+
subnet, ok := ipam.Subnets[subnetName]
286+
if !ok {
287+
return fmt.Errorf("subnet %s not found in ipam", subnetName)
288+
}
289+
290+
subnet.GatewayMAC = gatewayMAC
291+
klog.Infof("recorded gateway MAC %s for subnet %s", gatewayMAC, subnetName)
292+
return nil
293+
}

pkg/ipam/subnet.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Subnet struct {
3333
PodToNicList map[string][]string
3434
V4Gw string
3535
V6Gw string
36+
GatewayMAC string
3637
}
3738

3839
func NewSubnet(name, cidrStr string, excludeIps []string) (*Subnet, error) {
@@ -72,6 +73,7 @@ func NewSubnet(name, cidrStr string, excludeIps []string) (*Subnet, error) {
7273
MacToPod: map[string]string{},
7374
NicToMac: map[string]string{},
7475
PodToNicList: map[string][]string{},
76+
GatewayMAC: "",
7577
}
7678
subnet.joinFreeWithReserve()
7779
} else if protocol == kubeovnv1.ProtocolIPv6 {
@@ -93,6 +95,7 @@ func NewSubnet(name, cidrStr string, excludeIps []string) (*Subnet, error) {
9395
MacToPod: map[string]string{},
9496
NicToMac: map[string]string{},
9597
PodToNicList: map[string][]string{},
98+
GatewayMAC: "",
9699
}
97100
subnet.joinFreeWithReserve()
98101
} else {
@@ -121,6 +124,7 @@ func NewSubnet(name, cidrStr string, excludeIps []string) (*Subnet, error) {
121124
MacToPod: map[string]string{},
122125
NicToMac: map[string]string{},
123126
PodToNicList: map[string][]string{},
127+
GatewayMAC: "",
124128
}
125129
subnet.joinFreeWithReserve()
126130
}
@@ -132,7 +136,7 @@ func (subnet *Subnet) GetRandomMac(podName, nicName string) string {
132136
return mac
133137
}
134138
for {
135-
mac := util.GenerateMac()
139+
mac := util.GenerateMacWithExclusion([]string{subnet.GatewayMAC})
136140
if _, ok := subnet.MacToPod[mac]; !ok {
137141
subnet.MacToPod[mac] = podName
138142
subnet.NicToMac[nicName] = mac
@@ -142,6 +146,11 @@ func (subnet *Subnet) GetRandomMac(podName, nicName string) string {
142146
}
143147

144148
func (subnet *Subnet) GetStaticMac(podName, nicName, mac string, checkConflict bool) error {
149+
if subnet.GatewayMAC != "" && mac == subnet.GatewayMAC {
150+
klog.Errorf("mac %s conflicts with gateway MAC %s", mac, subnet.GatewayMAC)
151+
return ErrConflict
152+
}
153+
145154
if checkConflict {
146155
if p, ok := subnet.MacToPod[mac]; ok && p != podName {
147156
klog.Errorf("mac %s has been allocated to pod %s", mac, p)

pkg/ovs/ovn-nb-logical_router_port.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,16 @@ func (c OvnClient) LogicalRouterPortExists(name string) (bool, error) {
8282
lrp, err := c.GetLogicalRouterPort(name, true)
8383
return lrp != nil, err
8484
}
85+
86+
func (c OvnClient) GetLogicalRouterPortMAC(name string) (string, error) {
87+
lrp, err := c.GetLogicalRouterPort(name, false)
88+
if err != nil {
89+
return "", fmt.Errorf("failed to get logical router port %s: %v", name, err)
90+
}
91+
92+
if lrp == nil {
93+
return "", fmt.Errorf("logical router port %s not found", name)
94+
}
95+
96+
return lrp.MAC, nil
97+
}

pkg/ovs/ovn-nbctl-legacy.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,21 @@ func (c LegacyClient) DeleteLogicalRouterPort(port string) error {
136136
return nil
137137
}
138138

139+
// GetLogicalRouterPortMAC get logical router port mac address
140+
func (c LegacyClient) GetLogicalRouterPortMAC(port string) (string, error) {
141+
output, err := c.ovnNbCommand("--data=bare", "--no-heading", "--columns=mac", "find", "logical_router_port", fmt.Sprintf("name=%s", port))
142+
if err != nil {
143+
return "", fmt.Errorf("failed to get logical router port %s mac: %v", port, err)
144+
}
145+
146+
mac := strings.TrimSpace(output)
147+
if mac == "" {
148+
return "", fmt.Errorf("logical router port %s not found or has no mac address", port)
149+
}
150+
151+
return mac, nil
152+
}
153+
139154
func (c LegacyClient) CreateICLogicalRouterPort(az, ts, mac, subnet string, chassises []string) error {
140155
lspName := fmt.Sprintf("%s-%s", ts, az)
141156
lrpName := fmt.Sprintf("%s-%s", az, ts)

pkg/util/net.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"math"
88
"math/big"
99
"net"
10+
"slices"
1011
"strconv"
1112
"strings"
1213
"time"
@@ -46,6 +47,15 @@ func GenerateMac() string {
4647
return net.HardwareAddr(buf).String()
4748
}
4849

50+
func GenerateMacWithExclusion(exclusionMACs []string) string {
51+
for {
52+
mac := GenerateMac()
53+
if !slices.Contains(exclusionMACs, mac) {
54+
return mac
55+
}
56+
}
57+
}
58+
4959
func Ip2BigInt(ipStr string) *big.Int {
5060
ipBigInt := big.NewInt(0)
5161
if CheckProtocol(ipStr) == kubeovnv1.ProtocolIPv4 {

0 commit comments

Comments
 (0)