blob: 1821564f562a56780b00da72fa98bed2192c3348 [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;
Daniel Park2884b232021-03-04 18:58:47 +090026import org.onlab.packet.MacAddress;
Jian Li556709c2021-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;
Jian Lifc7e6cf2021-04-08 11:13:24 +090036import org.onosproject.kubevirtnetworking.api.KubevirtNetworkAdminService;
Jian Li556709c2021-02-03 17:54:28 +090037import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
38import org.onosproject.kubevirtnetworking.api.KubevirtNetworkListener;
39import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
Daniel Parkbabde9c2021-03-09 13:37:42 +090040import org.onosproject.kubevirtnetworking.api.KubevirtPort;
41import org.onosproject.kubevirtnetworking.api.KubevirtPortEvent;
42import org.onosproject.kubevirtnetworking.api.KubevirtPortListener;
43import org.onosproject.kubevirtnetworking.api.KubevirtPortService;
Daniel Park2884b232021-03-04 18:58:47 +090044import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
45import org.onosproject.kubevirtnetworking.api.KubevirtRouterAdminService;
46import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
47import org.onosproject.kubevirtnetworking.api.KubevirtRouterListener;
Jian Li556709c2021-02-03 17:54:28 +090048import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
49import org.onosproject.kubevirtnode.api.KubevirtNode;
50import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
51import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
52import org.onosproject.kubevirtnode.api.KubevirtNodeService;
53import org.onosproject.net.Device;
54import org.onosproject.net.DeviceId;
55import org.onosproject.net.PortNumber;
56import org.onosproject.net.behaviour.BridgeConfig;
57import org.onosproject.net.behaviour.BridgeDescription;
58import org.onosproject.net.behaviour.BridgeName;
59import org.onosproject.net.behaviour.ControllerInfo;
60import org.onosproject.net.behaviour.DefaultBridgeDescription;
61import org.onosproject.net.behaviour.DefaultPatchDescription;
62import org.onosproject.net.behaviour.InterfaceConfig;
63import org.onosproject.net.behaviour.PatchDescription;
64import org.onosproject.net.device.DeviceAdminService;
Daniel Parka8968802021-02-25 09:14:22 +090065import org.onosproject.net.driver.DriverService;
Jian Li556709c2021-02-03 17:54:28 +090066import org.onosproject.net.flow.DefaultTrafficSelector;
67import org.onosproject.net.flow.DefaultTrafficTreatment;
68import org.onosproject.net.flow.TrafficSelector;
69import org.onosproject.net.flow.TrafficTreatment;
70import org.osgi.service.component.annotations.Activate;
71import org.osgi.service.component.annotations.Component;
72import org.osgi.service.component.annotations.Deactivate;
73import org.osgi.service.component.annotations.Reference;
74import org.osgi.service.component.annotations.ReferenceCardinality;
75import org.slf4j.Logger;
76
77import java.util.List;
78import java.util.Objects;
Daniel Park2884b232021-03-04 18:58:47 +090079import java.util.Set;
Jian Li556709c2021-02-03 17:54:28 +090080import java.util.concurrent.ExecutorService;
81
82import static java.lang.Thread.sleep;
83import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Li858ccd72021-02-04 17:25:01 +090084import static org.onlab.packet.ICMP.CODE_ECHO_REQEUST;
85import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
86import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
Jian Li556709c2021-02-03 17:54:28 +090087import static org.onlab.util.Tools.groupedThreads;
Daniel Parkbabde9c2021-03-09 13:37:42 +090088import static org.onosproject.kubevirtnetworking.api.Constants.FORWARDING_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090089import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Daniel Parka8968802021-02-25 09:14:22 +090090import static org.onosproject.kubevirtnetworking.api.Constants.PRE_FLAT_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +090091import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li556709c2021-02-03 17:54:28 +090092import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li858ccd72021-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 Parkbabde9c2021-03-09 13:37:42 +090095import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
Daniel Parkf3136042021-03-10 07:49:11 +090096import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_TUNNEL_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090097import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ARP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090098import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_DHCP_TABLE;
99import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900100import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +0900101import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900102import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
Daniel Parkf3136042021-03-10 07:49:11 +0900103import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900104import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Daniel Park4cb120b2021-03-24 12:30:50 +0900105import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
106import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
Daniel Park2884b232021-03-04 18:58:47 +0900107import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.gatewayNodeForSpecifiedRouter;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900108import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtNetwork;
109import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
Daniel Parkf3136042021-03-10 07:49:11 +0900110import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
111import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.portNumber;
Jian Li556709c2021-02-03 17:54:28 +0900112import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Daniel Parkf3136042021-03-10 07:49:11 +0900113import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
114import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelToTenantPort;
Jian Li858ccd72021-02-04 17:25:01 +0900115import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
116import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
Daniel Parkf3136042021-03-10 07:49:11 +0900117import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
Jian Li858ccd72021-02-04 17:25:01 +0900118import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
119import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
120import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
121import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
122import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Li556709c2021-02-03 17:54:28 +0900123import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Parkf3136042021-03-10 07:49:11 +0900124import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_TO_INTEGRATION;
Daniel Parka8968802021-02-25 09:14:22 +0900125import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
126import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Li556709c2021-02-03 17:54:28 +0900127import static org.slf4j.LoggerFactory.getLogger;
128
129/**
130 * Handles kubevirt network events.
131 */
132@Component(immediate = true)
133public class KubevirtNetworkHandler {
134 protected final Logger log = getLogger(getClass());
135 private static final String DEFAULT_OF_PROTO = "tcp";
136 private static final int DEFAULT_OFPORT = 6653;
137 private static final int DPID_BEGIN = 3;
138 private static final long SLEEP_MS = 3000; // we wait 3s for init each node
Jian Li858ccd72021-02-04 17:25:01 +0900139 private static final int DEFAULT_TTL = 0xff;
Jian Li556709c2021-02-03 17:54:28 +0900140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
142 protected CoreService coreService;
143
144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
145 protected ClusterService clusterService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
148 protected LeadershipService leadershipService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
151 protected DeviceAdminService deviceService;
152
153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
154 protected KubevirtApiConfigService apiConfigService;
155
156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
157 protected KubevirtNodeService nodeService;
158
159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lifc7e6cf2021-04-08 11:13:24 +0900160 protected KubevirtNetworkAdminService networkService;
Jian Li556709c2021-02-03 17:54:28 +0900161
162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
163 protected KubevirtFlowRuleService flowService;
164
Daniel Parka8968802021-02-25 09:14:22 +0900165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
166 protected DriverService driverService;
167
Daniel Park2884b232021-03-04 18:58:47 +0900168 @Reference(cardinality = ReferenceCardinality.MANDATORY)
169 protected KubevirtRouterAdminService kubevirtRouterService;
170
Daniel Parkbabde9c2021-03-09 13:37:42 +0900171 @Reference(cardinality = ReferenceCardinality.MANDATORY)
172 protected KubevirtPortService kubevirtPortService;
173
174 @Reference(cardinality = ReferenceCardinality.MANDATORY)
175 protected KubevirtNetworkService kubevirtNetworkService;
176
177 @Reference(cardinality = ReferenceCardinality.MANDATORY)
178 protected KubevirtNodeService kubevirtNodeService;
179
Jian Li556709c2021-02-03 17:54:28 +0900180 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
181 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
Daniel Parkbabde9c2021-03-09 13:37:42 +0900182 private final KubevirtPortListener portListener = new InternalKubevirtPortListener();
Jian Li556709c2021-02-03 17:54:28 +0900183
Daniel Park2884b232021-03-04 18:58:47 +0900184 private final InternalRouterEventListener kubevirtRouterlistener =
185 new InternalRouterEventListener();
186
Jian Li556709c2021-02-03 17:54:28 +0900187 private final ExecutorService eventExecutor = newSingleThreadExecutor(
188 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
189
190 private ApplicationId appId;
191 private NodeId localNodeId;
192
193 @Activate
194 protected void activate() {
195 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
196 localNodeId = clusterService.getLocalNode().id();
Jian Li556709c2021-02-03 17:54:28 +0900197 leadershipService.runForLeadership(appId.name());
198
Daniel Parkbabde9c2021-03-09 13:37:42 +0900199 networkService.addListener(networkListener);
200 nodeService.addListener(nodeListener);
201 kubevirtPortService.addListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900202 kubevirtRouterService.addListener(kubevirtRouterlistener);
203
Jian Li556709c2021-02-03 17:54:28 +0900204 log.info("Started");
205 }
206
207 @Deactivate
208 protected void deactivate() {
209 networkService.removeListener(networkListener);
210 nodeService.removeListener(nodeListener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900211 kubevirtPortService.removeListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900212 kubevirtRouterService.removeListener(kubevirtRouterlistener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900213 leadershipService.withdraw(appId.name());
Jian Li556709c2021-02-03 17:54:28 +0900214 eventExecutor.shutdown();
215
216 log.info("Stopped");
217 }
218
219 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
220
221 Device tunBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
222 if (tunBridge != null) {
223 log.warn("The tunnel bridge {} already exists at node {}",
224 network.tenantBridgeName(), node.hostname());
Daniel Parkf3136042021-03-10 07:49:11 +0900225 setDefaultRulesForTenantNetwork(node, network);
Jian Li556709c2021-02-03 17:54:28 +0900226 return;
227 }
228
229 Device device = deviceService.getDevice(node.ovsdb());
230
231 IpAddress serverIp = apiConfigService.apiConfig().ipAddress();
232 ControllerInfo controlInfo =
233 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
234 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
235
236 String dpid = network.tenantDeviceId(
237 node.hostname()).toString().substring(DPID_BEGIN);
238
239 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
240 .name(network.tenantBridgeName())
241 .failMode(BridgeDescription.FailMode.SECURE)
242 .datapathId(dpid)
243 .disableInBand()
244 .controllers(controllers);
245
246 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
247 bridgeConfig.addBridge(builder.build());
248 }
249
250 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
251 Device device = deviceService.getDevice(node.ovsdb());
252
253 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
254
255 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
256 bridgeConfig.deleteBridge(bridgeName);
257 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
258 }
259
Daniel Parkf3136042021-03-10 07:49:11 +0900260 private void createPatchTenantInterface(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900261 Device device = deviceService.getDevice(node.ovsdb());
262
263 if (device == null || !device.is(InterfaceConfig.class)) {
264 log.error("Failed to create patch interface on {}", node.ovsdb());
265 return;
266 }
267
268 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
269
Jian Li858ccd72021-02-04 17:25:01 +0900270 String tenantToTunIntf =
271 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
272 String tunToTenantIntf =
273 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900274
Jian Li858ccd72021-02-04 17:25:01 +0900275 // tenant bridge -> tunnel bridge
276 PatchDescription brTenantTunPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900277 DefaultPatchDescription.builder()
278 .deviceId(network.tenantBridgeName())
Jian Li858ccd72021-02-04 17:25:01 +0900279 .ifaceName(tenantToTunIntf)
280 .peer(tunToTenantIntf)
Jian Li556709c2021-02-03 17:54:28 +0900281 .build();
282
Jian Li858ccd72021-02-04 17:25:01 +0900283 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900284
Jian Li858ccd72021-02-04 17:25:01 +0900285 // tunnel bridge -> tenant bridge
286 PatchDescription brTunTenantPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900287 DefaultPatchDescription.builder()
288 .deviceId(TUNNEL_BRIDGE)
Jian Li858ccd72021-02-04 17:25:01 +0900289 .ifaceName(tunToTenantIntf)
290 .peer(tenantToTunIntf)
Jian Li556709c2021-02-03 17:54:28 +0900291 .build();
Jian Li858ccd72021-02-04 17:25:01 +0900292 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900293 }
294
295 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
296 Device device = deviceService.getDevice(node.ovsdb());
297
298 if (device == null || !device.is(InterfaceConfig.class)) {
299 log.error("Failed to create patch interface on {}", node.ovsdb());
300 return;
301 }
302
303 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
304
Jian Li858ccd72021-02-04 17:25:01 +0900305 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900306
307 ifaceConfig.removePatchMode(tunToIntIntf);
308 }
309
Daniel Parkf3136042021-03-10 07:49:11 +0900310 private void setArpRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900311
312 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
313 if (router == null) {
314 return;
315 }
316
317 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
318 if (electedGw == null) {
319 return;
320 }
321
Daniel Parkf3136042021-03-10 07:49:11 +0900322 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE, electedGw.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900323 network.tenantDeviceId(node.hostname()), true);
324 }
325
Daniel Parkf3136042021-03-10 07:49:11 +0900326 private void setIcmpRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900327 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
328 if (router == null) {
329 return;
330 }
331
332 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
333 if (electedGw == null) {
334 return;
335 }
336
Daniel Parkf3136042021-03-10 07:49:11 +0900337 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE, electedGw.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900338 network.tenantDeviceId(node.hostname()), true);
339 }
340
Daniel Parkf3136042021-03-10 07:49:11 +0900341 private void setDefaultGatewayRuleToWorkerNodeWhenNodeCreated(KubevirtNode node, KubevirtNetwork network) {
342 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
343 if (router == null) {
344 return;
345 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900346
Daniel Parkf3136042021-03-10 07:49:11 +0900347 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
348 if (electedGw == null) {
349 return;
350 }
351
Jian Li517597a2021-03-22 11:04:52 +0900352 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network, electedGw.intgBridge(), node, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900353 }
354
355 private void setDefaultRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900356 DeviceId deviceId = network.tenantDeviceId(node.hostname());
357
358 while (!deviceService.isAvailable(deviceId)) {
359 log.warn("Device {} is not ready for installing rules", deviceId);
360
361 try {
362 sleep(SLEEP_MS);
363 } catch (InterruptedException e) {
364 log.error("Failed to check device availability", e);
365 }
366 }
367
368 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li858ccd72021-02-04 17:25:01 +0900369 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
370 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
371 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Li556709c2021-02-03 17:54:28 +0900372
Daniel Parkf3136042021-03-10 07:49:11 +0900373 setDhcpRuleForTenantNetwork(deviceId, true);
Jian Li556709c2021-02-03 17:54:28 +0900374 setForwardingRule(deviceId, true);
375
376 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
377 }
378
Daniel Parkf3136042021-03-10 07:49:11 +0900379 private void setDhcpRuleForTenantNetwork(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900380 TrafficSelector selector = DefaultTrafficSelector.builder()
381 .matchEthType(Ethernet.TYPE_IPV4)
382 .matchIPProtocol(IPv4.PROTOCOL_UDP)
383 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
384 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
385 .build();
386
387 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
388 .punt()
389 .build();
390
391 flowService.setRule(
392 appId,
393 deviceId,
394 selector,
395 treatment,
396 PRIORITY_DHCP_RULE,
397 TENANT_DHCP_TABLE,
398 install);
399 }
400
Jian Li858ccd72021-02-04 17:25:01 +0900401 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900402 TrafficSelector selector = DefaultTrafficSelector.builder().build();
403 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
404 .setOutput(PortNumber.NORMAL)
405 .build();
406
407 flowService.setRule(
408 appId,
409 deviceId,
410 selector,
411 treatment,
Jian Li858ccd72021-02-04 17:25:01 +0900412 PRIORITY_FORWARDING_RULE,
Jian Li556709c2021-02-03 17:54:28 +0900413 TENANT_FORWARDING_TABLE,
414 install);
415 }
416
Daniel Park2884b232021-03-04 18:58:47 +0900417 private void initGatewayNodeForInternalNetwork(KubevirtNetwork network,
418 KubevirtRouter router,
419 KubevirtNode electedGateway,
420 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900421 switch (network.type()) {
422 case VXLAN:
423 case GRE:
424 case GENEVE:
Daniel Parkf3136042021-03-10 07:49:11 +0900425 setDefaultEgressRuleToGatewayNode(router, network, electedGateway.intgBridge(), install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900426 kubevirtNodeService.completeNodes(WORKER).forEach(node -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900427 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900428 electedGateway.intgBridge(),
429 network.tenantDeviceId(node.hostname()), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900430 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900431 electedGateway.intgBridge(),
432 network.tenantDeviceId(node.hostname()), install);
Jian Li517597a2021-03-22 11:04:52 +0900433 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
Daniel Parkf3136042021-03-10 07:49:11 +0900434 electedGateway.intgBridge(), node, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900435 });
Daniel Park4cb120b2021-03-24 12:30:50 +0900436 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900437 break;
438 case FLAT:
439 case VLAN:
Daniel Parkf3136042021-03-10 07:49:11 +0900440 setGatewayArpRuleForProviderInternalNetwork(router, network, PRE_FLAT_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900441 electedGateway.intgBridge(), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900442 setGatewayIcmpRuleForProviderInternalNetwork(router, network, PRE_FLAT_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900443 electedGateway.intgBridge(), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900444 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900445 break;
446 default:
447 // do nothing
448 break;
449 }
Daniel Park2884b232021-03-04 18:58:47 +0900450 }
451
Jian Li517597a2021-03-22 11:04:52 +0900452 private void setDefaultGatewayRuleToWorkerNodeTunBridge(KubevirtRouter router,
453 KubevirtNetwork network,
454 DeviceId gwDeviceId,
455 KubevirtNode workerNode,
456 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900457 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900458
Daniel Parkf3136042021-03-10 07:49:11 +0900459 if (routerMacAddress == null) {
460 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
461 "there's no br-int port for device {}", gwDeviceId);
462 return;
463 }
464
465 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
466
467 if (gwNode == null) {
468 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
469 "there's no gateway node for device {}", gwDeviceId);
470 return;
471 }
472
473
474 PortNumber patchPortNumber = tunnelToTenantPort(workerNode, network);
475 if (patchPortNumber == null) {
476 return;
477 }
478
479 PortNumber tunnelPortNumber = tunnelPort(workerNode, network);
480 if (tunnelPortNumber == null) {
481 return;
482 }
483
484 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
485 .matchInPort(patchPortNumber)
486 .matchEthType(Ethernet.TYPE_IPV4)
487 .matchEthDst((routerMacAddress));
488
489 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
490 .setTunnelId(Long.parseLong(network.segmentId()))
491 .extension(buildExtension(
492 deviceService,
493 workerNode.tunBridge(),
494 gwNode.dataIp().getIp4Address()),
495 workerNode.tunBridge())
496 .setOutput(tunnelPortNumber);
497
498 flowService.setRule(
499 appId,
500 workerNode.tunBridge(),
501 sBuilder.build(),
502 tBuilder.build(),
503 PRIORITY_FORWARDING_RULE,
504 TUNNEL_DEFAULT_TABLE,
505 install);
506 }
507
508 private void setDefaultEgressRuleToGatewayNode(KubevirtRouter router,
509 KubevirtNetwork network,
510 DeviceId gwDeviceId,
511 boolean install) {
512 MacAddress routerMacAddress = getRouterMacAddress(router);
513
514 if (routerMacAddress == null) {
515 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
516 "there's no br-int port for device {}", gwDeviceId);
517 return;
518 }
519
520 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
521
522 if (gwNode == null) {
523 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
524 "there's no gateway node for device {}", gwDeviceId);
525 return;
526 }
527
528 PortNumber tunToIntPortNum = portNumber(gwNode.tunBridge(), TUNNEL_TO_INTEGRATION);
529
530 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
531 .matchTunnelId(Long.parseLong(network.segmentId()));
532
533 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
534 .setOutput(tunToIntPortNum);
535
536 flowService.setRule(
537 appId,
538 gwNode.tunBridge(),
539 sBuilder.build(),
540 tBuilder.build(),
541 PRIORITY_TUNNEL_RULE,
542 TUNNEL_DEFAULT_TABLE,
543 install);
544 }
545
546
547 private void setGatewayIcmpRuleForTenantInternalNetwork(KubevirtRouter router,
548 KubevirtNetwork network,
549 int tableNum,
550 DeviceId gwDeviceId,
551 DeviceId tenantDeviceId,
552 boolean install) {
553 MacAddress routerMacAddress = getRouterMacAddress(router);
554
555 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900556 log.warn("Setting gateway ICMP rule for internal network because " +
557 "there's no br-int port for device {}", gwDeviceId);
558 return;
559 }
560
561 Device device = deviceService.getDevice(tenantDeviceId);
562
563 if (device == null) {
564 log.warn("Setting gateway icmp rule for internal network because " +
565 "there's no tenant device for {} to install gateway arp rule",
566 tenantDeviceId);
567 return;
568 }
569
570
571 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
572 .matchEthType(Ethernet.TYPE_IPV4)
573 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
574 .matchIcmpType(TYPE_ECHO_REQUEST)
575 .matchIcmpCode(CODE_ECHO_REQEUST)
576 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
577
578 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
579 .extension(buildMoveEthSrcToDstExtension(device), device.id())
580 .extension(buildMoveIpSrcToDstExtension(device), device.id())
581 .extension(buildLoadExtension(device,
582 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
583 .extension(buildLoadExtension(device,
584 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
585 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900586 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900587 .setOutput(PortNumber.IN_PORT);
588
589 flowService.setRule(
590 appId,
591 tenantDeviceId,
592 sBuilder.build(),
593 tBuilder.build(),
594 PRIORITY_ICMP_RULE,
595 tableNum,
596 install);
597 }
598
Daniel Parkf3136042021-03-10 07:49:11 +0900599 private void setGatewayArpRuleForTenantInternalNetwork(KubevirtRouter router,
600 KubevirtNetwork network,
601 int tableNum,
602 DeviceId gwDeviceId,
603 DeviceId tenantDeviceId,
604 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900605
Daniel Parkf3136042021-03-10 07:49:11 +0900606 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900607
Daniel Parkf3136042021-03-10 07:49:11 +0900608 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900609 log.warn("Setting gateway arp rule for internal network because " +
610 "there's no br-int port for device {}", gwDeviceId);
611 return;
612 }
613
614 Device device = deviceService.getDevice(tenantDeviceId);
615
616 if (device == null) {
617 log.warn("Setting gateway arp rule for internal network because " +
618 "there's no tenant device for {} to install gateway arp rule",
619 tenantDeviceId);
620 return;
621 }
622
623
624 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
625 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
626 .matchArpOp(ARP.OP_REQUEST)
627 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
628
629 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
630 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
631 .extension(buildMoveArpShaToThaExtension(device), device.id())
632 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
633 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900634 .setArpSha(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900635 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900636 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900637 .setOutput(PortNumber.IN_PORT);
638
639 flowService.setRule(
640 appId,
641 device.id(),
642 sBuilder.build(),
643 tBuilder.build(),
644 PRIORITY_ARP_GATEWAY_RULE,
645 tableNum,
646 install
647 );
648 }
649
Daniel Parkf3136042021-03-10 07:49:11 +0900650 private void setGatewayProviderInterNetworkRoutingWithinSameRouter(
Daniel Parkbabde9c2021-03-09 13:37:42 +0900651 KubevirtNetwork network, KubevirtRouter router, KubevirtNode gatewayNode, boolean install) {
Daniel Park2884b232021-03-04 18:58:47 +0900652 router.internal().forEach(srcNetwork -> {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900653 if (srcNetwork.equals(network.networkId())
654 || kubevirtNetworkService.network(srcNetwork) == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900655 return;
656 }
657
Daniel Parkbabde9c2021-03-09 13:37:42 +0900658 kubevirtPortService.ports(network.networkId()).forEach(port -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900659 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900660 port, gatewayNode, install);
661 });
Daniel Park2884b232021-03-04 18:58:47 +0900662 });
663 }
664
Daniel Parkf3136042021-03-10 07:49:11 +0900665 private void setGatewayInterNetworkRoutingFromNetworkToPort(KubevirtRouter router,
666 KubevirtNetwork srcNetwork,
667 KubevirtPort dstPort,
668 KubevirtNode gatewayNode,
669 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900670 Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
671
672 if (gwDevice == null) {
673 log.warn("Failed to set internal network routing rule because " +
674 "there's no device Id for device {}", gatewayNode.intgBridge());
675 return;
676 }
677
Daniel Parkf3136042021-03-10 07:49:11 +0900678 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900679
Daniel Parkf3136042021-03-10 07:49:11 +0900680 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900681 log.warn("Failed to set internal network routing rule because " +
682 "there's no br-int port for device {}", gatewayNode.intgBridge());
683 return;
684 }
685
Daniel Park4cb120b2021-03-24 12:30:50 +0900686 TrafficSelector.Builder sBuilder;
687 TrafficTreatment treatment;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900688
Daniel Park4cb120b2021-03-24 12:30:50 +0900689 if (srcNetwork.type() == FLAT || srcNetwork.type() == VLAN) {
690 sBuilder = DefaultTrafficSelector.builder()
691 .matchEthType(Ethernet.TYPE_IPV4)
692 .matchEthDst(routerMacAddress)
693 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
694 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
Daniel Parkbabde9c2021-03-09 13:37:42 +0900695
Daniel Park4cb120b2021-03-24 12:30:50 +0900696 treatment = DefaultTrafficTreatment.builder()
697 .setEthSrc(routerMacAddress)
698 .setEthDst(dstPort.macAddress())
699 .transition(FORWARDING_TABLE)
700 .build();
701
702 flowService.setRule(
703 appId,
704 gwDevice.id(),
705 sBuilder.build(),
706 treatment,
707 PRIORITY_INTERNAL_ROUTING_RULE,
708 PRE_FLAT_TABLE,
709 install);
710 } else {
711 KubevirtNetwork dstNetwork = kubevirtNetworkService.network(dstPort.networkId());
712 if (dstNetwork == null) {
713 return;
714 }
715
716 KubevirtNode dstPortWorkerNode = kubevirtNodeService.node(dstPort.deviceId());
717 if (dstPortWorkerNode == null) {
718 return;
719 }
720
721 sBuilder = DefaultTrafficSelector.builder()
722 .matchEthType(Ethernet.TYPE_IPV4)
723 .matchEthDst(routerMacAddress)
724 .matchTunnelId(Long.parseLong(srcNetwork.segmentId()))
725 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
726 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
727
728 treatment = DefaultTrafficTreatment.builder()
729 .setTunnelId(Long.parseLong(dstNetwork.segmentId()))
730 .setEthSrc(routerMacAddress)
731 .setEthDst(dstPort.macAddress())
732 .extension(buildExtension(
733 deviceService,
734 gatewayNode.tunBridge(),
735 dstPortWorkerNode.dataIp().getIp4Address()),
736 gatewayNode.tunBridge())
737 .setOutput(PortNumber.IN_PORT)
738 .build();
739
740 flowService.setRule(
741 appId,
742 gatewayNode.tunBridge(),
743 sBuilder.build(),
744 treatment,
745 PRIORITY_INTERNAL_ROUTING_RULE,
746 TUNNEL_DEFAULT_TABLE,
747 install);
748 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900749 }
750
Daniel Parkf3136042021-03-10 07:49:11 +0900751 private void setGatewayArpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
752 int tableNum, DeviceId gwDeviceId, boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900753
754
755 Device device = deviceService.getDevice(gwDeviceId);
Daniel Parkf3136042021-03-10 07:49:11 +0900756 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900757
Daniel Parkf3136042021-03-10 07:49:11 +0900758 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900759 log.warn("Setting gateway arp rule for internal network because " +
760 "there's no br-int port for device {}", gwDeviceId);
Daniel Park2884b232021-03-04 18:58:47 +0900761 return;
762 }
763
Jian Li858ccd72021-02-04 17:25:01 +0900764 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
765 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
766 .matchArpOp(ARP.OP_REQUEST)
767 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
768
769 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
770 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
771 .extension(buildMoveArpShaToThaExtension(device), device.id())
772 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
773 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900774 .setArpSha(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900775 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900776 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900777 .setOutput(PortNumber.IN_PORT);
778
779 flowService.setRule(
780 appId,
781 device.id(),
782 sBuilder.build(),
783 tBuilder.build(),
784 PRIORITY_ARP_GATEWAY_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900785 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900786 install
787 );
788 }
789
Daniel Park2884b232021-03-04 18:58:47 +0900790 /**
791 * Sends ICMP echo reply for the ICMP echo request from the kubevirt VM.
792 *
Daniel Parkf3136042021-03-10 07:49:11 +0900793 * @param router kubevirt router
Daniel Park2884b232021-03-04 18:58:47 +0900794 * @param network kubevirt network
795 * @param tableNum flow table number
796 * @param deviceId device id of the selected gateway for the network
797 * @param install install if true, remove otherwise
798 */
Daniel Parkf3136042021-03-10 07:49:11 +0900799 private void setGatewayIcmpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
800 int tableNum, DeviceId deviceId, boolean install) {
801 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900802
Daniel Parkf3136042021-03-10 07:49:11 +0900803 if (routerMacAddress == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900804 log.error("Setting gateway ICMP rule for internal network because " +
805 "there's no br-int port for device {}", deviceId);
806 return;
807 }
808
Jian Li858ccd72021-02-04 17:25:01 +0900809 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
810 .matchEthType(Ethernet.TYPE_IPV4)
811 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
812 .matchIcmpType(TYPE_ECHO_REQUEST)
813 .matchIcmpCode(CODE_ECHO_REQEUST)
814 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
815
816 Device device = deviceService.getDevice(deviceId);
817 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
818 .extension(buildMoveEthSrcToDstExtension(device), device.id())
819 .extension(buildMoveIpSrcToDstExtension(device), device.id())
820 .extension(buildLoadExtension(device,
821 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
822 .extension(buildLoadExtension(device,
823 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
824 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900825 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900826 .setOutput(PortNumber.IN_PORT);
827
828 flowService.setRule(
829 appId,
830 deviceId,
831 sBuilder.build(),
832 tBuilder.build(),
833 PRIORITY_ICMP_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900834 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900835 install);
836 }
837
Jian Lifc7e6cf2021-04-08 11:13:24 +0900838 private void reserveVrouterIp(KubevirtNetwork network) {
839 String networkId = network.networkId();
840 IpAddress vrouterIp = network.ipPool().start();
841
842 networkService.reserveIp(networkId, vrouterIp);
843 }
844
Daniel Park2884b232021-03-04 18:58:47 +0900845 private class InternalRouterEventListener implements KubevirtRouterListener {
846 private boolean isRelevantHelper() {
847 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Daniel Parka8968802021-02-25 09:14:22 +0900848 }
849
Daniel Park2884b232021-03-04 18:58:47 +0900850 @Override
851 public void event(KubevirtRouterEvent event) {
852 switch (event.type()) {
853 case KUBEVIRT_ROUTER_CREATED:
854 eventExecutor.execute(() -> processRouterCreation(event.subject()));
855 break;
856 case KUBEVIRT_ROUTER_REMOVED:
857 eventExecutor.execute(() -> processRouterDeletion(event.subject()));
858 break;
859 case KUBEVIRT_ROUTER_UPDATED:
860 eventExecutor.execute(() -> processRouterUpdate(event.subject()));
861 break;
862 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_ATTACHED:
863 eventExecutor.execute(() -> processRouterInternalNetworksAttached(event.subject(),
864 event.internal()));
865 break;
866 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_DETACHED:
867 eventExecutor.execute(() -> processRouterInternalNetworksDetached(event.subject(),
868 event.internal()));
869 break;
870 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
871 eventExecutor.execute(() -> processRouterGatewayNodeAttached(event.subject(),
872 event.gateway()));
873 break;
874 case KUBEVIRT_GATEWAY_NODE_DETACHED:
875 eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(),
876 event.gateway()));
877 break;
878 case KUBEVIRT_GATEWAY_NODE_CHANGED:
879 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
880 event.gateway()));
881 break;
Daniel Parka8968802021-02-25 09:14:22 +0900882
Daniel Park2884b232021-03-04 18:58:47 +0900883 default:
884 //do nothing
885 break;
886 }
887 }
888
889 private void processRouterCreation(KubevirtRouter router) {
890 // When a router is created, we performs the election process to associate the router
891 // to the specific gateway. After the election, KubevirtNetwork handler installs bunch of rules
892 // to elected gateway node so that VMs associated to the router can ping to their gateway IP.
893 // SNAT and floating ip rule setup is out of this handler's scope and would be done with the other handlers
894 if (!isRelevantHelper()) {
895 return;
896 }
897 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
898 if (electedGw == null) {
899 return;
900 }
901
902 router.internal().forEach(networkName -> {
903 KubevirtNetwork network = networkService.network(networkName);
904
905 if (network != null) {
906 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
907 }
908 });
909 kubevirtRouterService.updateRouter(router.updatedElectedGateway(electedGw.hostname()));
910 }
911
912 private void processRouterDeletion(KubevirtRouter router) {
913 if (!isRelevantHelper()) {
914 return;
915 }
916 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
917 if (electedGw == null) {
918 return;
919 }
920
921 router.internal().forEach(networkName -> {
922 KubevirtNetwork network = networkService.network(networkName);
923
924 if (network != null) {
925 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
926 }
927 });
928 }
929
930 private void processRouterUpdate(KubevirtRouter router) {
931 if (!isRelevantHelper()) {
932 return;
933 }
934 if (router.electedGateway() == null) {
935 return;
936 }
937
938 KubevirtNode electedGw = nodeService.node(router.electedGateway());
939
940 router.internal().forEach(networkName -> {
941 KubevirtNetwork network = networkService.network(networkName);
942
943 if (network != null) {
944 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
945 }
946 });
947 }
948
949 private void processRouterInternalNetworksAttached(KubevirtRouter router,
950 Set<String> attachedInternalNetworks) {
951 if (!isRelevantHelper()) {
952 return;
953 }
954 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
955 if (electedGw == null) {
956 return;
957 }
958
959 attachedInternalNetworks.forEach(networkName -> {
960 KubevirtNetwork network = networkService.network(networkName);
961
962 if (network != null) {
963 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
964 }
965 });
966 }
967
968 private void processRouterInternalNetworksDetached(KubevirtRouter router,
969 Set<String> detachedInternalNetworks) {
970 if (!isRelevantHelper()) {
971 return;
972 }
973 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
974 if (electedGw == null) {
975 return;
976 }
977
978 detachedInternalNetworks.forEach(networkName -> {
979 KubevirtNetwork network = networkService.network(networkName);
980
981 if (network != null) {
982 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
983 }
Daniel Park2884b232021-03-04 18:58:47 +0900984
Daniel Parkbabde9c2021-03-09 13:37:42 +0900985 removeDetachedInternalNetworkRules(network, router, electedGw);
986 });
987 }
988
989 private void removeDetachedInternalNetworkRules(KubevirtNetwork removedNetwork, KubevirtRouter router,
990 KubevirtNode electedGw) {
Daniel Parkf3136042021-03-10 07:49:11 +0900991 router.internal().stream().filter(networkId -> kubevirtNetworkService.network(networkId) != null)
992 .forEach(networkId -> {
993 kubevirtPortService.ports(networkId).forEach(kubevirtPort -> {
994 setGatewayInterNetworkRoutingFromNetworkToPort(
995 router, removedNetwork, kubevirtPort, electedGw, false);
996 });
Daniel Parkbabde9c2021-03-09 13:37:42 +0900997 });
Daniel Park2884b232021-03-04 18:58:47 +0900998 }
999
1000 private void processRouterGatewayNodeAttached(KubevirtRouter router,
1001 String associatedGateway) {
1002 if (!isRelevantHelper()) {
1003 return;
1004 }
1005
1006 KubevirtNode gatewayNode = nodeService.node(associatedGateway);
1007 if (gatewayNode == null) {
1008 return;
1009 }
1010
1011 router.internal().forEach(networkName -> {
1012 KubevirtNetwork network = networkService.network(networkName);
1013
1014 if (network != null) {
1015 initGatewayNodeForInternalNetwork(network, router, gatewayNode, true);
1016 }
1017 });
1018 }
1019
1020 private void processRouterGatewayNodeDetached(KubevirtRouter router,
1021 String disAssociatedGateway) {
1022 if (!isRelevantHelper()) {
1023 return;
1024 }
1025
1026 KubevirtNode gatewayNode = nodeService.node(disAssociatedGateway);
1027 if (gatewayNode == null) {
1028 return;
1029 }
1030
1031 router.internal().forEach(networkName -> {
1032 KubevirtNetwork network = networkService.network(networkName);
1033
1034 if (network != null) {
1035 initGatewayNodeForInternalNetwork(network, router, gatewayNode, false);
1036 }
1037 });
1038 }
1039
1040 private void processRouterGatewayNodeChanged(KubevirtRouter router,
1041 String disAssociatedGateway) {
1042 if (!isRelevantHelper()) {
1043 return;
1044 }
1045
1046 KubevirtNode oldGatewayNode = nodeService.node(disAssociatedGateway);
1047 if (oldGatewayNode == null) {
1048 return;
1049 }
1050
1051 router.internal().forEach(networkName -> {
1052 KubevirtNetwork network = networkService.network(networkName);
1053
1054 if (network != null) {
1055 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, false);
1056 }
1057 });
1058
1059 KubevirtNode newGatewayNode = nodeService.node(router.electedGateway());
1060 if (newGatewayNode == null) {
1061 return;
1062 }
1063
1064 router.internal().forEach(networkName -> {
1065 KubevirtNetwork network = networkService.network(networkName);
1066
1067 if (network != null) {
1068 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, true);
1069 }
1070 });
1071 }
Daniel Parka8968802021-02-25 09:14:22 +09001072 }
1073
Jian Li556709c2021-02-03 17:54:28 +09001074 private class InternalNetworkEventListener implements KubevirtNetworkListener {
1075
1076 private boolean isRelevantHelper() {
1077 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1078 }
1079
1080 @Override
1081 public void event(KubevirtNetworkEvent event) {
1082 switch (event.type()) {
1083 case KUBEVIRT_NETWORK_CREATED:
1084 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
1085 break;
1086 case KUBEVIRT_NETWORK_REMOVED:
1087 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
1088 break;
1089 case KUBEVIRT_NETWORK_UPDATED:
1090 default:
1091 // do nothing
1092 break;
1093 }
1094 }
1095
1096 private void processNetworkCreation(KubevirtNetwork network) {
1097 if (!isRelevantHelper()) {
1098 return;
1099 }
1100
1101 switch (network.type()) {
1102 case VXLAN:
1103 case GRE:
1104 case GENEVE:
1105 initIntegrationTunnelBridge(network);
1106 break;
1107 case FLAT:
Jian Lifc7e6cf2021-04-08 11:13:24 +09001108 reserveVrouterIp(network);
1109 break;
Jian Li2ce718e2021-02-17 20:42:15 +09001110 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001111 break;
Jian Li556709c2021-02-03 17:54:28 +09001112 default:
1113 // do nothing
1114 break;
1115 }
1116 }
1117
1118 private void processNetworkRemoval(KubevirtNetwork network) {
1119 if (!isRelevantHelper()) {
1120 return;
1121 }
1122
1123 switch (network.type()) {
1124 case VXLAN:
1125 case GRE:
1126 case GENEVE:
1127 purgeIntegrationTunnelBridge(network);
1128 break;
1129 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001130 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001131 break;
Jian Li556709c2021-02-03 17:54:28 +09001132 default:
1133 // do nothing
1134 break;
1135 }
1136 }
1137
1138 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
1139 if (network.segmentId() == null) {
1140 return;
1141 }
1142
1143 nodeService.completeNodes().forEach(n -> {
1144 createBridge(n, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001145 createPatchTenantInterface(n, network);
1146 setDefaultRulesForTenantNetwork(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001147 });
1148 }
1149
1150 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
1151 if (network.segmentId() == null) {
1152 return;
1153 }
1154
1155 nodeService.completeNodes().forEach(n -> {
1156 removePatchInterface(n, network);
1157 removeBridge(n, network);
1158 });
1159 }
1160 }
1161
1162 private class InternalNodeEventListener implements KubevirtNodeListener {
1163
1164 private boolean isRelevantHelper() {
1165 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1166 }
1167
1168 @Override
1169 public void event(KubevirtNodeEvent event) {
1170 switch (event.type()) {
1171 case KUBEVIRT_NODE_COMPLETE:
1172 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
1173 break;
Daniel Park2884b232021-03-04 18:58:47 +09001174 case KUBEVIRT_NODE_REMOVED:
1175 eventExecutor.execute(() -> processNodeDeletion(event.subject()));
1176 break;
Jian Li556709c2021-02-03 17:54:28 +09001177 case KUBEVIRT_NODE_INCOMPLETE:
1178 case KUBEVIRT_NODE_UPDATED:
1179 default:
1180 // do nothing
1181 break;
1182 }
1183 }
1184
1185 private void processNodeCompletion(KubevirtNode node) {
1186 if (!isRelevantHelper()) {
1187 return;
1188 }
1189
Daniel Parka8968802021-02-25 09:14:22 +09001190 if (node.type().equals(WORKER)) {
1191 for (KubevirtNetwork network : networkService.networks()) {
1192 switch (network.type()) {
1193 case VXLAN:
1194 case GRE:
1195 case GENEVE:
1196 if (network.segmentId() == null) {
1197 continue;
1198 }
1199 createBridge(node, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001200 createPatchTenantInterface(node, network);
1201 setDefaultRulesForTenantNetwork(node, network);
1202 setArpRulesForTenantNetwork(node, network);
1203 setIcmpRulesForTenantNetwork(node, network);
1204 setDefaultGatewayRuleToWorkerNodeWhenNodeCreated(node, network);
Daniel Parka8968802021-02-25 09:14:22 +09001205 break;
1206 case FLAT:
Jian Lifc7e6cf2021-04-08 11:13:24 +09001207 reserveVrouterIp(network);
1208 break;
Daniel Parka8968802021-02-25 09:14:22 +09001209 case VLAN:
1210 default:
1211 // do nothing
1212 break;
1213 }
1214 }
1215 } else if (node.type().equals(GATEWAY)) {
Daniel Park2884b232021-03-04 18:58:47 +09001216 updateGatewayNodeForRouter();
Daniel Parka8968802021-02-25 09:14:22 +09001217 for (KubevirtNetwork network : networkService.networks()) {
1218 switch (network.type()) {
1219 case FLAT:
1220 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001221 break;
1222 case VXLAN:
1223 case GRE:
1224 case GENEVE:
1225 default:
1226 // do nothing
1227 break;
1228 }
Jian Li556709c2021-02-03 17:54:28 +09001229 }
1230 }
1231 }
Daniel Park2884b232021-03-04 18:58:47 +09001232
1233 private void processNodeDeletion(KubevirtNode node) {
1234 if (!isRelevantHelper()) {
1235 return;
1236 }
1237
1238 if (node.type().equals(GATEWAY)) {
1239 updateGatewayNodeForRouter();
1240 for (KubevirtNetwork network : networkService.networks()) {
1241 switch (network.type()) {
1242 case FLAT:
1243 case VLAN:
1244 break;
1245 case VXLAN:
1246 case GRE:
1247 case GENEVE:
1248 default:
1249 // do nothing
1250 break;
1251 }
1252 }
1253 }
1254 }
1255
1256 private void updateGatewayNodeForRouter() {
1257 kubevirtRouterService.routers().forEach(router -> {
1258 KubevirtNode newGwNode = gatewayNodeForSpecifiedRouter(nodeService, router);
1259
1260 if (newGwNode == null) {
1261 return;
1262 }
1263 kubevirtRouterService.updateRouter(router.updatedElectedGateway(newGwNode.hostname()));
1264 });
1265 }
Jian Li556709c2021-02-03 17:54:28 +09001266 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001267
1268 private class InternalKubevirtPortListener implements KubevirtPortListener {
1269
1270 private boolean isRelevantHelper() {
1271 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1272 }
1273
1274 @Override
1275 public void event(KubevirtPortEvent event) {
1276 switch (event.type()) {
1277 case KUBEVIRT_PORT_CREATED:
1278 eventExecutor.execute(() -> processPortCreation(event.subject()));
1279 break;
1280 case KUBEVIRT_PORT_UPDATED:
1281 eventExecutor.execute(() -> processPortUpdate(event.subject()));
1282 break;
1283 case KUBEVIRT_PORT_REMOVED:
1284 eventExecutor.execute(() -> processPortDeletion(event.subject()));
1285 break;
1286 default:
1287 //do nothing
1288 break;
1289 }
1290 }
1291
1292 private void processPortCreation(KubevirtPort kubevirtPort) {
1293 if (!isRelevantHelper()) {
1294 return;
1295 }
1296
1297 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1298 if (router == null) {
1299 return;
1300 }
1301
1302 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1303
1304 if (gwNode != null) {
1305
1306 router.internal().forEach(srcNetwork -> {
1307 if (srcNetwork.equals(kubevirtPort.networkId())
1308 || kubevirtNetworkService.network(srcNetwork) == null) {
1309 return;
1310 }
Daniel Parkf3136042021-03-10 07:49:11 +09001311 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001312 kubevirtPort, gwNode, true);
1313 });
1314 }
1315 }
1316
1317 private void processPortUpdate(KubevirtPort kubevirtPort) {
1318 if (!isRelevantHelper()) {
1319 return;
1320 }
1321
1322 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1323 if (router == null) {
1324 return;
1325 }
1326
1327 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1328
1329 if (gwNode != null) {
1330
1331 router.internal().forEach(srcNetwork -> {
1332 if (srcNetwork.equals(kubevirtPort.networkId())
1333 || kubevirtNetworkService.network(srcNetwork) == null) {
1334 return;
1335 }
Daniel Parkf3136042021-03-10 07:49:11 +09001336 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001337 kubevirtPort, gwNode, true);
1338 });
1339 }
1340 }
1341
1342 private void processPortDeletion(KubevirtPort kubevirtPort) {
1343 if (!isRelevantHelper()) {
1344 return;
1345 }
1346
1347 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1348 if (router == null) {
1349 return;
1350 }
1351
1352 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1353
1354 if (gwNode != null) {
1355
1356 router.internal().forEach(srcNetwork -> {
1357 if (srcNetwork.equals(kubevirtPort.networkId())
1358 || kubevirtNetworkService.network(srcNetwork) == null) {
1359 return;
1360 }
Daniel Parkf3136042021-03-10 07:49:11 +09001361 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001362 kubevirtPort, gwNode, false);
1363 });
1364 }
1365
1366 }
1367 }
Jian Li556709c2021-02-03 17:54:28 +09001368}