blob: 7f539de5ad5fc2e77a3281fbb2ea866b429f0367 [file] [log] [blame]
Jian Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +090019import org.onlab.packet.ARP;
20import org.onlab.packet.EthType;
Jian Lib5ab63c2021-02-03 17:54:28 +090021import org.onlab.packet.Ethernet;
22import org.onlab.packet.IPv4;
Jian Li543fe852021-02-04 17:25:01 +090023import org.onlab.packet.Ip4Address;
Jian Lib5ab63c2021-02-03 17:54:28 +090024import org.onlab.packet.IpAddress;
Jian Li543fe852021-02-04 17:25:01 +090025import org.onlab.packet.IpPrefix;
Jian Lib5ab63c2021-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 Park4063f402021-02-25 09:14:22 +090055import org.onosproject.net.driver.DriverService;
Jian Lib5ab63c2021-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 Li543fe852021-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 Lib5ab63c2021-02-03 17:54:28 +090076import static org.onlab.util.Tools.groupedThreads;
Jian Li543fe852021-02-04 17:25:01 +090077import static org.onosproject.kubevirtnetworking.api.Constants.DEFAULT_GATEWAY_MAC;
Jian Lib5ab63c2021-02-03 17:54:28 +090078import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Daniel Park4063f402021-02-25 09:14:22 +090079import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
Jian Li543fe852021-02-04 17:25:01 +090080import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Lib5ab63c2021-02-03 17:54:28 +090081import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li543fe852021-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 Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +090087import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Lib5ab63c2021-02-03 17:54:28 +090088import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li543fe852021-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 Lib5ab63c2021-02-03 17:54:28 +090091import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Jian Li543fe852021-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 Lib5ab63c2021-02-03 17:54:28 +090099import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Park4063f402021-02-25 09:14:22 +0900100import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
101import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +0900114 private static final int DEFAULT_TTL = 0xff;
Jian Lib5ab63c2021-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 Park4063f402021-02-25 09:14:22 +0900140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
141 protected DriverService driverService;
142
Jian Lib5ab63c2021-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 Li543fe852021-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 Lib5ab63c2021-02-03 17:54:28 +0900228
Jian Li543fe852021-02-04 17:25:01 +0900229 // tenant bridge -> tunnel bridge
230 PatchDescription brTenantTunPatchDesc =
Jian Lib5ab63c2021-02-03 17:54:28 +0900231 DefaultPatchDescription.builder()
232 .deviceId(network.tenantBridgeName())
Jian Li543fe852021-02-04 17:25:01 +0900233 .ifaceName(tenantToTunIntf)
234 .peer(tunToTenantIntf)
Jian Lib5ab63c2021-02-03 17:54:28 +0900235 .build();
236
Jian Li543fe852021-02-04 17:25:01 +0900237 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Lib5ab63c2021-02-03 17:54:28 +0900238
Jian Li543fe852021-02-04 17:25:01 +0900239 // tunnel bridge -> tenant bridge
240 PatchDescription brTunTenantPatchDesc =
Jian Lib5ab63c2021-02-03 17:54:28 +0900241 DefaultPatchDescription.builder()
242 .deviceId(TUNNEL_BRIDGE)
Jian Li543fe852021-02-04 17:25:01 +0900243 .ifaceName(tunToTenantIntf)
244 .peer(tenantToTunIntf)
Jian Lib5ab63c2021-02-03 17:54:28 +0900245 .build();
Jian Li543fe852021-02-04 17:25:01 +0900246 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
Jian Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +0900259 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Lib5ab63c2021-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 Li543fe852021-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 Lib5ab63c2021-02-03 17:54:28 +0900281
282 setDhcpRule(deviceId, true);
283 setForwardingRule(deviceId, true);
Daniel Park4063f402021-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 Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +0900314 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Lib5ab63c2021-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 Li543fe852021-02-04 17:25:01 +0900325 PRIORITY_FORWARDING_RULE,
Jian Lib5ab63c2021-02-03 17:54:28 +0900326 TENANT_FORWARDING_TABLE,
327 install);
328 }
329
Daniel Park4063f402021-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 Li543fe852021-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 Park4063f402021-02-25 09:14:22 +0900355 tableNum,
Jian Li543fe852021-02-04 17:25:01 +0900356 install
357 );
358 }
359
Daniel Park4063f402021-02-25 09:14:22 +0900360 private void
361 setGatewayIcmpRule(KubevirtNetwork network,
362 int tableNum, DeviceId deviceId, boolean install) {
Jian Li543fe852021-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 Park4063f402021-02-25 09:14:22 +0900388 tableNum,
Jian Li543fe852021-02-04 17:25:01 +0900389 install);
390 }
391
Daniel Park4063f402021-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());
Jian Li4acd4542021-03-03 14:46:50 +0900397 return;
Daniel Park4063f402021-02-25 09:14:22 +0900398 }
399
400 setGatewayArpRule(network, PRE_FLAT_TABLE, electedGateway.intgBridge(), install);
401 setGatewayIcmpRule(network, PRE_FLAT_TABLE, electedGateway.intgBridge(), install);
402 }
403
404 /**
405 * Returns the gateway node for the specified network.
406 * Among gateways, only one gateway would act as a gateway per network.
407 *
408 * @param network kubevirt network
409 * @return gateway node which would act as the gateway for the network
410 */
411 private KubevirtNode gatewayNodeForSpecifiedNetwork(KubevirtNetwork network) {
412 //TODO: would implement election logic for each network.
413 //TODO: would implement cleanup logic in case a gateway node is added
414 // and the election is changed
415 return nodeService.completeNodes(GATEWAY).stream()
416 .findFirst().orElse(null);
417 }
418
Jian Lib5ab63c2021-02-03 17:54:28 +0900419 private class InternalNetworkEventListener implements KubevirtNetworkListener {
420
421 private boolean isRelevantHelper() {
422 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
423 }
424
425 @Override
426 public void event(KubevirtNetworkEvent event) {
427 switch (event.type()) {
428 case KUBEVIRT_NETWORK_CREATED:
429 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
430 break;
431 case KUBEVIRT_NETWORK_REMOVED:
432 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
433 break;
434 case KUBEVIRT_NETWORK_UPDATED:
435 default:
436 // do nothing
437 break;
438 }
439 }
440
441 private void processNetworkCreation(KubevirtNetwork network) {
442 if (!isRelevantHelper()) {
443 return;
444 }
445
446 switch (network.type()) {
447 case VXLAN:
448 case GRE:
449 case GENEVE:
450 initIntegrationTunnelBridge(network);
451 break;
452 case FLAT:
Jian Li81b1aab2021-02-17 20:42:15 +0900453 case VLAN:
Daniel Park4063f402021-02-25 09:14:22 +0900454 initGatewayNodeBridge(network, true);
455 break;
Jian Lib5ab63c2021-02-03 17:54:28 +0900456 default:
457 // do nothing
458 break;
459 }
460 }
461
462 private void processNetworkRemoval(KubevirtNetwork network) {
463 if (!isRelevantHelper()) {
464 return;
465 }
466
467 switch (network.type()) {
468 case VXLAN:
469 case GRE:
470 case GENEVE:
471 purgeIntegrationTunnelBridge(network);
472 break;
473 case FLAT:
Jian Li81b1aab2021-02-17 20:42:15 +0900474 case VLAN:
Daniel Park4063f402021-02-25 09:14:22 +0900475 initGatewayNodeBridge(network, false);
476 break;
Jian Lib5ab63c2021-02-03 17:54:28 +0900477 default:
478 // do nothing
479 break;
480 }
481 }
482
483 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
484 if (network.segmentId() == null) {
485 return;
486 }
487
488 nodeService.completeNodes().forEach(n -> {
489 createBridge(n, network);
490 createPatchInterface(n, network);
491 setDefaultRules(n, network);
492 });
493 }
494
495 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
496 if (network.segmentId() == null) {
497 return;
498 }
499
500 nodeService.completeNodes().forEach(n -> {
501 removePatchInterface(n, network);
502 removeBridge(n, network);
503 });
504 }
505 }
506
507 private class InternalNodeEventListener implements KubevirtNodeListener {
508
509 private boolean isRelevantHelper() {
510 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
511 }
512
513 @Override
514 public void event(KubevirtNodeEvent event) {
515 switch (event.type()) {
516 case KUBEVIRT_NODE_COMPLETE:
517 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
518 break;
519 case KUBEVIRT_NODE_INCOMPLETE:
520 case KUBEVIRT_NODE_UPDATED:
521 default:
522 // do nothing
523 break;
524 }
525 }
526
527 private void processNodeCompletion(KubevirtNode node) {
528 if (!isRelevantHelper()) {
529 return;
530 }
531
Daniel Park4063f402021-02-25 09:14:22 +0900532 if (node.type().equals(WORKER)) {
533 for (KubevirtNetwork network : networkService.networks()) {
534 switch (network.type()) {
535 case VXLAN:
536 case GRE:
537 case GENEVE:
538 if (network.segmentId() == null) {
539 continue;
540 }
541 createBridge(node, network);
542 createPatchInterface(node, network);
543 setDefaultRules(node, network);
544 break;
545 case FLAT:
546 case VLAN:
547 default:
548 // do nothing
549 break;
550 }
551 }
552 } else if (node.type().equals(GATEWAY)) {
553 for (KubevirtNetwork network : networkService.networks()) {
554 switch (network.type()) {
555 case FLAT:
556 case VLAN:
557 initGatewayNodeBridge(network, true);
558 break;
559 case VXLAN:
560 case GRE:
561 case GENEVE:
562 default:
563 // do nothing
564 break;
565 }
Jian Lib5ab63c2021-02-03 17:54:28 +0900566 }
567 }
568 }
569 }
570}