Skip to content

Commit 48724b1

Browse files
committed
fix: remove ip from uplink even if it already exist on the bridge
in case someone re-add the ip to the uplink the controller should remove the ip even if it's already exist on the bridge Signed-off-by: Michael Filanov <[email protected]>
1 parent 021636c commit 48724b1

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

internal/controller/ovs_ipaddress_controller.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,25 +154,24 @@ func (r *OvsIPaddressReconciler) processRailDeviceMapping(ctx context.Context, m
154154

155155
// Extract the full CIDR (IP + subnet mask)
156156
railCIDR := railAddrs[0].String()
157+
// Ensure railCIDR is correctly formatted (strip unwanted text)
158+
railCIDR = strings.Fields(railCIDR)[0] // Keep only the IP/CIDR part
157159
railIP := railAddrs[0].IP.String()
158160
logr.Info("Rail IP with subnet", "rail", rail, "dev", railDevice, "CIDR", railCIDR)
159161

160162
// Ensure the bridge has the rail IP (with subnet) and move it from railDevice if needed
161163
if _, exists := bridgeIPSet[railIP]; !exists {
162-
// Ensure railCIDR is correctly formatted (strip unwanted text)
163-
railCIDR = strings.Fields(railCIDR)[0] // Keep only the IP/CIDR part
164-
165164
logr.Info("Moving rail IP to bridge", "rail", rail, "dev", railDevice, "IP", railCIDR, "bridge", bridgeInternalIfc)
166165

167166
// Add railIP (with original subnet mask) to the bridge interface
168167
if err := r.addIPToInterface(bridgeInternalIfc, railCIDR); err != nil {
169168
return fmt.Errorf("failed to add rail IP %s to OVS bridge interface %s: %w", railCIDR, bridgeInternalIfc, err)
170169
}
170+
}
171171

172-
// Remove railIP (with original subnet mask) from the physical railDevice
173-
if err := r.removeIPFromInterface(railDevice, railCIDR); err != nil {
174-
return fmt.Errorf("failed to remove rail IP %s from physical port %s: %w", railCIDR, railDevice, err)
175-
}
172+
// Remove railIP (with original subnet mask) from the physical railDevice
173+
if err := r.removeIPFromInterface(railDevice, railCIDR); err != nil {
174+
return fmt.Errorf("failed to remove rail IP %s from physical port %s: %w", railCIDR, railDevice, err)
176175
}
177176

178177
return nil

internal/controller/ovs_ipaddress_controller_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,42 @@ var _ = Describe("OvsIPaddressReconciler", func() {
135135
Expect(err).To(BeNil())
136136
Expect(result).To(Equal(ctrl.Result{}))
137137
})
138+
It("should succeed reconcile - ip already exists on the bridge", func() {
139+
By("Reconciling the created config map with valid json")
140+
updateConfigMap(ctx, ns.Name, validConfig())
141+
// Port 1
142+
eth0Link := &netlink.Dummy{}
143+
internalLink1 := &netlink.Dummy{}
144+
mockExec.EXPECT().Execute("ovs-vsctl port-to-br eth0").Return("br-0000_08_00.1", nil)
145+
mockNetlink.EXPECT().LinkByName("br-0000_08_00.1").Return(internalLink1, nil).AnyTimes()
146+
mockNetlink.EXPECT().IsLinkAdminStateUp(internalLink1).Return(false)
147+
mockNetlink.EXPECT().LinkSetUp(internalLink1).Return(nil)
148+
By("ip already exists on the bridge and need to be removed from the physical port")
149+
eth0Addr := netlink.Addr{IPNet: &net.IPNet{IP: net.ParseIP("172.0.0.2"), Mask: net.CIDRMask(24, 32)}}
150+
mockNetlink.EXPECT().IPv4Addresses(internalLink1).Return([]netlink.Addr{eth0Addr}, nil)
151+
mockNetlink.EXPECT().AddrAdd(internalLink1, "192.0.0.1/31").Return(nil)
152+
mockNetlink.EXPECT().LinkByName("eth0").Return(eth0Link, nil).AnyTimes()
153+
mockNetlink.EXPECT().IPv4Addresses(eth0Link).Return([]netlink.Addr{eth0Addr}, nil)
154+
mockNetlink.EXPECT().AddrDel(eth0Link, "172.0.0.2/24").Return(nil)
155+
// Port 2
156+
internalLink2 := &netlink.Dummy{}
157+
mockExec.EXPECT().Execute("ovs-vsctl port-to-br eth1").Return("br-0000_08_00.2", nil)
158+
mockNetlink.EXPECT().LinkByName("br-0000_08_00.2").Return(internalLink2, nil).AnyTimes()
159+
mockNetlink.EXPECT().IsLinkAdminStateUp(internalLink2).Return(false)
160+
mockNetlink.EXPECT().LinkSetUp(internalLink2).Return(nil)
161+
mockNetlink.EXPECT().IPv4Addresses(internalLink2).Return([]netlink.Addr{}, nil)
162+
mockNetlink.EXPECT().AddrAdd(internalLink2, "192.32.0.1/31").Return(nil)
163+
eth1Link := &netlink.Dummy{}
164+
mockNetlink.EXPECT().LinkByName("eth1").Return(eth1Link, nil).AnyTimes()
165+
mockNetlink.EXPECT().IPv4Addresses(eth1Link).Return([]netlink.Addr{
166+
{IPNet: &net.IPNet{IP: net.ParseIP("172.32.0.2"), Mask: net.CIDRMask(24, 32)}},
167+
}, nil)
168+
mockNetlink.EXPECT().AddrAdd(internalLink2, "172.32.0.2/24").Return(nil)
169+
mockNetlink.EXPECT().AddrDel(eth1Link, "172.32.0.2/24").Return(nil)
170+
result, err := r.Reconcile(ctx, request)
171+
Expect(err).To(BeNil())
172+
Expect(result).To(Equal(ctrl.Result{}))
173+
})
138174
})
139175

140176
Describe("processRailDeviceMapping", func() {

0 commit comments

Comments
 (0)