blob: 2797f32352b1518fe45163402dacbdd948880826 [file] [log] [blame]
Daniel Parkf3136042021-03-10 07:49:11 +09001/*
2 * Copyright 2021-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.kubevirtnetworking.impl;
17
18import org.onlab.packet.ARP;
19import org.onlab.packet.EthType;
20import org.onlab.packet.Ethernet;
21import org.onlab.packet.IpPrefix;
22import org.onlab.packet.MacAddress;
23import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.LeadershipService;
25import org.onosproject.cluster.NodeId;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.kubevirtnetworking.api.KubevirtFloatingIp;
29import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
30import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
31import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
32import org.onosproject.kubevirtnetworking.api.KubevirtPort;
Jian Li254de8a2022-10-27 17:29:29 +090033import org.onosproject.kubevirtnetworking.api.KubevirtPortEvent;
34import org.onosproject.kubevirtnetworking.api.KubevirtPortListener;
Daniel Parkf3136042021-03-10 07:49:11 +090035import org.onosproject.kubevirtnetworking.api.KubevirtPortService;
36import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
37import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
38import org.onosproject.kubevirtnetworking.api.KubevirtRouterListener;
39import org.onosproject.kubevirtnetworking.api.KubevirtRouterService;
40import org.onosproject.kubevirtnetworking.util.RulePopulatorUtil;
41import org.onosproject.kubevirtnode.api.KubevirtNode;
Jian Li394bef52021-05-27 18:53:45 +090042import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
43import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
Daniel Parkf3136042021-03-10 07:49:11 +090044import org.onosproject.kubevirtnode.api.KubevirtNodeService;
45import org.onosproject.net.Device;
46import org.onosproject.net.PortNumber;
47import org.onosproject.net.device.DeviceAdminService;
48import org.onosproject.net.driver.DriverService;
49import org.onosproject.net.flow.DefaultTrafficSelector;
50import org.onosproject.net.flow.DefaultTrafficTreatment;
51import org.onosproject.net.flow.TrafficSelector;
52import org.onosproject.net.flow.TrafficTreatment;
Daniel Park157947f2021-04-09 17:50:53 +090053import org.onosproject.net.packet.DefaultOutboundPacket;
54import org.onosproject.net.packet.PacketService;
Daniel Parkf3136042021-03-10 07:49:11 +090055import org.osgi.service.component.annotations.Activate;
56import org.osgi.service.component.annotations.Component;
57import org.osgi.service.component.annotations.Deactivate;
58import org.osgi.service.component.annotations.Reference;
59import org.osgi.service.component.annotations.ReferenceCardinality;
60import org.slf4j.Logger;
61
Daniel Park157947f2021-04-09 17:50:53 +090062import java.nio.ByteBuffer;
Daniel Parkf3136042021-03-10 07:49:11 +090063import java.util.Objects;
64import java.util.concurrent.ExecutorService;
65
66import static java.util.concurrent.Executors.newSingleThreadExecutor;
67import static org.onlab.util.Tools.groupedThreads;
68import static org.onosproject.kubevirtnetworking.api.Constants.FORWARDING_TABLE;
Jian Lif89d9602021-04-27 19:05:49 +090069import static org.onosproject.kubevirtnetworking.api.Constants.GW_ENTRY_TABLE;
Daniel Parkf3136042021-03-10 07:49:11 +090070import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Daniel Parkf3136042021-03-10 07:49:11 +090071import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Daniel Park328fb602021-05-31 13:49:53 +090072import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FLOATING_GATEWAY_TUN_BRIDGE_RULE;
Daniel Parkc1ba1f42022-05-16 17:30:24 +090073import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FLOATING_IP_DOWNSTREAM_RULE;
74import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FLOATING_IP_UPSTREAM_RULE;
Daniel Parkf3136042021-03-10 07:49:11 +090075import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
76import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.GENEVE;
77import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.GRE;
Jian Li4b3436a2022-03-23 13:07:19 +090078import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.STT;
Daniel Parkf3136042021-03-10 07:49:11 +090079import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VXLAN;
Daniel Park157947f2021-04-09 17:50:53 +090080import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.buildGarpPacket;
Daniel Parkf3136042021-03-10 07:49:11 +090081import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.externalPatchPortNum;
Daniel Parkf3136042021-03-10 07:49:11 +090082import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
83import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
84import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
85import static org.slf4j.LoggerFactory.getLogger;
86
87/**
88 * Handles kubevirt floating ip.
89 */
90@Component(immediate = true)
91public class KubevirtFloatingIpHandler {
92 protected final Logger log = getLogger(getClass());
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY)
95 protected CoreService coreService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY)
98 protected ClusterService clusterService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY)
101 protected LeadershipService leadershipService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY)
104 protected DeviceAdminService deviceService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Daniel Park157947f2021-04-09 17:50:53 +0900107 protected PacketService packetService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Daniel Parkf3136042021-03-10 07:49:11 +0900110 protected KubevirtPortService kubevirtPortService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY)
113 protected KubevirtNodeService kubevirtNodeService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY)
116 protected KubevirtNetworkService kubevirtNetworkService;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY)
119 protected KubevirtFlowRuleService flowService;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY)
122 protected DriverService driverService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
125 protected KubevirtRouterService kubevirtRouterService;
126
127 private final ExecutorService eventExecutor = newSingleThreadExecutor(
128 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
129
130 private ApplicationId appId;
131 private NodeId localNodeId;
132
Jian Li517597a2021-03-22 11:04:52 +0900133 private final InternalRouterEventListener kubevirtRouterListener =
Daniel Parkf3136042021-03-10 07:49:11 +0900134 new InternalRouterEventListener();
Jian Li394bef52021-05-27 18:53:45 +0900135 private final InternalNodeListener kubevirtNodeListener =
136 new InternalNodeListener();
Daniel Parkf3136042021-03-10 07:49:11 +0900137
Jian Li254de8a2022-10-27 17:29:29 +0900138 private final InternalPortListener kubevirtPortListener =
139 new InternalPortListener();
140
Daniel Parkf3136042021-03-10 07:49:11 +0900141 @Activate
142 protected void activate() {
143 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
144 localNodeId = clusterService.getLocalNode().id();
145 leadershipService.runForLeadership(appId.name());
Jian Li517597a2021-03-22 11:04:52 +0900146 kubevirtRouterService.addListener(kubevirtRouterListener);
Jian Li394bef52021-05-27 18:53:45 +0900147 kubevirtNodeService.addListener(kubevirtNodeListener);
Jian Li254de8a2022-10-27 17:29:29 +0900148 kubevirtPortService.addListener(kubevirtPortListener);
Daniel Parkf3136042021-03-10 07:49:11 +0900149
150 log.info("Started");
151 }
152
153 @Deactivate
154 protected void deactivate() {
155 leadershipService.withdraw(appId.name());
Jian Li517597a2021-03-22 11:04:52 +0900156 kubevirtRouterService.removeListener(kubevirtRouterListener);
Jian Li394bef52021-05-27 18:53:45 +0900157 kubevirtNodeService.removeListener(kubevirtNodeListener);
Jian Li254de8a2022-10-27 17:29:29 +0900158 kubevirtPortService.removeListener(kubevirtPortListener);
Daniel Parkf3136042021-03-10 07:49:11 +0900159
160 eventExecutor.shutdown();
161
162 log.info("Stopped");
163 }
164
Daniel Park157947f2021-04-09 17:50:53 +0900165 private void setFloatingIpRulesForFip(KubevirtRouter router,
166 KubevirtFloatingIp floatingIp,
167 KubevirtNode electedGw,
168 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900169
Jian Licb580422022-02-03 15:08:31 +0900170 KubevirtPort kubevirtPort = getKubevirtPortByFloatingIp(floatingIp);
Daniel Parkf3136042021-03-10 07:49:11 +0900171 if (kubevirtPort == null) {
Daniel Parkf3136042021-03-10 07:49:11 +0900172 return;
173 }
174
175 KubevirtNetwork kubevirtNetwork = kubevirtNetworkService.network(kubevirtPort.networkId());
Jian Li4b3436a2022-03-23 13:07:19 +0900176 if (kubevirtNetwork.type() == VXLAN || kubevirtNetwork.type() == GENEVE ||
177 kubevirtNetwork.type() == GRE || kubevirtNetwork.type() == STT) {
Daniel Park328fb602021-05-31 13:49:53 +0900178 setFloatingIpDownstreamRulesToGatewayTunBridge(floatingIp,
179 electedGw, kubevirtNetwork, kubevirtPort, install);
Daniel Parkf3136042021-03-10 07:49:11 +0900180 }
181
Daniel Park157947f2021-04-09 17:50:53 +0900182 setFloatingIpArpResponseRules(router, floatingIp, kubevirtPort, electedGw, install);
183 setFloatingIpUpstreamRules(router, floatingIp, kubevirtPort, electedGw, install);
184 setFloatingIpDownstreamRules(router, floatingIp, kubevirtPort, electedGw, install);
Daniel Parkf3136042021-03-10 07:49:11 +0900185 }
186
187 private void setFloatingIpArpResponseRules(KubevirtRouter router,
188 KubevirtFloatingIp floatingIp,
189 KubevirtPort port,
Daniel Park157947f2021-04-09 17:50:53 +0900190 KubevirtNode electedGw,
Daniel Parkf3136042021-03-10 07:49:11 +0900191 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900192 TrafficSelector selector = DefaultTrafficSelector.builder()
193 .matchInPort(externalPatchPortNum(deviceService, electedGw))
194 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
195 .matchArpOp(ARP.OP_REQUEST)
196 .matchArpTpa(floatingIp.floatingIp().getIp4Address())
197 .build();
198
199 Device device = deviceService.getDevice(electedGw.intgBridge());
200
201 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
202 .extension(RulePopulatorUtil.buildMoveEthSrcToDstExtension(device), device.id())
203 .extension(RulePopulatorUtil.buildMoveArpShaToThaExtension(device), device.id())
204 .extension(RulePopulatorUtil.buildMoveArpSpaToTpaExtension(device), device.id())
205 .setArpOp(ARP.OP_REPLY)
206 .setEthSrc(port.macAddress())
207 .setArpSha(port.macAddress())
208 .setArpSpa(floatingIp.floatingIp().getIp4Address())
209 .setOutput(PortNumber.IN_PORT)
210 .build();
211
212 flowService.setRule(
213 appId,
214 electedGw.intgBridge(),
215 selector,
216 treatment,
217 PRIORITY_ARP_GATEWAY_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900218 GW_ENTRY_TABLE,
Daniel Parkf3136042021-03-10 07:49:11 +0900219 install);
220 }
Jian Li517597a2021-03-22 11:04:52 +0900221
Jian Licb580422022-02-03 15:08:31 +0900222 private KubevirtPort getKubevirtPortByFloatingIp(KubevirtFloatingIp floatingIp) {
Daniel Parkf3136042021-03-10 07:49:11 +0900223
224 return kubevirtPortService.ports().stream()
225 .filter(port -> port.ipAddress().equals(floatingIp.fixedIp()))
Jian Licb580422022-02-03 15:08:31 +0900226 .filter(port -> port.vmName().equals(floatingIp.vmName()))
Daniel Parkf3136042021-03-10 07:49:11 +0900227 .findAny().orElse(null);
228 }
229
Jian Li254de8a2022-10-27 17:29:29 +0900230 private KubevirtFloatingIp getFloatingIpByKubevirtPort(KubevirtPort port) {
231
232 return kubevirtRouterService.floatingIps().stream()
233 .filter(fip -> port.ipAddress().equals(fip.fixedIp()))
234 .filter(fip -> port.vmName().equals(fip.vmName()))
235 .findAny().orElse(null);
236 }
237
Daniel Parkf3136042021-03-10 07:49:11 +0900238 private void setFloatingIpUpstreamRules(KubevirtRouter router,
239 KubevirtFloatingIp floatingIp,
240 KubevirtPort port,
Daniel Park157947f2021-04-09 17:50:53 +0900241 KubevirtNode electedGw,
Daniel Parkf3136042021-03-10 07:49:11 +0900242 boolean install) {
243
Daniel Parkf3136042021-03-10 07:49:11 +0900244 MacAddress peerMacAddress = router.peerRouter().macAddress();
245
246 if (peerMacAddress == null) {
247 log.warn("Failed to install floating Ip rules for floating ip {} and router {}" +
248 "because there's no peer router mac address", floatingIp.floatingIp(),
249 router.name());
250 return;
251 }
252
253 MacAddress routerMacAddress = getRouterMacAddress(router);
254
255 TrafficSelector selector = DefaultTrafficSelector.builder()
256 .matchEthType(Ethernet.TYPE_IPV4)
257 .matchEthSrc(port.macAddress())
258 .matchEthDst(routerMacAddress)
259 .matchIPSrc(IpPrefix.valueOf(floatingIp.fixedIp(), 32))
260 .build();
261
Daniel Parkf3136042021-03-10 07:49:11 +0900262 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
263 .setEthDst(peerMacAddress)
264 .setEthSrc(port.macAddress())
265 .setIpSrc(floatingIp.floatingIp())
266 .setOutput(externalPatchPortNum(deviceService, electedGw))
267 .build();
268
269 flowService.setRule(
270 appId,
271 electedGw.intgBridge(),
272 selector,
273 treatment,
Daniel Parkc1ba1f42022-05-16 17:30:24 +0900274 PRIORITY_FLOATING_IP_UPSTREAM_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900275 GW_ENTRY_TABLE,
Daniel Parkf3136042021-03-10 07:49:11 +0900276 install);
277 }
278
279 private void setFloatingIpDownstreamRules(KubevirtRouter router,
280 KubevirtFloatingIp floatingIp,
281 KubevirtPort port,
Daniel Park157947f2021-04-09 17:50:53 +0900282 KubevirtNode electedGw,
Daniel Parkf3136042021-03-10 07:49:11 +0900283 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900284 MacAddress routerMacAddress = getRouterMacAddress(router);
285
286 TrafficSelector selector = DefaultTrafficSelector.builder()
287 .matchEthType(Ethernet.TYPE_IPV4)
288 .matchEthDst(port.macAddress())
289 .matchIPDst(IpPrefix.valueOf(floatingIp.floatingIp(), 32))
290 .build();
291
292 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
293 .setEthSrc(routerMacAddress)
294 .setEthDst(port.macAddress())
295 .setIpDst(floatingIp.fixedIp())
296 .transition(FORWARDING_TABLE)
297 .build();
298
299 flowService.setRule(
300 appId,
301 electedGw.intgBridge(),
302 selector,
303 treatment,
Daniel Parkc1ba1f42022-05-16 17:30:24 +0900304 PRIORITY_FLOATING_IP_DOWNSTREAM_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900305 GW_ENTRY_TABLE,
Daniel Parkf3136042021-03-10 07:49:11 +0900306 install);
307 }
308
Daniel Park328fb602021-05-31 13:49:53 +0900309 private void setFloatingIpDownstreamRulesToGatewayTunBridge(KubevirtFloatingIp floatingIp,
310 KubevirtNode electedGw,
Daniel Parkf3136042021-03-10 07:49:11 +0900311 KubevirtNetwork network,
312 KubevirtPort port,
313 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900314 KubevirtNode workerNode = kubevirtNodeService.node(port.deviceId());
315 if (workerNode == null) {
316 log.warn("Failed to install floating Ip rules for floating ip {} " +
317 "because fail to fine the worker node that the associated port is running on",
318 floatingIp.floatingIp());
Jian Li9793ec42021-03-19 15:03:32 +0900319 return;
Daniel Parkf3136042021-03-10 07:49:11 +0900320 }
321
322 PortNumber tunnelPortNumber = tunnelPort(electedGw, network);
323 if (tunnelPortNumber == null) {
324 return;
325 }
326
Daniel Parkf3136042021-03-10 07:49:11 +0900327 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
328 .matchEthType(Ethernet.TYPE_IPV4)
329 .matchIPDst(IpPrefix.valueOf(port.ipAddress(), 32))
330 .matchEthDst(port.macAddress());
331
332 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
333 .setTunnelId(Long.parseLong(network.segmentId()))
334 .extension(buildExtension(
335 deviceService,
336 electedGw.tunBridge(),
337 workerNode.dataIp().getIp4Address()),
338 electedGw.tunBridge())
339 .setOutput(tunnelPortNumber);
340
341 flowService.setRule(
342 appId,
343 electedGw.tunBridge(),
344 sBuilder.build(),
345 tBuilder.build(),
Daniel Park328fb602021-05-31 13:49:53 +0900346 PRIORITY_FLOATING_GATEWAY_TUN_BRIDGE_RULE,
Daniel Parkf3136042021-03-10 07:49:11 +0900347 TUNNEL_DEFAULT_TABLE,
348 install);
349 }
350
Daniel Park157947f2021-04-09 17:50:53 +0900351 private void processGarpPacketForFloatingIp(KubevirtFloatingIp floatingIp, KubevirtNode electedGw) {
352
353 if (floatingIp == null) {
354 return;
355 }
356
Jian Licb580422022-02-03 15:08:31 +0900357 KubevirtPort kubevirtPort = getKubevirtPortByFloatingIp(floatingIp);
Daniel Park157947f2021-04-09 17:50:53 +0900358 if (kubevirtPort == null) {
Daniel Park157947f2021-04-09 17:50:53 +0900359 return;
360 }
361
362 Ethernet ethernet = buildGarpPacket(kubevirtPort.macAddress(), floatingIp.floatingIp());
363 if (ethernet == null) {
364 return;
365 }
366
367 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
368 .setOutput(externalPatchPortNum(deviceService, electedGw)).build();
369
370 packetService.emit(new DefaultOutboundPacket(electedGw.intgBridge(), treatment,
371 ByteBuffer.wrap(ethernet.serialize())));
372 }
373
Daniel Parkf3136042021-03-10 07:49:11 +0900374 private class InternalRouterEventListener implements KubevirtRouterListener {
375 private boolean isRelevantHelper() {
376 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
377 }
378
Daniel Parkf3136042021-03-10 07:49:11 +0900379 @Override
380 public void event(KubevirtRouterEvent event) {
381 switch (event.type()) {
Daniel Parkf3136042021-03-10 07:49:11 +0900382 case KUBEVIRT_FLOATING_IP_ASSOCIATED:
383 eventExecutor.execute(() -> processFloatingIpAssociation(event.subject(),
384 event.floatingIp()));
385 break;
386 case KUBEVIRT_FLOATING_IP_DISASSOCIATED:
387 eventExecutor.execute(() -> processFloatingIpDisassociation(event.subject(),
388 event.floatingIp()));
389 break;
Daniel Park157947f2021-04-09 17:50:53 +0900390 case KUBEVIRT_GATEWAY_NODE_CHANGED:
391 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
392 event.gateway()));
393 break;
Jian Li8f944d42021-03-23 00:43:29 +0900394 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
395 eventExecutor.execute(() -> processGatewayNodeAttachment(event.subject(),
396 event.gateway()));
397 break;
398 case KUBEVIRT_GATEWAY_NODE_DETACHED:
399 eventExecutor.execute(() -> processGatewayNodeDetachment(event.subject(),
400 event.gateway()));
401 break;
Daniel Parkf3136042021-03-10 07:49:11 +0900402 default:
403 //do nothing
404 break;
405 }
406 }
407
Daniel Park157947f2021-04-09 17:50:53 +0900408 private void processRouterGatewayNodeChanged(KubevirtRouter router, String disAssociatedGateway) {
Daniel Parka5ba88d2021-05-28 15:46:46 +0900409 kubevirtRouterService.floatingIpsByRouter(router.name())
410 .forEach(fip -> {
Daniel Park157947f2021-04-09 17:50:53 +0900411 KubevirtNode newGw = kubevirtNodeService.node(router.electedGateway());
412 if (newGw == null) {
413 return;
414 }
Daniel Park157947f2021-04-09 17:50:53 +0900415 setFloatingIpRulesForFip(router, fip, newGw, true);
416 processGarpPacketForFloatingIp(fip, newGw);
Daniel Parka5ba88d2021-05-28 15:46:46 +0900417 KubevirtNode oldGw = kubevirtNodeService.node(disAssociatedGateway);
Daniel Park157947f2021-04-09 17:50:53 +0900418
Daniel Parka5ba88d2021-05-28 15:46:46 +0900419 if (oldGw == null) {
420 return;
421 }
422 setFloatingIpRulesForFip(router, fip, oldGw, false);
423 });
Daniel Park157947f2021-04-09 17:50:53 +0900424 }
425
Jian Li8f944d42021-03-23 00:43:29 +0900426 private void processGatewayNodeAttachment(KubevirtRouter router, String gatewayName) {
Daniel Parka5ba88d2021-05-28 15:46:46 +0900427 kubevirtRouterService.floatingIpsByRouter(router.name())
428 .forEach(fip -> {
429 KubevirtNode gw = kubevirtNodeService.node(gatewayName);
430 if (gw != null) {
431 setFloatingIpRulesForFip(router, fip, gw, true);
432 }
433 });
Jian Li8f944d42021-03-23 00:43:29 +0900434 }
435
436 private void processGatewayNodeDetachment(KubevirtRouter router, String gatewayName) {
Daniel Parka5ba88d2021-05-28 15:46:46 +0900437 kubevirtRouterService.floatingIpsByRouter(router.name())
438 .forEach(fip -> {
439 KubevirtNode gw = kubevirtNodeService.node(gatewayName);
440 if (gw != null) {
441 setFloatingIpRulesForFip(router, fip, gw, false);
442 }
443 });
Jian Li8f944d42021-03-23 00:43:29 +0900444 }
445
Daniel Parkf3136042021-03-10 07:49:11 +0900446 private void processFloatingIpAssociation(KubevirtRouter router, KubevirtFloatingIp floatingIp) {
Daniel Park157947f2021-04-09 17:50:53 +0900447 if (!isRelevantHelper() || router.electedGateway() == null) {
Daniel Parkf3136042021-03-10 07:49:11 +0900448 return;
449 }
Daniel Park157947f2021-04-09 17:50:53 +0900450
451 KubevirtNode electedGw = kubevirtNodeService.node(router.electedGateway());
452
453 if (electedGw == null) {
454 return;
455 }
456
457 processGarpPacketForFloatingIp(floatingIp, electedGw);
458 setFloatingIpRulesForFip(router, floatingIp, electedGw, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900459 }
460
461 private void processFloatingIpDisassociation(KubevirtRouter router, KubevirtFloatingIp floatingIp) {
Daniel Park157947f2021-04-09 17:50:53 +0900462 if (!isRelevantHelper() || router.electedGateway() == null) {
Daniel Parkf3136042021-03-10 07:49:11 +0900463 return;
464 }
Daniel Park157947f2021-04-09 17:50:53 +0900465
466 KubevirtNode electedGw = kubevirtNodeService.node(router.electedGateway());
467
468 if (electedGw == null) {
469 return;
470 }
471 setFloatingIpRulesForFip(router, floatingIp, electedGw, false);
Daniel Parkf3136042021-03-10 07:49:11 +0900472 }
473 }
Jian Li394bef52021-05-27 18:53:45 +0900474
475 private class InternalNodeListener implements KubevirtNodeListener {
476 private boolean isRelevantHelper() {
477 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
478 }
479
480 @Override
481 public void event(KubevirtNodeEvent event) {
482 switch (event.type()) {
483 case KUBEVIRT_NODE_COMPLETE:
484 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
485 break;
486 default:
487 break;
488 }
489 }
490
491 private void processNodeCompletion(KubevirtNode node) {
492 if (!isRelevantHelper()) {
493 return;
494 }
495
496 for (KubevirtFloatingIp fip : kubevirtRouterService.floatingIps()) {
497 KubevirtRouter router = kubevirtRouterService.router(fip.routerName());
498 if (router == null) {
499 log.warn("The router {} is not found", fip.routerName());
500 continue;
501 }
502
503 if (node.hostname().equals(router.electedGateway())) {
504 setFloatingIpRulesForFip(router, fip, node, true);
505 log.info("Configure floating IP {} on gateway {}",
506 fip.floatingIp().toString(), node.hostname());
507 }
508 }
509 }
510 }
Jian Li254de8a2022-10-27 17:29:29 +0900511
512 private class InternalPortListener implements KubevirtPortListener {
513
514 private boolean isRelevantHelper() {
515 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
516 }
517
518 @Override
519 public void event(KubevirtPortEvent event) {
520 switch (event.type()) {
521 case KUBEVIRT_PORT_MIGRATED:
522 eventExecutor.execute(() -> processPortMigration(event.subject()));
523 break;
524 default:
525 // do nothing
526 break;
527 }
528 }
529
530 private void processPortMigration(KubevirtPort port) {
531 if (!isRelevantHelper()) {
532 return;
533 }
534
535 KubevirtFloatingIp fip = getFloatingIpByKubevirtPort(port);
536 if (fip == null) {
537 return;
538 }
539
540 KubevirtRouter router = kubevirtRouterService.router(fip.routerName());
541 if (router == null) {
542 log.warn("The router {} is not found", fip.routerName());
543 return;
544 }
545
546 String gateway = router.electedGateway();
547 KubevirtNode node = kubevirtNodeService.node(gateway);
548
549 if (node == null) {
550 log.warn("The gateway node {} is not found", gateway);
551 return;
552 }
553
554 setFloatingIpRulesForFip(router, fip, node, true);
555
556 log.info("Configure floating IP {} on gateway {}",
557 fip.floatingIp().toString(), node.hostname());
558 }
559 }
Daniel Parkf3136042021-03-10 07:49:11 +0900560}