blob: 18caff199191a19d5503158dfe70f1fb30dbeacc [file] [log] [blame]
Jian Li556709c2021-02-03 17:54:28 +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 com.google.common.collect.Lists;
Jian Li858ccd72021-02-04 17:25:01 +090019import org.onlab.packet.ARP;
20import org.onlab.packet.EthType;
Jian Li556709c2021-02-03 17:54:28 +090021import org.onlab.packet.Ethernet;
22import org.onlab.packet.IPv4;
Jian Li858ccd72021-02-04 17:25:01 +090023import org.onlab.packet.Ip4Address;
Jian Li556709c2021-02-03 17:54:28 +090024import org.onlab.packet.IpAddress;
Jian Li858ccd72021-02-04 17:25:01 +090025import org.onlab.packet.IpPrefix;
Jian Li556709c2021-02-03 17:54:28 +090026import org.onlab.packet.TpPort;
27import org.onlab.packet.UDP;
28import org.onosproject.cluster.ClusterService;
29import org.onosproject.cluster.LeadershipService;
30import org.onosproject.cluster.NodeId;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
34import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
35import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
36import org.onosproject.kubevirtnetworking.api.KubevirtNetworkListener;
37import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
38import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
39import org.onosproject.kubevirtnode.api.KubevirtNode;
40import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
41import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
42import org.onosproject.kubevirtnode.api.KubevirtNodeService;
43import org.onosproject.net.Device;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.PortNumber;
46import org.onosproject.net.behaviour.BridgeConfig;
47import org.onosproject.net.behaviour.BridgeDescription;
48import org.onosproject.net.behaviour.BridgeName;
49import org.onosproject.net.behaviour.ControllerInfo;
50import org.onosproject.net.behaviour.DefaultBridgeDescription;
51import org.onosproject.net.behaviour.DefaultPatchDescription;
52import org.onosproject.net.behaviour.InterfaceConfig;
53import org.onosproject.net.behaviour.PatchDescription;
54import org.onosproject.net.device.DeviceAdminService;
Daniel Parka8968802021-02-25 09:14:22 +090055import org.onosproject.net.driver.DriverService;
Jian Li556709c2021-02-03 17:54:28 +090056import org.onosproject.net.flow.DefaultTrafficSelector;
57import org.onosproject.net.flow.DefaultTrafficTreatment;
58import org.onosproject.net.flow.TrafficSelector;
59import org.onosproject.net.flow.TrafficTreatment;
60import org.osgi.service.component.annotations.Activate;
61import org.osgi.service.component.annotations.Component;
62import org.osgi.service.component.annotations.Deactivate;
63import org.osgi.service.component.annotations.Reference;
64import org.osgi.service.component.annotations.ReferenceCardinality;
65import org.slf4j.Logger;
66
67import java.util.List;
68import java.util.Objects;
69import java.util.concurrent.ExecutorService;
70
71import static java.lang.Thread.sleep;
72import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Li858ccd72021-02-04 17:25:01 +090073import static org.onlab.packet.ICMP.CODE_ECHO_REQEUST;
74import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
75import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
Jian Li556709c2021-02-03 17:54:28 +090076import static org.onlab.util.Tools.groupedThreads;
Jian Li858ccd72021-02-04 17:25:01 +090077import static org.onosproject.kubevirtnetworking.api.Constants.DEFAULT_GATEWAY_MAC;
Jian Li556709c2021-02-03 17:54:28 +090078import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Daniel Parka8968802021-02-25 09:14:22 +090079import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +090080import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li556709c2021-02-03 17:54:28 +090081import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090082import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FORWARDING_RULE;
83import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ICMP_RULE;
84import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ARP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090085import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_DHCP_TABLE;
86import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +090087import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090088import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +090089import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
90import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Jian Li556709c2021-02-03 17:54:28 +090091import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Jian Li858ccd72021-02-04 17:25:01 +090092import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
93import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
94import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
95import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
96import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
97import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
98import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Li556709c2021-02-03 17:54:28 +090099import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Parka8968802021-02-25 09:14:22 +0900100import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
101import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Li556709c2021-02-03 17:54:28 +0900102import static org.slf4j.LoggerFactory.getLogger;
103
104/**
105 * Handles kubevirt network events.
106 */
107@Component(immediate = true)
108public class KubevirtNetworkHandler {
109 protected final Logger log = getLogger(getClass());
110 private static final String DEFAULT_OF_PROTO = "tcp";
111 private static final int DEFAULT_OFPORT = 6653;
112 private static final int DPID_BEGIN = 3;
113 private static final long SLEEP_MS = 3000; // we wait 3s for init each node
Jian Li858ccd72021-02-04 17:25:01 +0900114 private static final int DEFAULT_TTL = 0xff;
Jian Li556709c2021-02-03 17:54:28 +0900115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
117 protected CoreService coreService;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
120 protected ClusterService clusterService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
123 protected LeadershipService leadershipService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
126 protected DeviceAdminService deviceService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
129 protected KubevirtApiConfigService apiConfigService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY)
132 protected KubevirtNodeService nodeService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
135 protected KubevirtNetworkService networkService;
136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY)
138 protected KubevirtFlowRuleService flowService;
139
Daniel Parka8968802021-02-25 09:14:22 +0900140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
141 protected DriverService driverService;
142
Jian Li556709c2021-02-03 17:54:28 +0900143 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
144 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
145
146 private final ExecutorService eventExecutor = newSingleThreadExecutor(
147 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
148
149 private ApplicationId appId;
150 private NodeId localNodeId;
151
152 @Activate
153 protected void activate() {
154 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
155 localNodeId = clusterService.getLocalNode().id();
156 networkService.addListener(networkListener);
157 nodeService.addListener(nodeListener);
158 leadershipService.runForLeadership(appId.name());
159
160 log.info("Started");
161 }
162
163 @Deactivate
164 protected void deactivate() {
165 networkService.removeListener(networkListener);
166 nodeService.removeListener(nodeListener);
167 leadershipService.withdraw(appId.name());
168 eventExecutor.shutdown();
169
170 log.info("Stopped");
171 }
172
173 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
174
175 Device tunBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
176 if (tunBridge != null) {
177 log.warn("The tunnel bridge {} already exists at node {}",
178 network.tenantBridgeName(), node.hostname());
179 setDefaultRules(node, network);
180 return;
181 }
182
183 Device device = deviceService.getDevice(node.ovsdb());
184
185 IpAddress serverIp = apiConfigService.apiConfig().ipAddress();
186 ControllerInfo controlInfo =
187 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
188 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
189
190 String dpid = network.tenantDeviceId(
191 node.hostname()).toString().substring(DPID_BEGIN);
192
193 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
194 .name(network.tenantBridgeName())
195 .failMode(BridgeDescription.FailMode.SECURE)
196 .datapathId(dpid)
197 .disableInBand()
198 .controllers(controllers);
199
200 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
201 bridgeConfig.addBridge(builder.build());
202 }
203
204 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
205 Device device = deviceService.getDevice(node.ovsdb());
206
207 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
208
209 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
210 bridgeConfig.deleteBridge(bridgeName);
211 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
212 }
213
214 private void createPatchInterface(KubevirtNode node, KubevirtNetwork network) {
215 Device device = deviceService.getDevice(node.ovsdb());
216
217 if (device == null || !device.is(InterfaceConfig.class)) {
218 log.error("Failed to create patch interface on {}", node.ovsdb());
219 return;
220 }
221
222 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
223
Jian Li858ccd72021-02-04 17:25:01 +0900224 String tenantToTunIntf =
225 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
226 String tunToTenantIntf =
227 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900228
Jian Li858ccd72021-02-04 17:25:01 +0900229 // tenant bridge -> tunnel bridge
230 PatchDescription brTenantTunPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900231 DefaultPatchDescription.builder()
232 .deviceId(network.tenantBridgeName())
Jian Li858ccd72021-02-04 17:25:01 +0900233 .ifaceName(tenantToTunIntf)
234 .peer(tunToTenantIntf)
Jian Li556709c2021-02-03 17:54:28 +0900235 .build();
236
Jian Li858ccd72021-02-04 17:25:01 +0900237 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900238
Jian Li858ccd72021-02-04 17:25:01 +0900239 // tunnel bridge -> tenant bridge
240 PatchDescription brTunTenantPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900241 DefaultPatchDescription.builder()
242 .deviceId(TUNNEL_BRIDGE)
Jian Li858ccd72021-02-04 17:25:01 +0900243 .ifaceName(tunToTenantIntf)
244 .peer(tenantToTunIntf)
Jian Li556709c2021-02-03 17:54:28 +0900245 .build();
Jian Li858ccd72021-02-04 17:25:01 +0900246 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900247 }
248
249 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
250 Device device = deviceService.getDevice(node.ovsdb());
251
252 if (device == null || !device.is(InterfaceConfig.class)) {
253 log.error("Failed to create patch interface on {}", node.ovsdb());
254 return;
255 }
256
257 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
258
Jian Li858ccd72021-02-04 17:25:01 +0900259 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900260
261 ifaceConfig.removePatchMode(tunToIntIntf);
262 }
263
264 private void setDefaultRules(KubevirtNode node, KubevirtNetwork network) {
265 DeviceId deviceId = network.tenantDeviceId(node.hostname());
266
267 while (!deviceService.isAvailable(deviceId)) {
268 log.warn("Device {} is not ready for installing rules", deviceId);
269
270 try {
271 sleep(SLEEP_MS);
272 } catch (InterruptedException e) {
273 log.error("Failed to check device availability", e);
274 }
275 }
276
277 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li858ccd72021-02-04 17:25:01 +0900278 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
279 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
280 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Li556709c2021-02-03 17:54:28 +0900281
282 setDhcpRule(deviceId, true);
283 setForwardingRule(deviceId, true);
Daniel Parka8968802021-02-25 09:14:22 +0900284 setGatewayArpRule(network, TENANT_ARP_TABLE,
285 network.tenantDeviceId(node.hostname()), true);
286 setGatewayIcmpRule(network, TENANT_ICMP_TABLE,
287 network.tenantDeviceId(node.hostname()), true);
Jian Li556709c2021-02-03 17:54:28 +0900288
289 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
290 }
291
292 private void setDhcpRule(DeviceId deviceId, boolean install) {
293 TrafficSelector selector = DefaultTrafficSelector.builder()
294 .matchEthType(Ethernet.TYPE_IPV4)
295 .matchIPProtocol(IPv4.PROTOCOL_UDP)
296 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
297 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
298 .build();
299
300 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
301 .punt()
302 .build();
303
304 flowService.setRule(
305 appId,
306 deviceId,
307 selector,
308 treatment,
309 PRIORITY_DHCP_RULE,
310 TENANT_DHCP_TABLE,
311 install);
312 }
313
Jian Li858ccd72021-02-04 17:25:01 +0900314 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900315 TrafficSelector selector = DefaultTrafficSelector.builder().build();
316 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
317 .setOutput(PortNumber.NORMAL)
318 .build();
319
320 flowService.setRule(
321 appId,
322 deviceId,
323 selector,
324 treatment,
Jian Li858ccd72021-02-04 17:25:01 +0900325 PRIORITY_FORWARDING_RULE,
Jian Li556709c2021-02-03 17:54:28 +0900326 TENANT_FORWARDING_TABLE,
327 install);
328 }
329
Daniel Parka8968802021-02-25 09:14:22 +0900330 private void setGatewayArpRule(KubevirtNetwork network,
331 int tableNum, DeviceId deviceId, boolean install) {
332 Device device = deviceService.getDevice(deviceId);
Jian Li858ccd72021-02-04 17:25:01 +0900333
334 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
335 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
336 .matchArpOp(ARP.OP_REQUEST)
337 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
338
339 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
340 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
341 .extension(buildMoveArpShaToThaExtension(device), device.id())
342 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
343 .setArpOp(ARP.OP_REPLY)
344 .setArpSha(DEFAULT_GATEWAY_MAC)
345 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
346 .setEthSrc(DEFAULT_GATEWAY_MAC)
347 .setOutput(PortNumber.IN_PORT);
348
349 flowService.setRule(
350 appId,
351 device.id(),
352 sBuilder.build(),
353 tBuilder.build(),
354 PRIORITY_ARP_GATEWAY_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900355 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900356 install
357 );
358 }
359
Daniel Parka8968802021-02-25 09:14:22 +0900360 private void
361 setGatewayIcmpRule(KubevirtNetwork network,
362 int tableNum, DeviceId deviceId, boolean install) {
Jian Li858ccd72021-02-04 17:25:01 +0900363 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
364 .matchEthType(Ethernet.TYPE_IPV4)
365 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
366 .matchIcmpType(TYPE_ECHO_REQUEST)
367 .matchIcmpCode(CODE_ECHO_REQEUST)
368 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
369
370 Device device = deviceService.getDevice(deviceId);
371 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
372 .extension(buildMoveEthSrcToDstExtension(device), device.id())
373 .extension(buildMoveIpSrcToDstExtension(device), device.id())
374 .extension(buildLoadExtension(device,
375 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
376 .extension(buildLoadExtension(device,
377 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
378 .setIpSrc(network.gatewayIp())
379 .setEthSrc(DEFAULT_GATEWAY_MAC)
380 .setOutput(PortNumber.IN_PORT);
381
382 flowService.setRule(
383 appId,
384 deviceId,
385 sBuilder.build(),
386 tBuilder.build(),
387 PRIORITY_ICMP_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900388 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900389 install);
390 }
391
Daniel Parka8968802021-02-25 09:14:22 +0900392
393 private void initGatewayNodeBridge(KubevirtNetwork network, boolean install) {
394 KubevirtNode electedGateway = gatewayNodeForSpecifiedNetwork(network);
395 if (electedGateway == null) {
396 log.warn("There's no elected gateway for the network {}", network.name());
397 }
398
399 setGatewayArpRule(network, PRE_FLAT_TABLE, electedGateway.intgBridge(), install);
400 setGatewayIcmpRule(network, PRE_FLAT_TABLE, electedGateway.intgBridge(), install);
401 }
402
403 /**
404 * Returns the gateway node for the specified network.
405 * Among gateways, only one gateway would act as a gateway per network.
406 *
407 * @param network kubevirt network
408 * @return gateway node which would act as the gateway for the network
409 */
410 private KubevirtNode gatewayNodeForSpecifiedNetwork(KubevirtNetwork network) {
411 //TODO: would implement election logic for each network.
412 //TODO: would implement cleanup logic in case a gateway node is added
413 // and the election is changed
414 return nodeService.completeNodes(GATEWAY).stream()
415 .findFirst().orElse(null);
416 }
417
Jian Li556709c2021-02-03 17:54:28 +0900418 private class InternalNetworkEventListener implements KubevirtNetworkListener {
419
420 private boolean isRelevantHelper() {
421 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
422 }
423
424 @Override
425 public void event(KubevirtNetworkEvent event) {
426 switch (event.type()) {
427 case KUBEVIRT_NETWORK_CREATED:
428 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
429 break;
430 case KUBEVIRT_NETWORK_REMOVED:
431 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
432 break;
433 case KUBEVIRT_NETWORK_UPDATED:
434 default:
435 // do nothing
436 break;
437 }
438 }
439
440 private void processNetworkCreation(KubevirtNetwork network) {
441 if (!isRelevantHelper()) {
442 return;
443 }
444
445 switch (network.type()) {
446 case VXLAN:
447 case GRE:
448 case GENEVE:
449 initIntegrationTunnelBridge(network);
450 break;
451 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +0900452 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +0900453 initGatewayNodeBridge(network, true);
454 break;
Jian Li556709c2021-02-03 17:54:28 +0900455 default:
456 // do nothing
457 break;
458 }
459 }
460
461 private void processNetworkRemoval(KubevirtNetwork network) {
462 if (!isRelevantHelper()) {
463 return;
464 }
465
466 switch (network.type()) {
467 case VXLAN:
468 case GRE:
469 case GENEVE:
470 purgeIntegrationTunnelBridge(network);
471 break;
472 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +0900473 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +0900474 initGatewayNodeBridge(network, false);
475 break;
Jian Li556709c2021-02-03 17:54:28 +0900476 default:
477 // do nothing
478 break;
479 }
480 }
481
482 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
483 if (network.segmentId() == null) {
484 return;
485 }
486
487 nodeService.completeNodes().forEach(n -> {
488 createBridge(n, network);
489 createPatchInterface(n, network);
490 setDefaultRules(n, network);
491 });
492 }
493
494 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
495 if (network.segmentId() == null) {
496 return;
497 }
498
499 nodeService.completeNodes().forEach(n -> {
500 removePatchInterface(n, network);
501 removeBridge(n, network);
502 });
503 }
504 }
505
506 private class InternalNodeEventListener implements KubevirtNodeListener {
507
508 private boolean isRelevantHelper() {
509 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
510 }
511
512 @Override
513 public void event(KubevirtNodeEvent event) {
514 switch (event.type()) {
515 case KUBEVIRT_NODE_COMPLETE:
516 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
517 break;
518 case KUBEVIRT_NODE_INCOMPLETE:
519 case KUBEVIRT_NODE_UPDATED:
520 default:
521 // do nothing
522 break;
523 }
524 }
525
526 private void processNodeCompletion(KubevirtNode node) {
527 if (!isRelevantHelper()) {
528 return;
529 }
530
Daniel Parka8968802021-02-25 09:14:22 +0900531 if (node.type().equals(WORKER)) {
532 for (KubevirtNetwork network : networkService.networks()) {
533 switch (network.type()) {
534 case VXLAN:
535 case GRE:
536 case GENEVE:
537 if (network.segmentId() == null) {
538 continue;
539 }
540 createBridge(node, network);
541 createPatchInterface(node, network);
542 setDefaultRules(node, network);
543 break;
544 case FLAT:
545 case VLAN:
546 default:
547 // do nothing
548 break;
549 }
550 }
551 } else if (node.type().equals(GATEWAY)) {
552 for (KubevirtNetwork network : networkService.networks()) {
553 switch (network.type()) {
554 case FLAT:
555 case VLAN:
556 initGatewayNodeBridge(network, true);
557 break;
558 case VXLAN:
559 case GRE:
560 case GENEVE:
561 default:
562 // do nothing
563 break;
564 }
Jian Li556709c2021-02-03 17:54:28 +0900565 }
566 }
567 }
568 }
569}