blob: a8867f23165dc98aef93772d2011061322d96516 [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;
Daniel Parkb9a22022021-03-04 18:58:47 +090026import org.onlab.packet.MacAddress;
Jian Lib5ab63c2021-02-03 17:54:28 +090027import org.onlab.packet.TpPort;
28import org.onlab.packet.UDP;
29import org.onosproject.cluster.ClusterService;
30import org.onosproject.cluster.LeadershipService;
31import org.onosproject.cluster.NodeId;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
34import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
35import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
36import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
37import org.onosproject.kubevirtnetworking.api.KubevirtNetworkListener;
38import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
Daniel Parkcc8e7462021-03-09 13:37:42 +090039import org.onosproject.kubevirtnetworking.api.KubevirtPort;
40import org.onosproject.kubevirtnetworking.api.KubevirtPortEvent;
41import org.onosproject.kubevirtnetworking.api.KubevirtPortListener;
42import org.onosproject.kubevirtnetworking.api.KubevirtPortService;
Daniel Parkb9a22022021-03-04 18:58:47 +090043import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
44import org.onosproject.kubevirtnetworking.api.KubevirtRouterAdminService;
45import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
46import org.onosproject.kubevirtnetworking.api.KubevirtRouterListener;
Jian Lib5ab63c2021-02-03 17:54:28 +090047import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
48import org.onosproject.kubevirtnode.api.KubevirtNode;
49import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
50import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
51import org.onosproject.kubevirtnode.api.KubevirtNodeService;
52import org.onosproject.net.Device;
53import org.onosproject.net.DeviceId;
54import org.onosproject.net.PortNumber;
55import org.onosproject.net.behaviour.BridgeConfig;
56import org.onosproject.net.behaviour.BridgeDescription;
57import org.onosproject.net.behaviour.BridgeName;
58import org.onosproject.net.behaviour.ControllerInfo;
59import org.onosproject.net.behaviour.DefaultBridgeDescription;
60import org.onosproject.net.behaviour.DefaultPatchDescription;
61import org.onosproject.net.behaviour.InterfaceConfig;
62import org.onosproject.net.behaviour.PatchDescription;
63import org.onosproject.net.device.DeviceAdminService;
Daniel Park4063f402021-02-25 09:14:22 +090064import org.onosproject.net.driver.DriverService;
Jian Lib5ab63c2021-02-03 17:54:28 +090065import org.onosproject.net.flow.DefaultTrafficSelector;
66import org.onosproject.net.flow.DefaultTrafficTreatment;
67import org.onosproject.net.flow.TrafficSelector;
68import org.onosproject.net.flow.TrafficTreatment;
69import org.osgi.service.component.annotations.Activate;
70import org.osgi.service.component.annotations.Component;
71import org.osgi.service.component.annotations.Deactivate;
72import org.osgi.service.component.annotations.Reference;
73import org.osgi.service.component.annotations.ReferenceCardinality;
74import org.slf4j.Logger;
75
76import java.util.List;
77import java.util.Objects;
Daniel Parkb9a22022021-03-04 18:58:47 +090078import java.util.Set;
Jian Lib5ab63c2021-02-03 17:54:28 +090079import java.util.concurrent.ExecutorService;
80
81import static java.lang.Thread.sleep;
82import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Li543fe852021-02-04 17:25:01 +090083import static org.onlab.packet.ICMP.CODE_ECHO_REQEUST;
84import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
85import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
Jian Lib5ab63c2021-02-03 17:54:28 +090086import static org.onlab.util.Tools.groupedThreads;
Daniel Parkcc8e7462021-03-09 13:37:42 +090087import static org.onosproject.kubevirtnetworking.api.Constants.FLAT_TABLE;
88import static org.onosproject.kubevirtnetworking.api.Constants.FORWARDING_TABLE;
Jian Lib5ab63c2021-02-03 17:54:28 +090089import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Daniel Park4063f402021-02-25 09:14:22 +090090import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
Jian Li543fe852021-02-04 17:25:01 +090091import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Lib5ab63c2021-02-03 17:54:28 +090092import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li543fe852021-02-04 17:25:01 +090093import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FORWARDING_RULE;
94import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ICMP_RULE;
Daniel Parkcc8e7462021-03-09 13:37:42 +090095import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
Jian Li543fe852021-02-04 17:25:01 +090096import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ARP_TABLE;
Jian Lib5ab63c2021-02-03 17:54:28 +090097import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_DHCP_TABLE;
98import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
Jian Li543fe852021-02-04 17:25:01 +090099import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Lib5ab63c2021-02-03 17:54:28 +0900100import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li543fe852021-02-04 17:25:01 +0900101import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
102import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Daniel Parkb9a22022021-03-04 18:58:47 +0900103import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.gatewayNodeForSpecifiedRouter;
Daniel Parkcc8e7462021-03-09 13:37:42 +0900104import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtNetwork;
105import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
Daniel Parkb9a22022021-03-04 18:58:47 +0900106import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getbrIntMacAddress;
Jian Lib5ab63c2021-02-03 17:54:28 +0900107import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Jian Li543fe852021-02-04 17:25:01 +0900108import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
109import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
110import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
111import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
112import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
113import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
114import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Lib5ab63c2021-02-03 17:54:28 +0900115import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Park4063f402021-02-25 09:14:22 +0900116import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
117import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Lib5ab63c2021-02-03 17:54:28 +0900118import static org.slf4j.LoggerFactory.getLogger;
119
120/**
121 * Handles kubevirt network events.
122 */
123@Component(immediate = true)
124public class KubevirtNetworkHandler {
125 protected final Logger log = getLogger(getClass());
126 private static final String DEFAULT_OF_PROTO = "tcp";
127 private static final int DEFAULT_OFPORT = 6653;
128 private static final int DPID_BEGIN = 3;
129 private static final long SLEEP_MS = 3000; // we wait 3s for init each node
Jian Li543fe852021-02-04 17:25:01 +0900130 private static final int DEFAULT_TTL = 0xff;
Jian Lib5ab63c2021-02-03 17:54:28 +0900131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY)
133 protected CoreService coreService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY)
136 protected ClusterService clusterService;
137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
139 protected LeadershipService leadershipService;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
142 protected DeviceAdminService deviceService;
143
144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
145 protected KubevirtApiConfigService apiConfigService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
148 protected KubevirtNodeService nodeService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
151 protected KubevirtNetworkService networkService;
152
153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
154 protected KubevirtFlowRuleService flowService;
155
Daniel Park4063f402021-02-25 09:14:22 +0900156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
157 protected DriverService driverService;
158
Daniel Parkb9a22022021-03-04 18:58:47 +0900159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
160 protected KubevirtRouterAdminService kubevirtRouterService;
161
Daniel Parkcc8e7462021-03-09 13:37:42 +0900162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
163 protected KubevirtPortService kubevirtPortService;
164
165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
166 protected KubevirtNetworkService kubevirtNetworkService;
167
168 @Reference(cardinality = ReferenceCardinality.MANDATORY)
169 protected KubevirtNodeService kubevirtNodeService;
170
Jian Lib5ab63c2021-02-03 17:54:28 +0900171 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
172 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
Daniel Parkcc8e7462021-03-09 13:37:42 +0900173 private final KubevirtPortListener portListener = new InternalKubevirtPortListener();
Jian Lib5ab63c2021-02-03 17:54:28 +0900174
Daniel Parkb9a22022021-03-04 18:58:47 +0900175 private final InternalRouterEventListener kubevirtRouterlistener =
176 new InternalRouterEventListener();
177
Jian Lib5ab63c2021-02-03 17:54:28 +0900178 private final ExecutorService eventExecutor = newSingleThreadExecutor(
179 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
180
181 private ApplicationId appId;
182 private NodeId localNodeId;
183
184 @Activate
185 protected void activate() {
186 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
187 localNodeId = clusterService.getLocalNode().id();
Jian Lib5ab63c2021-02-03 17:54:28 +0900188 leadershipService.runForLeadership(appId.name());
189
Daniel Parkcc8e7462021-03-09 13:37:42 +0900190 networkService.addListener(networkListener);
191 nodeService.addListener(nodeListener);
192 kubevirtPortService.addListener(portListener);
Daniel Parkb9a22022021-03-04 18:58:47 +0900193 kubevirtRouterService.addListener(kubevirtRouterlistener);
194
Jian Lib5ab63c2021-02-03 17:54:28 +0900195 log.info("Started");
196 }
197
198 @Deactivate
199 protected void deactivate() {
200 networkService.removeListener(networkListener);
201 nodeService.removeListener(nodeListener);
Daniel Parkcc8e7462021-03-09 13:37:42 +0900202 kubevirtPortService.removeListener(portListener);
Daniel Parkb9a22022021-03-04 18:58:47 +0900203 kubevirtRouterService.removeListener(kubevirtRouterlistener);
Daniel Parkcc8e7462021-03-09 13:37:42 +0900204 leadershipService.withdraw(appId.name());
Jian Lib5ab63c2021-02-03 17:54:28 +0900205 eventExecutor.shutdown();
206
207 log.info("Stopped");
208 }
209
210 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
211
212 Device tunBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
213 if (tunBridge != null) {
214 log.warn("The tunnel bridge {} already exists at node {}",
215 network.tenantBridgeName(), node.hostname());
216 setDefaultRules(node, network);
217 return;
218 }
219
220 Device device = deviceService.getDevice(node.ovsdb());
221
222 IpAddress serverIp = apiConfigService.apiConfig().ipAddress();
223 ControllerInfo controlInfo =
224 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
225 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
226
227 String dpid = network.tenantDeviceId(
228 node.hostname()).toString().substring(DPID_BEGIN);
229
230 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
231 .name(network.tenantBridgeName())
232 .failMode(BridgeDescription.FailMode.SECURE)
233 .datapathId(dpid)
234 .disableInBand()
235 .controllers(controllers);
236
237 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
238 bridgeConfig.addBridge(builder.build());
239 }
240
241 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
242 Device device = deviceService.getDevice(node.ovsdb());
243
244 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
245
246 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
247 bridgeConfig.deleteBridge(bridgeName);
248 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
249 }
250
Daniel Parkcc8e7462021-03-09 13:37:42 +0900251 private void createPatchInterfaceInCaseOveray(KubevirtNode node, KubevirtNetwork network) {
Jian Lib5ab63c2021-02-03 17:54:28 +0900252 Device device = deviceService.getDevice(node.ovsdb());
253
254 if (device == null || !device.is(InterfaceConfig.class)) {
255 log.error("Failed to create patch interface on {}", node.ovsdb());
256 return;
257 }
258
259 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
260
Jian Li543fe852021-02-04 17:25:01 +0900261 String tenantToTunIntf =
262 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
263 String tunToTenantIntf =
264 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Lib5ab63c2021-02-03 17:54:28 +0900265
Jian Li543fe852021-02-04 17:25:01 +0900266 // tenant bridge -> tunnel bridge
267 PatchDescription brTenantTunPatchDesc =
Jian Lib5ab63c2021-02-03 17:54:28 +0900268 DefaultPatchDescription.builder()
269 .deviceId(network.tenantBridgeName())
Jian Li543fe852021-02-04 17:25:01 +0900270 .ifaceName(tenantToTunIntf)
271 .peer(tunToTenantIntf)
Jian Lib5ab63c2021-02-03 17:54:28 +0900272 .build();
273
Jian Li543fe852021-02-04 17:25:01 +0900274 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Lib5ab63c2021-02-03 17:54:28 +0900275
Jian Li543fe852021-02-04 17:25:01 +0900276 // tunnel bridge -> tenant bridge
277 PatchDescription brTunTenantPatchDesc =
Jian Lib5ab63c2021-02-03 17:54:28 +0900278 DefaultPatchDescription.builder()
279 .deviceId(TUNNEL_BRIDGE)
Jian Li543fe852021-02-04 17:25:01 +0900280 .ifaceName(tunToTenantIntf)
281 .peer(tenantToTunIntf)
Jian Lib5ab63c2021-02-03 17:54:28 +0900282 .build();
Jian Li543fe852021-02-04 17:25:01 +0900283 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
Jian Lib5ab63c2021-02-03 17:54:28 +0900284 }
285
286 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
287 Device device = deviceService.getDevice(node.ovsdb());
288
289 if (device == null || !device.is(InterfaceConfig.class)) {
290 log.error("Failed to create patch interface on {}", node.ovsdb());
291 return;
292 }
293
294 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
295
Jian Li543fe852021-02-04 17:25:01 +0900296 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Lib5ab63c2021-02-03 17:54:28 +0900297
298 ifaceConfig.removePatchMode(tunToIntIntf);
299 }
300
Daniel Parkcc8e7462021-03-09 13:37:42 +0900301 private void setArpRules(KubevirtNode node, KubevirtNetwork network) {
302
303 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
304 if (router == null) {
305 return;
306 }
307
308 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
309 if (electedGw == null) {
310 return;
311 }
312
313 setGatewayArpRuleForInternalNetworkInCaseOveray(network, TENANT_ARP_TABLE, electedGw.intgBridge(),
314 network.tenantDeviceId(node.hostname()), true);
315 }
316
317 private void setIcmpRules(KubevirtNode node, KubevirtNetwork network) {
318 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
319 if (router == null) {
320 return;
321 }
322
323 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
324 if (electedGw == null) {
325 return;
326 }
327
328 setGatewayIcmpRuleForInternalNetworkInCaseOveray(network, TENANT_ICMP_TABLE, electedGw.intgBridge(),
329 network.tenantDeviceId(node.hostname()), true);
330 }
331
332
Jian Lib5ab63c2021-02-03 17:54:28 +0900333 private void setDefaultRules(KubevirtNode node, KubevirtNetwork network) {
334 DeviceId deviceId = network.tenantDeviceId(node.hostname());
335
336 while (!deviceService.isAvailable(deviceId)) {
337 log.warn("Device {} is not ready for installing rules", deviceId);
338
339 try {
340 sleep(SLEEP_MS);
341 } catch (InterruptedException e) {
342 log.error("Failed to check device availability", e);
343 }
344 }
345
346 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li543fe852021-02-04 17:25:01 +0900347 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
348 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
349 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Lib5ab63c2021-02-03 17:54:28 +0900350
351 setDhcpRule(deviceId, true);
352 setForwardingRule(deviceId, true);
353
354 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
355 }
356
357 private void setDhcpRule(DeviceId deviceId, boolean install) {
358 TrafficSelector selector = DefaultTrafficSelector.builder()
359 .matchEthType(Ethernet.TYPE_IPV4)
360 .matchIPProtocol(IPv4.PROTOCOL_UDP)
361 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
362 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
363 .build();
364
365 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
366 .punt()
367 .build();
368
369 flowService.setRule(
370 appId,
371 deviceId,
372 selector,
373 treatment,
374 PRIORITY_DHCP_RULE,
375 TENANT_DHCP_TABLE,
376 install);
377 }
378
Jian Li543fe852021-02-04 17:25:01 +0900379 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Lib5ab63c2021-02-03 17:54:28 +0900380 TrafficSelector selector = DefaultTrafficSelector.builder().build();
381 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
382 .setOutput(PortNumber.NORMAL)
383 .build();
384
385 flowService.setRule(
386 appId,
387 deviceId,
388 selector,
389 treatment,
Jian Li543fe852021-02-04 17:25:01 +0900390 PRIORITY_FORWARDING_RULE,
Jian Lib5ab63c2021-02-03 17:54:28 +0900391 TENANT_FORWARDING_TABLE,
392 install);
393 }
394
Daniel Parkb9a22022021-03-04 18:58:47 +0900395 private void initGatewayNodeForInternalNetwork(KubevirtNetwork network,
396 KubevirtRouter router,
397 KubevirtNode electedGateway,
398 boolean install) {
Daniel Parkcc8e7462021-03-09 13:37:42 +0900399 switch (network.type()) {
400 case VXLAN:
401 case GRE:
402 case GENEVE:
403
404 kubevirtNodeService.completeNodes(WORKER).forEach(node -> {
405 setGatewayArpRuleForInternalNetworkInCaseOveray(network, TENANT_ARP_TABLE,
406 electedGateway.intgBridge(),
407 network.tenantDeviceId(node.hostname()), install);
408 setGatewayIcmpRuleForInternalNetworkInCaseOveray(network, TENANT_ICMP_TABLE,
409 electedGateway.intgBridge(),
410 network.tenantDeviceId(node.hostname()), install);
411 });
412 break;
413 case FLAT:
414 case VLAN:
415 setGatewayArpRuleForInternalNetworkInCaseVlanFlat(network, PRE_FLAT_TABLE,
416 electedGateway.intgBridge(), install);
417 setGatewayIcmpRuleForInternalNetworkInCaseVlanFlat(network, PRE_FLAT_TABLE,
418 electedGateway.intgBridge(), install);
419 setGatewayInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
420 break;
421 default:
422 // do nothing
423 break;
424 }
425
Daniel Parkb9a22022021-03-04 18:58:47 +0900426 }
427
Daniel Parkcc8e7462021-03-09 13:37:42 +0900428 private void setGatewayIcmpRuleForInternalNetworkInCaseOveray(KubevirtNetwork network,
429 int tableNum,
430 DeviceId gwDeviceId,
431 DeviceId tenantDeviceId,
432 boolean install) {
433 MacAddress brIntMacAddress = getbrIntMacAddress(deviceService, gwDeviceId);
Daniel Parkb9a22022021-03-04 18:58:47 +0900434
Daniel Parkcc8e7462021-03-09 13:37:42 +0900435 if (brIntMacAddress == null) {
436 log.warn("Setting gateway ICMP rule for internal network because " +
437 "there's no br-int port for device {}", gwDeviceId);
438 return;
439 }
440
441 Device device = deviceService.getDevice(tenantDeviceId);
442
443 if (device == null) {
444 log.warn("Setting gateway icmp rule for internal network because " +
445 "there's no tenant device for {} to install gateway arp rule",
446 tenantDeviceId);
447 return;
448 }
449
450
451 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
452 .matchEthType(Ethernet.TYPE_IPV4)
453 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
454 .matchIcmpType(TYPE_ECHO_REQUEST)
455 .matchIcmpCode(CODE_ECHO_REQEUST)
456 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
457
458 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
459 .extension(buildMoveEthSrcToDstExtension(device), device.id())
460 .extension(buildMoveIpSrcToDstExtension(device), device.id())
461 .extension(buildLoadExtension(device,
462 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
463 .extension(buildLoadExtension(device,
464 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
465 .setIpSrc(network.gatewayIp())
466 .setEthSrc(brIntMacAddress)
467 .setOutput(PortNumber.IN_PORT);
468
469 flowService.setRule(
470 appId,
471 tenantDeviceId,
472 sBuilder.build(),
473 tBuilder.build(),
474 PRIORITY_ICMP_RULE,
475 tableNum,
476 install);
477 }
478
479 private void setGatewayArpRuleForInternalNetworkInCaseOveray(KubevirtNetwork network,
480 int tableNum,
481 DeviceId gwDeviceId,
482 DeviceId tenantDeviceId,
483 boolean install) {
484
485 MacAddress brIntMacAddress = getbrIntMacAddress(deviceService, gwDeviceId);
486
487 if (brIntMacAddress == null) {
488 log.warn("Setting gateway arp rule for internal network because " +
489 "there's no br-int port for device {}", gwDeviceId);
490 return;
491 }
492
493 Device device = deviceService.getDevice(tenantDeviceId);
494
495 if (device == null) {
496 log.warn("Setting gateway arp rule for internal network because " +
497 "there's no tenant device for {} to install gateway arp rule",
498 tenantDeviceId);
499 return;
500 }
501
502
503 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
504 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
505 .matchArpOp(ARP.OP_REQUEST)
506 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
507
508 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
509 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
510 .extension(buildMoveArpShaToThaExtension(device), device.id())
511 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
512 .setArpOp(ARP.OP_REPLY)
513 .setArpSha(brIntMacAddress)
514 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
515 .setEthSrc(brIntMacAddress)
516 .setOutput(PortNumber.IN_PORT);
517
518 flowService.setRule(
519 appId,
520 device.id(),
521 sBuilder.build(),
522 tBuilder.build(),
523 PRIORITY_ARP_GATEWAY_RULE,
524 tableNum,
525 install
526 );
527 }
528
529 private void setGatewayInterNetworkRoutingWithinSameRouter(
530 KubevirtNetwork network, KubevirtRouter router, KubevirtNode gatewayNode, boolean install) {
Daniel Parkb9a22022021-03-04 18:58:47 +0900531 router.internal().forEach(srcNetwork -> {
Daniel Parkcc8e7462021-03-09 13:37:42 +0900532 if (srcNetwork.equals(network.networkId())
533 || kubevirtNetworkService.network(srcNetwork) == null) {
Daniel Parkb9a22022021-03-04 18:58:47 +0900534 return;
535 }
536
Daniel Parkcc8e7462021-03-09 13:37:42 +0900537 kubevirtPortService.ports(network.networkId()).forEach(port -> {
538 setGatewayInterNetworkRoutingFromNetworkToPort(kubevirtNetworkService.network(srcNetwork),
539 port, gatewayNode, install);
540 });
Daniel Parkb9a22022021-03-04 18:58:47 +0900541 });
542 }
543
Daniel Parkcc8e7462021-03-09 13:37:42 +0900544 private void setGatewayInterNetworkRoutingFromNetworkToPort(KubevirtNetwork srcNetwork, KubevirtPort dstPort,
545 KubevirtNode gatewayNode, boolean install) {
Jian Li543fe852021-02-04 17:25:01 +0900546
Daniel Parkcc8e7462021-03-09 13:37:42 +0900547 Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
548
549 if (gwDevice == null) {
550 log.warn("Failed to set internal network routing rule because " +
551 "there's no device Id for device {}", gatewayNode.intgBridge());
552 return;
553 }
554
555 MacAddress brIntMacAddress = getbrIntMacAddress(deviceService, gatewayNode.intgBridge());
Daniel Parkb9a22022021-03-04 18:58:47 +0900556
557 if (brIntMacAddress == null) {
Daniel Parkcc8e7462021-03-09 13:37:42 +0900558 log.warn("Failed to set internal network routing rule because " +
559 "there's no br-int port for device {}", gatewayNode.intgBridge());
560 return;
561 }
562
563 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
564 .matchEthType(Ethernet.TYPE_IPV4)
565 .matchEthDst(brIntMacAddress)
566 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
567 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
568
569 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
570 .setEthSrc(brIntMacAddress)
571 .setEthDst(dstPort.macAddress())
572 .transition(FORWARDING_TABLE)
573 .build();
574
575 flowService.setRule(
576 appId,
577 gwDevice.id(),
578 sBuilder.build(),
579 treatment,
580 PRIORITY_INTERNAL_ROUTING_RULE,
581 FLAT_TABLE,
582 install
583 );
584 }
585
586 private void setGatewayArpRuleForInternalNetworkInCaseVlanFlat(KubevirtNetwork network,
587 int tableNum, DeviceId gwDeviceId, boolean install) {
588
589
590 Device device = deviceService.getDevice(gwDeviceId);
591 MacAddress brIntMacAddress = getbrIntMacAddress(deviceService, gwDeviceId);
592
593 if (brIntMacAddress == null) {
594 log.warn("Setting gateway arp rule for internal network because " +
595 "there's no br-int port for device {}", gwDeviceId);
Daniel Parkb9a22022021-03-04 18:58:47 +0900596 return;
597 }
598
Jian Li543fe852021-02-04 17:25:01 +0900599 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
600 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
601 .matchArpOp(ARP.OP_REQUEST)
602 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
603
604 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
605 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
606 .extension(buildMoveArpShaToThaExtension(device), device.id())
607 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
608 .setArpOp(ARP.OP_REPLY)
Daniel Parkb9a22022021-03-04 18:58:47 +0900609 .setArpSha(brIntMacAddress)
Jian Li543fe852021-02-04 17:25:01 +0900610 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkb9a22022021-03-04 18:58:47 +0900611 .setEthSrc(brIntMacAddress)
Jian Li543fe852021-02-04 17:25:01 +0900612 .setOutput(PortNumber.IN_PORT);
613
614 flowService.setRule(
615 appId,
616 device.id(),
617 sBuilder.build(),
618 tBuilder.build(),
619 PRIORITY_ARP_GATEWAY_RULE,
Daniel Park4063f402021-02-25 09:14:22 +0900620 tableNum,
Jian Li543fe852021-02-04 17:25:01 +0900621 install
622 );
623 }
624
Daniel Parkb9a22022021-03-04 18:58:47 +0900625 /**
626 * Sends ICMP echo reply for the ICMP echo request from the kubevirt VM.
627 *
628 * @param network kubevirt network
629 * @param tableNum flow table number
630 * @param deviceId device id of the selected gateway for the network
631 * @param install install if true, remove otherwise
632 */
Daniel Parkcc8e7462021-03-09 13:37:42 +0900633 private void setGatewayIcmpRuleForInternalNetworkInCaseVlanFlat(KubevirtNetwork network,
634 int tableNum, DeviceId deviceId, boolean install) {
Daniel Parkb9a22022021-03-04 18:58:47 +0900635 MacAddress brIntMacAddress = getbrIntMacAddress(deviceService, deviceId);
636
637 if (brIntMacAddress == null) {
638 log.error("Setting gateway ICMP rule for internal network because " +
639 "there's no br-int port for device {}", deviceId);
640 return;
641 }
642
Jian Li543fe852021-02-04 17:25:01 +0900643 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
644 .matchEthType(Ethernet.TYPE_IPV4)
645 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
646 .matchIcmpType(TYPE_ECHO_REQUEST)
647 .matchIcmpCode(CODE_ECHO_REQEUST)
648 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
649
650 Device device = deviceService.getDevice(deviceId);
651 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
652 .extension(buildMoveEthSrcToDstExtension(device), device.id())
653 .extension(buildMoveIpSrcToDstExtension(device), device.id())
654 .extension(buildLoadExtension(device,
655 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
656 .extension(buildLoadExtension(device,
657 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
658 .setIpSrc(network.gatewayIp())
Daniel Parkb9a22022021-03-04 18:58:47 +0900659 .setEthSrc(brIntMacAddress)
Jian Li543fe852021-02-04 17:25:01 +0900660 .setOutput(PortNumber.IN_PORT);
661
662 flowService.setRule(
663 appId,
664 deviceId,
665 sBuilder.build(),
666 tBuilder.build(),
667 PRIORITY_ICMP_RULE,
Daniel Park4063f402021-02-25 09:14:22 +0900668 tableNum,
Jian Li543fe852021-02-04 17:25:01 +0900669 install);
670 }
671
Daniel Parkb9a22022021-03-04 18:58:47 +0900672 private class InternalRouterEventListener implements KubevirtRouterListener {
673 private boolean isRelevantHelper() {
674 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Daniel Park4063f402021-02-25 09:14:22 +0900675 }
676
Daniel Parkb9a22022021-03-04 18:58:47 +0900677 @Override
678 public void event(KubevirtRouterEvent event) {
679 switch (event.type()) {
680 case KUBEVIRT_ROUTER_CREATED:
681 eventExecutor.execute(() -> processRouterCreation(event.subject()));
682 break;
683 case KUBEVIRT_ROUTER_REMOVED:
684 eventExecutor.execute(() -> processRouterDeletion(event.subject()));
685 break;
686 case KUBEVIRT_ROUTER_UPDATED:
687 eventExecutor.execute(() -> processRouterUpdate(event.subject()));
688 break;
689 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_ATTACHED:
690 eventExecutor.execute(() -> processRouterInternalNetworksAttached(event.subject(),
691 event.internal()));
692 break;
693 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_DETACHED:
694 eventExecutor.execute(() -> processRouterInternalNetworksDetached(event.subject(),
695 event.internal()));
696 break;
697 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
698 eventExecutor.execute(() -> processRouterGatewayNodeAttached(event.subject(),
699 event.gateway()));
700 break;
701 case KUBEVIRT_GATEWAY_NODE_DETACHED:
702 eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(),
703 event.gateway()));
704 break;
705 case KUBEVIRT_GATEWAY_NODE_CHANGED:
706 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
707 event.gateway()));
708 break;
Daniel Park4063f402021-02-25 09:14:22 +0900709
Daniel Parkb9a22022021-03-04 18:58:47 +0900710 default:
711 //do nothing
712 break;
713 }
714 }
715
716 private void processRouterCreation(KubevirtRouter router) {
717 // When a router is created, we performs the election process to associate the router
718 // to the specific gateway. After the election, KubevirtNetwork handler installs bunch of rules
719 // to elected gateway node so that VMs associated to the router can ping to their gateway IP.
720 // SNAT and floating ip rule setup is out of this handler's scope and would be done with the other handlers
721 if (!isRelevantHelper()) {
722 return;
723 }
724 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
725 if (electedGw == null) {
726 return;
727 }
728
729 router.internal().forEach(networkName -> {
730 KubevirtNetwork network = networkService.network(networkName);
731
732 if (network != null) {
733 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
734 }
735 });
736 kubevirtRouterService.updateRouter(router.updatedElectedGateway(electedGw.hostname()));
737 }
738
739 private void processRouterDeletion(KubevirtRouter router) {
740 if (!isRelevantHelper()) {
741 return;
742 }
743 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
744 if (electedGw == null) {
745 return;
746 }
747
748 router.internal().forEach(networkName -> {
749 KubevirtNetwork network = networkService.network(networkName);
750
751 if (network != null) {
752 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
753 }
754 });
755 }
756
757 private void processRouterUpdate(KubevirtRouter router) {
758 if (!isRelevantHelper()) {
759 return;
760 }
761 if (router.electedGateway() == null) {
762 return;
763 }
764
765 KubevirtNode electedGw = nodeService.node(router.electedGateway());
766
767 router.internal().forEach(networkName -> {
768 KubevirtNetwork network = networkService.network(networkName);
769
770 if (network != null) {
771 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
772 }
773 });
774 }
775
776 private void processRouterInternalNetworksAttached(KubevirtRouter router,
777 Set<String> attachedInternalNetworks) {
778 if (!isRelevantHelper()) {
779 return;
780 }
781 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
782 if (electedGw == null) {
783 return;
784 }
785
786 attachedInternalNetworks.forEach(networkName -> {
787 KubevirtNetwork network = networkService.network(networkName);
788
789 if (network != null) {
790 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
791 }
792 });
793 }
794
795 private void processRouterInternalNetworksDetached(KubevirtRouter router,
796 Set<String> detachedInternalNetworks) {
797 if (!isRelevantHelper()) {
798 return;
799 }
800 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
801 if (electedGw == null) {
802 return;
803 }
804
805 detachedInternalNetworks.forEach(networkName -> {
806 KubevirtNetwork network = networkService.network(networkName);
807
808 if (network != null) {
809 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
810 }
Daniel Parkb9a22022021-03-04 18:58:47 +0900811
Daniel Parkcc8e7462021-03-09 13:37:42 +0900812 removeDetachedInternalNetworkRules(network, router, electedGw);
813 });
814 }
815
816 private void removeDetachedInternalNetworkRules(KubevirtNetwork removedNetwork, KubevirtRouter router,
817 KubevirtNode electedGw) {
818 router.internal().forEach(networkName -> {
819 kubevirtPortService.ports(networkName).forEach(kubevirtPort -> {
820 setGatewayInterNetworkRoutingFromNetworkToPort(
821 removedNetwork, kubevirtPort, electedGw, false);
822 });
823 });
Daniel Parkb9a22022021-03-04 18:58:47 +0900824 }
825
826 private void processRouterGatewayNodeAttached(KubevirtRouter router,
827 String associatedGateway) {
828 if (!isRelevantHelper()) {
829 return;
830 }
831
832 KubevirtNode gatewayNode = nodeService.node(associatedGateway);
833 if (gatewayNode == null) {
834 return;
835 }
836
837 router.internal().forEach(networkName -> {
838 KubevirtNetwork network = networkService.network(networkName);
839
840 if (network != null) {
841 initGatewayNodeForInternalNetwork(network, router, gatewayNode, true);
842 }
843 });
844 }
845
846 private void processRouterGatewayNodeDetached(KubevirtRouter router,
847 String disAssociatedGateway) {
848 if (!isRelevantHelper()) {
849 return;
850 }
851
852 KubevirtNode gatewayNode = nodeService.node(disAssociatedGateway);
853 if (gatewayNode == null) {
854 return;
855 }
856
857 router.internal().forEach(networkName -> {
858 KubevirtNetwork network = networkService.network(networkName);
859
860 if (network != null) {
861 initGatewayNodeForInternalNetwork(network, router, gatewayNode, false);
862 }
863 });
864 }
865
866 private void processRouterGatewayNodeChanged(KubevirtRouter router,
867 String disAssociatedGateway) {
868 if (!isRelevantHelper()) {
869 return;
870 }
871
872 KubevirtNode oldGatewayNode = nodeService.node(disAssociatedGateway);
873 if (oldGatewayNode == null) {
874 return;
875 }
876
877 router.internal().forEach(networkName -> {
878 KubevirtNetwork network = networkService.network(networkName);
879
880 if (network != null) {
881 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, false);
882 }
883 });
884
885 KubevirtNode newGatewayNode = nodeService.node(router.electedGateway());
886 if (newGatewayNode == null) {
887 return;
888 }
889
890 router.internal().forEach(networkName -> {
891 KubevirtNetwork network = networkService.network(networkName);
892
893 if (network != null) {
894 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, true);
895 }
896 });
897 }
Daniel Park4063f402021-02-25 09:14:22 +0900898 }
899
Jian Lib5ab63c2021-02-03 17:54:28 +0900900 private class InternalNetworkEventListener implements KubevirtNetworkListener {
901
902 private boolean isRelevantHelper() {
903 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
904 }
905
906 @Override
907 public void event(KubevirtNetworkEvent event) {
908 switch (event.type()) {
909 case KUBEVIRT_NETWORK_CREATED:
910 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
911 break;
912 case KUBEVIRT_NETWORK_REMOVED:
913 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
914 break;
915 case KUBEVIRT_NETWORK_UPDATED:
916 default:
917 // do nothing
918 break;
919 }
920 }
921
922 private void processNetworkCreation(KubevirtNetwork network) {
923 if (!isRelevantHelper()) {
924 return;
925 }
926
927 switch (network.type()) {
928 case VXLAN:
929 case GRE:
930 case GENEVE:
931 initIntegrationTunnelBridge(network);
932 break;
933 case FLAT:
Jian Li81b1aab2021-02-17 20:42:15 +0900934 case VLAN:
Daniel Park4063f402021-02-25 09:14:22 +0900935 break;
Jian Lib5ab63c2021-02-03 17:54:28 +0900936 default:
937 // do nothing
938 break;
939 }
940 }
941
942 private void processNetworkRemoval(KubevirtNetwork network) {
943 if (!isRelevantHelper()) {
944 return;
945 }
946
947 switch (network.type()) {
948 case VXLAN:
949 case GRE:
950 case GENEVE:
951 purgeIntegrationTunnelBridge(network);
952 break;
953 case FLAT:
Jian Li81b1aab2021-02-17 20:42:15 +0900954 case VLAN:
Daniel Park4063f402021-02-25 09:14:22 +0900955 break;
Jian Lib5ab63c2021-02-03 17:54:28 +0900956 default:
957 // do nothing
958 break;
959 }
960 }
961
962 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
963 if (network.segmentId() == null) {
964 return;
965 }
966
967 nodeService.completeNodes().forEach(n -> {
968 createBridge(n, network);
Daniel Parkcc8e7462021-03-09 13:37:42 +0900969 createPatchInterfaceInCaseOveray(n, network);
Jian Lib5ab63c2021-02-03 17:54:28 +0900970 setDefaultRules(n, network);
971 });
972 }
973
974 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
975 if (network.segmentId() == null) {
976 return;
977 }
978
979 nodeService.completeNodes().forEach(n -> {
980 removePatchInterface(n, network);
981 removeBridge(n, network);
982 });
983 }
984 }
985
986 private class InternalNodeEventListener implements KubevirtNodeListener {
987
988 private boolean isRelevantHelper() {
989 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
990 }
991
992 @Override
993 public void event(KubevirtNodeEvent event) {
994 switch (event.type()) {
995 case KUBEVIRT_NODE_COMPLETE:
996 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
997 break;
Daniel Parkb9a22022021-03-04 18:58:47 +0900998 case KUBEVIRT_NODE_REMOVED:
999 eventExecutor.execute(() -> processNodeDeletion(event.subject()));
1000 break;
Jian Lib5ab63c2021-02-03 17:54:28 +09001001 case KUBEVIRT_NODE_INCOMPLETE:
1002 case KUBEVIRT_NODE_UPDATED:
1003 default:
1004 // do nothing
1005 break;
1006 }
1007 }
1008
1009 private void processNodeCompletion(KubevirtNode node) {
1010 if (!isRelevantHelper()) {
1011 return;
1012 }
1013
Daniel Park4063f402021-02-25 09:14:22 +09001014 if (node.type().equals(WORKER)) {
1015 for (KubevirtNetwork network : networkService.networks()) {
1016 switch (network.type()) {
1017 case VXLAN:
1018 case GRE:
1019 case GENEVE:
1020 if (network.segmentId() == null) {
1021 continue;
1022 }
1023 createBridge(node, network);
Daniel Parkcc8e7462021-03-09 13:37:42 +09001024 createPatchInterfaceInCaseOveray(node, network);
Daniel Park4063f402021-02-25 09:14:22 +09001025 setDefaultRules(node, network);
Daniel Parkcc8e7462021-03-09 13:37:42 +09001026 setArpRules(node, network);
1027 setIcmpRules(node, network);
1028
Daniel Park4063f402021-02-25 09:14:22 +09001029 break;
1030 case FLAT:
1031 case VLAN:
1032 default:
1033 // do nothing
1034 break;
1035 }
1036 }
1037 } else if (node.type().equals(GATEWAY)) {
Daniel Parkb9a22022021-03-04 18:58:47 +09001038 updateGatewayNodeForRouter();
Daniel Park4063f402021-02-25 09:14:22 +09001039 for (KubevirtNetwork network : networkService.networks()) {
1040 switch (network.type()) {
1041 case FLAT:
1042 case VLAN:
Daniel Park4063f402021-02-25 09:14:22 +09001043 break;
1044 case VXLAN:
1045 case GRE:
1046 case GENEVE:
1047 default:
1048 // do nothing
1049 break;
1050 }
Jian Lib5ab63c2021-02-03 17:54:28 +09001051 }
1052 }
1053 }
Daniel Parkb9a22022021-03-04 18:58:47 +09001054
1055 private void processNodeDeletion(KubevirtNode node) {
1056 if (!isRelevantHelper()) {
1057 return;
1058 }
1059
1060 if (node.type().equals(GATEWAY)) {
1061 updateGatewayNodeForRouter();
1062 for (KubevirtNetwork network : networkService.networks()) {
1063 switch (network.type()) {
1064 case FLAT:
1065 case VLAN:
1066 break;
1067 case VXLAN:
1068 case GRE:
1069 case GENEVE:
1070 default:
1071 // do nothing
1072 break;
1073 }
1074 }
1075 }
1076 }
1077
1078 private void updateGatewayNodeForRouter() {
1079 kubevirtRouterService.routers().forEach(router -> {
1080 KubevirtNode newGwNode = gatewayNodeForSpecifiedRouter(nodeService, router);
1081
1082 if (newGwNode == null) {
1083 return;
1084 }
1085 kubevirtRouterService.updateRouter(router.updatedElectedGateway(newGwNode.hostname()));
1086 });
1087 }
Jian Lib5ab63c2021-02-03 17:54:28 +09001088 }
Daniel Parkcc8e7462021-03-09 13:37:42 +09001089
1090 private class InternalKubevirtPortListener implements KubevirtPortListener {
1091
1092 private boolean isRelevantHelper() {
1093 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1094 }
1095
1096 @Override
1097 public void event(KubevirtPortEvent event) {
1098 switch (event.type()) {
1099 case KUBEVIRT_PORT_CREATED:
1100 eventExecutor.execute(() -> processPortCreation(event.subject()));
1101 break;
1102 case KUBEVIRT_PORT_UPDATED:
1103 eventExecutor.execute(() -> processPortUpdate(event.subject()));
1104 break;
1105 case KUBEVIRT_PORT_REMOVED:
1106 eventExecutor.execute(() -> processPortDeletion(event.subject()));
1107 break;
1108 default:
1109 //do nothing
1110 break;
1111 }
1112 }
1113
1114 private void processPortCreation(KubevirtPort kubevirtPort) {
1115 if (!isRelevantHelper()) {
1116 return;
1117 }
1118
1119 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1120 if (router == null) {
1121 return;
1122 }
1123
1124 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1125
1126 if (gwNode != null) {
1127
1128 router.internal().forEach(srcNetwork -> {
1129 if (srcNetwork.equals(kubevirtPort.networkId())
1130 || kubevirtNetworkService.network(srcNetwork) == null) {
1131 return;
1132 }
1133 setGatewayInterNetworkRoutingFromNetworkToPort(kubevirtNetworkService.network(srcNetwork),
1134 kubevirtPort, gwNode, true);
1135 });
1136 }
1137 }
1138
1139 private void processPortUpdate(KubevirtPort kubevirtPort) {
1140 if (!isRelevantHelper()) {
1141 return;
1142 }
1143
1144 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1145 if (router == null) {
1146 return;
1147 }
1148
1149 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1150
1151 if (gwNode != null) {
1152
1153 router.internal().forEach(srcNetwork -> {
1154 if (srcNetwork.equals(kubevirtPort.networkId())
1155 || kubevirtNetworkService.network(srcNetwork) == null) {
1156 return;
1157 }
1158 setGatewayInterNetworkRoutingFromNetworkToPort(kubevirtNetworkService.network(srcNetwork),
1159 kubevirtPort, gwNode, true);
1160 });
1161 }
1162 }
1163
1164 private void processPortDeletion(KubevirtPort kubevirtPort) {
1165 if (!isRelevantHelper()) {
1166 return;
1167 }
1168
1169 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1170 if (router == null) {
1171 return;
1172 }
1173
1174 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1175
1176 if (gwNode != null) {
1177
1178 router.internal().forEach(srcNetwork -> {
1179 if (srcNetwork.equals(kubevirtPort.networkId())
1180 || kubevirtNetworkService.network(srcNetwork) == null) {
1181 return;
1182 }
1183 setGatewayInterNetworkRoutingFromNetworkToPort(kubevirtNetworkService.network(srcNetwork),
1184 kubevirtPort, gwNode, false);
1185 });
1186 }
1187
1188 }
1189 }
Jian Lib5ab63c2021-02-03 17:54:28 +09001190}