blob: 603a293da0401208d28efcfb2fa4de83c03053a2 [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 Li94b6d162021-04-15 17:09:11 +0900112import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.resolveHostname;
Jian Li556709c2021-02-03 17:54:28 +0900113import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Daniel Parkf3136042021-03-10 07:49:11 +0900114import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
115import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelToTenantPort;
Jian Li858ccd72021-02-04 17:25:01 +0900116import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
117import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
Daniel Parkf3136042021-03-10 07:49:11 +0900118import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
Jian Li858ccd72021-02-04 17:25:01 +0900119import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
120import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
121import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
122import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
123import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Li556709c2021-02-03 17:54:28 +0900124import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Parkf3136042021-03-10 07:49:11 +0900125import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_TO_INTEGRATION;
Daniel Parka8968802021-02-25 09:14:22 +0900126import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
127import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Li556709c2021-02-03 17:54:28 +0900128import static org.slf4j.LoggerFactory.getLogger;
129
130/**
131 * Handles kubevirt network events.
132 */
133@Component(immediate = true)
134public class KubevirtNetworkHandler {
135 protected final Logger log = getLogger(getClass());
136 private static final String DEFAULT_OF_PROTO = "tcp";
137 private static final int DEFAULT_OFPORT = 6653;
138 private static final int DPID_BEGIN = 3;
139 private static final long SLEEP_MS = 3000; // we wait 3s for init each node
Jian Li858ccd72021-02-04 17:25:01 +0900140 private static final int DEFAULT_TTL = 0xff;
Jian Li556709c2021-02-03 17:54:28 +0900141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY)
143 protected CoreService coreService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY)
146 protected ClusterService clusterService;
147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY)
149 protected LeadershipService leadershipService;
150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY)
152 protected DeviceAdminService deviceService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY)
155 protected KubevirtApiConfigService apiConfigService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY)
158 protected KubevirtNodeService nodeService;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lifc7e6cf2021-04-08 11:13:24 +0900161 protected KubevirtNetworkAdminService networkService;
Jian Li556709c2021-02-03 17:54:28 +0900162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY)
164 protected KubevirtFlowRuleService flowService;
165
Daniel Parka8968802021-02-25 09:14:22 +0900166 @Reference(cardinality = ReferenceCardinality.MANDATORY)
167 protected DriverService driverService;
168
Daniel Park2884b232021-03-04 18:58:47 +0900169 @Reference(cardinality = ReferenceCardinality.MANDATORY)
170 protected KubevirtRouterAdminService kubevirtRouterService;
171
Daniel Parkbabde9c2021-03-09 13:37:42 +0900172 @Reference(cardinality = ReferenceCardinality.MANDATORY)
173 protected KubevirtPortService kubevirtPortService;
174
175 @Reference(cardinality = ReferenceCardinality.MANDATORY)
176 protected KubevirtNetworkService kubevirtNetworkService;
177
178 @Reference(cardinality = ReferenceCardinality.MANDATORY)
179 protected KubevirtNodeService kubevirtNodeService;
180
Jian Li556709c2021-02-03 17:54:28 +0900181 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
182 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
Daniel Parkbabde9c2021-03-09 13:37:42 +0900183 private final KubevirtPortListener portListener = new InternalKubevirtPortListener();
Jian Li556709c2021-02-03 17:54:28 +0900184
Daniel Park2884b232021-03-04 18:58:47 +0900185 private final InternalRouterEventListener kubevirtRouterlistener =
186 new InternalRouterEventListener();
187
Jian Li556709c2021-02-03 17:54:28 +0900188 private final ExecutorService eventExecutor = newSingleThreadExecutor(
189 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
190
191 private ApplicationId appId;
192 private NodeId localNodeId;
193
194 @Activate
195 protected void activate() {
196 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
197 localNodeId = clusterService.getLocalNode().id();
Jian Li556709c2021-02-03 17:54:28 +0900198 leadershipService.runForLeadership(appId.name());
199
Daniel Parkbabde9c2021-03-09 13:37:42 +0900200 networkService.addListener(networkListener);
201 nodeService.addListener(nodeListener);
202 kubevirtPortService.addListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900203 kubevirtRouterService.addListener(kubevirtRouterlistener);
204
Jian Li556709c2021-02-03 17:54:28 +0900205 log.info("Started");
206 }
207
208 @Deactivate
209 protected void deactivate() {
210 networkService.removeListener(networkListener);
211 nodeService.removeListener(nodeListener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900212 kubevirtPortService.removeListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900213 kubevirtRouterService.removeListener(kubevirtRouterlistener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900214 leadershipService.withdraw(appId.name());
Jian Li556709c2021-02-03 17:54:28 +0900215 eventExecutor.shutdown();
216
217 log.info("Stopped");
218 }
219
220 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
221
222 Device tunBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
223 if (tunBridge != null) {
224 log.warn("The tunnel bridge {} already exists at node {}",
225 network.tenantBridgeName(), node.hostname());
Daniel Parkf3136042021-03-10 07:49:11 +0900226 setDefaultRulesForTenantNetwork(node, network);
Jian Li556709c2021-02-03 17:54:28 +0900227 return;
228 }
229
230 Device device = deviceService.getDevice(node.ovsdb());
231
Jian Li94b6d162021-04-15 17:09:11 +0900232 IpAddress serverIp;
233 String serviceFqdn = apiConfigService.apiConfig().serviceFqdn();
234 IpAddress serviceIp = null;
235
236 if (serviceFqdn != null) {
237 serviceIp = resolveHostname(serviceFqdn);
238 }
239
240 if (serviceIp != null) {
241 serverIp = serviceIp;
242 } else {
243 serverIp = apiConfigService.apiConfig().ipAddress();
244 }
245
Jian Li556709c2021-02-03 17:54:28 +0900246 ControllerInfo controlInfo =
247 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
248 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
249
250 String dpid = network.tenantDeviceId(
251 node.hostname()).toString().substring(DPID_BEGIN);
252
253 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
254 .name(network.tenantBridgeName())
255 .failMode(BridgeDescription.FailMode.SECURE)
256 .datapathId(dpid)
257 .disableInBand()
258 .controllers(controllers);
259
260 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
261 bridgeConfig.addBridge(builder.build());
262 }
263
264 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
265 Device device = deviceService.getDevice(node.ovsdb());
266
267 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
268
269 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
270 bridgeConfig.deleteBridge(bridgeName);
271 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
272 }
273
Daniel Parkf3136042021-03-10 07:49:11 +0900274 private void createPatchTenantInterface(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900275 Device device = deviceService.getDevice(node.ovsdb());
276
277 if (device == null || !device.is(InterfaceConfig.class)) {
278 log.error("Failed to create patch interface on {}", node.ovsdb());
279 return;
280 }
281
282 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
283
Jian Li858ccd72021-02-04 17:25:01 +0900284 String tenantToTunIntf =
285 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
286 String tunToTenantIntf =
287 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900288
Jian Li858ccd72021-02-04 17:25:01 +0900289 // tenant bridge -> tunnel bridge
290 PatchDescription brTenantTunPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900291 DefaultPatchDescription.builder()
292 .deviceId(network.tenantBridgeName())
Jian Li858ccd72021-02-04 17:25:01 +0900293 .ifaceName(tenantToTunIntf)
294 .peer(tunToTenantIntf)
Jian Li556709c2021-02-03 17:54:28 +0900295 .build();
296
Jian Li858ccd72021-02-04 17:25:01 +0900297 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900298
Jian Li858ccd72021-02-04 17:25:01 +0900299 // tunnel bridge -> tenant bridge
300 PatchDescription brTunTenantPatchDesc =
Jian Li556709c2021-02-03 17:54:28 +0900301 DefaultPatchDescription.builder()
302 .deviceId(TUNNEL_BRIDGE)
Jian Li858ccd72021-02-04 17:25:01 +0900303 .ifaceName(tunToTenantIntf)
304 .peer(tenantToTunIntf)
Jian Li556709c2021-02-03 17:54:28 +0900305 .build();
Jian Li858ccd72021-02-04 17:25:01 +0900306 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900307 }
308
309 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
310 Device device = deviceService.getDevice(node.ovsdb());
311
312 if (device == null || !device.is(InterfaceConfig.class)) {
313 log.error("Failed to create patch interface on {}", node.ovsdb());
314 return;
315 }
316
317 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
318
Jian Li858ccd72021-02-04 17:25:01 +0900319 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900320
321 ifaceConfig.removePatchMode(tunToIntIntf);
322 }
323
Daniel Parkf3136042021-03-10 07:49:11 +0900324 private void setArpRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900325
326 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
327 if (router == null) {
328 return;
329 }
330
331 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
332 if (electedGw == null) {
333 return;
334 }
335
Daniel Parkf3136042021-03-10 07:49:11 +0900336 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE, electedGw.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900337 network.tenantDeviceId(node.hostname()), true);
338 }
339
Daniel Parkf3136042021-03-10 07:49:11 +0900340 private void setIcmpRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900341 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
342 if (router == null) {
343 return;
344 }
345
346 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
347 if (electedGw == null) {
348 return;
349 }
350
Daniel Parkf3136042021-03-10 07:49:11 +0900351 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE, electedGw.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900352 network.tenantDeviceId(node.hostname()), true);
353 }
354
Daniel Parkf3136042021-03-10 07:49:11 +0900355 private void setDefaultGatewayRuleToWorkerNodeWhenNodeCreated(KubevirtNode node, KubevirtNetwork network) {
356 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
357 if (router == null) {
358 return;
359 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900360
Daniel Parkf3136042021-03-10 07:49:11 +0900361 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
362 if (electedGw == null) {
363 return;
364 }
365
Jian Li517597a2021-03-22 11:04:52 +0900366 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network, electedGw.intgBridge(), node, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900367 }
368
369 private void setDefaultRulesForTenantNetwork(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900370 DeviceId deviceId = network.tenantDeviceId(node.hostname());
371
372 while (!deviceService.isAvailable(deviceId)) {
373 log.warn("Device {} is not ready for installing rules", deviceId);
374
375 try {
376 sleep(SLEEP_MS);
377 } catch (InterruptedException e) {
378 log.error("Failed to check device availability", e);
379 }
380 }
381
382 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li858ccd72021-02-04 17:25:01 +0900383 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
384 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
385 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Li556709c2021-02-03 17:54:28 +0900386
Daniel Parkf3136042021-03-10 07:49:11 +0900387 setDhcpRuleForTenantNetwork(deviceId, true);
Jian Li556709c2021-02-03 17:54:28 +0900388 setForwardingRule(deviceId, true);
389
390 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
391 }
392
Daniel Parkf3136042021-03-10 07:49:11 +0900393 private void setDhcpRuleForTenantNetwork(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900394 TrafficSelector selector = DefaultTrafficSelector.builder()
395 .matchEthType(Ethernet.TYPE_IPV4)
396 .matchIPProtocol(IPv4.PROTOCOL_UDP)
397 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
398 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
399 .build();
400
401 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
402 .punt()
403 .build();
404
405 flowService.setRule(
406 appId,
407 deviceId,
408 selector,
409 treatment,
410 PRIORITY_DHCP_RULE,
411 TENANT_DHCP_TABLE,
412 install);
413 }
414
Jian Li858ccd72021-02-04 17:25:01 +0900415 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900416 TrafficSelector selector = DefaultTrafficSelector.builder().build();
417 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
418 .setOutput(PortNumber.NORMAL)
419 .build();
420
421 flowService.setRule(
422 appId,
423 deviceId,
424 selector,
425 treatment,
Jian Li858ccd72021-02-04 17:25:01 +0900426 PRIORITY_FORWARDING_RULE,
Jian Li556709c2021-02-03 17:54:28 +0900427 TENANT_FORWARDING_TABLE,
428 install);
429 }
430
Daniel Park2884b232021-03-04 18:58:47 +0900431 private void initGatewayNodeForInternalNetwork(KubevirtNetwork network,
432 KubevirtRouter router,
433 KubevirtNode electedGateway,
434 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900435 switch (network.type()) {
436 case VXLAN:
437 case GRE:
438 case GENEVE:
Daniel Parkf3136042021-03-10 07:49:11 +0900439 setDefaultEgressRuleToGatewayNode(router, network, electedGateway.intgBridge(), install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900440 kubevirtNodeService.completeNodes(WORKER).forEach(node -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900441 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900442 electedGateway.intgBridge(),
443 network.tenantDeviceId(node.hostname()), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900444 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900445 electedGateway.intgBridge(),
446 network.tenantDeviceId(node.hostname()), install);
Jian Li517597a2021-03-22 11:04:52 +0900447 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
Daniel Parkf3136042021-03-10 07:49:11 +0900448 electedGateway.intgBridge(), node, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900449 });
Daniel Park4cb120b2021-03-24 12:30:50 +0900450 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900451 break;
452 case FLAT:
453 case VLAN:
Daniel Parkf3136042021-03-10 07:49:11 +0900454 setGatewayArpRuleForProviderInternalNetwork(router, network, PRE_FLAT_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900455 electedGateway.intgBridge(), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900456 setGatewayIcmpRuleForProviderInternalNetwork(router, network, PRE_FLAT_TABLE,
Daniel Parkbabde9c2021-03-09 13:37:42 +0900457 electedGateway.intgBridge(), install);
Daniel Parkf3136042021-03-10 07:49:11 +0900458 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900459 break;
460 default:
461 // do nothing
462 break;
463 }
Daniel Park2884b232021-03-04 18:58:47 +0900464 }
465
Jian Li517597a2021-03-22 11:04:52 +0900466 private void setDefaultGatewayRuleToWorkerNodeTunBridge(KubevirtRouter router,
467 KubevirtNetwork network,
468 DeviceId gwDeviceId,
469 KubevirtNode workerNode,
470 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900471 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900472
Daniel Parkf3136042021-03-10 07:49:11 +0900473 if (routerMacAddress == null) {
474 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
475 "there's no br-int port for device {}", gwDeviceId);
476 return;
477 }
478
479 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
480
481 if (gwNode == null) {
482 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
483 "there's no gateway node for device {}", gwDeviceId);
484 return;
485 }
486
487
488 PortNumber patchPortNumber = tunnelToTenantPort(workerNode, network);
489 if (patchPortNumber == null) {
490 return;
491 }
492
493 PortNumber tunnelPortNumber = tunnelPort(workerNode, network);
494 if (tunnelPortNumber == null) {
495 return;
496 }
497
498 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
499 .matchInPort(patchPortNumber)
500 .matchEthType(Ethernet.TYPE_IPV4)
501 .matchEthDst((routerMacAddress));
502
503 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
504 .setTunnelId(Long.parseLong(network.segmentId()))
505 .extension(buildExtension(
506 deviceService,
507 workerNode.tunBridge(),
508 gwNode.dataIp().getIp4Address()),
509 workerNode.tunBridge())
510 .setOutput(tunnelPortNumber);
511
512 flowService.setRule(
513 appId,
514 workerNode.tunBridge(),
515 sBuilder.build(),
516 tBuilder.build(),
517 PRIORITY_FORWARDING_RULE,
518 TUNNEL_DEFAULT_TABLE,
519 install);
520 }
521
522 private void setDefaultEgressRuleToGatewayNode(KubevirtRouter router,
523 KubevirtNetwork network,
524 DeviceId gwDeviceId,
525 boolean install) {
526 MacAddress routerMacAddress = getRouterMacAddress(router);
527
528 if (routerMacAddress == null) {
529 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
530 "there's no br-int port for device {}", gwDeviceId);
531 return;
532 }
533
534 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
535
536 if (gwNode == null) {
537 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
538 "there's no gateway node for device {}", gwDeviceId);
539 return;
540 }
541
542 PortNumber tunToIntPortNum = portNumber(gwNode.tunBridge(), TUNNEL_TO_INTEGRATION);
543
544 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
545 .matchTunnelId(Long.parseLong(network.segmentId()));
546
547 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
548 .setOutput(tunToIntPortNum);
549
550 flowService.setRule(
551 appId,
552 gwNode.tunBridge(),
553 sBuilder.build(),
554 tBuilder.build(),
555 PRIORITY_TUNNEL_RULE,
556 TUNNEL_DEFAULT_TABLE,
557 install);
558 }
559
560
561 private void setGatewayIcmpRuleForTenantInternalNetwork(KubevirtRouter router,
562 KubevirtNetwork network,
563 int tableNum,
564 DeviceId gwDeviceId,
565 DeviceId tenantDeviceId,
566 boolean install) {
567 MacAddress routerMacAddress = getRouterMacAddress(router);
568
569 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900570 log.warn("Setting gateway ICMP rule for internal network because " +
571 "there's no br-int port for device {}", gwDeviceId);
572 return;
573 }
574
575 Device device = deviceService.getDevice(tenantDeviceId);
576
577 if (device == null) {
578 log.warn("Setting gateway icmp rule for internal network because " +
579 "there's no tenant device for {} to install gateway arp rule",
580 tenantDeviceId);
581 return;
582 }
583
584
585 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
586 .matchEthType(Ethernet.TYPE_IPV4)
587 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
588 .matchIcmpType(TYPE_ECHO_REQUEST)
589 .matchIcmpCode(CODE_ECHO_REQEUST)
590 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
591
592 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
593 .extension(buildMoveEthSrcToDstExtension(device), device.id())
594 .extension(buildMoveIpSrcToDstExtension(device), device.id())
595 .extension(buildLoadExtension(device,
596 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
597 .extension(buildLoadExtension(device,
598 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
599 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900600 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900601 .setOutput(PortNumber.IN_PORT);
602
603 flowService.setRule(
604 appId,
605 tenantDeviceId,
606 sBuilder.build(),
607 tBuilder.build(),
608 PRIORITY_ICMP_RULE,
609 tableNum,
610 install);
611 }
612
Daniel Parkf3136042021-03-10 07:49:11 +0900613 private void setGatewayArpRuleForTenantInternalNetwork(KubevirtRouter router,
614 KubevirtNetwork network,
615 int tableNum,
616 DeviceId gwDeviceId,
617 DeviceId tenantDeviceId,
618 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900619
Daniel Parkf3136042021-03-10 07:49:11 +0900620 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900621
Daniel Parkf3136042021-03-10 07:49:11 +0900622 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900623 log.warn("Setting gateway arp rule for internal network because " +
624 "there's no br-int port for device {}", gwDeviceId);
625 return;
626 }
627
628 Device device = deviceService.getDevice(tenantDeviceId);
629
630 if (device == null) {
631 log.warn("Setting gateway arp rule for internal network because " +
632 "there's no tenant device for {} to install gateway arp rule",
633 tenantDeviceId);
634 return;
635 }
636
637
638 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
639 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
640 .matchArpOp(ARP.OP_REQUEST)
641 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
642
643 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
644 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
645 .extension(buildMoveArpShaToThaExtension(device), device.id())
646 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
647 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900648 .setArpSha(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900649 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900650 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900651 .setOutput(PortNumber.IN_PORT);
652
653 flowService.setRule(
654 appId,
655 device.id(),
656 sBuilder.build(),
657 tBuilder.build(),
658 PRIORITY_ARP_GATEWAY_RULE,
659 tableNum,
660 install
661 );
662 }
663
Daniel Parkf3136042021-03-10 07:49:11 +0900664 private void setGatewayProviderInterNetworkRoutingWithinSameRouter(
Daniel Parkbabde9c2021-03-09 13:37:42 +0900665 KubevirtNetwork network, KubevirtRouter router, KubevirtNode gatewayNode, boolean install) {
Daniel Park2884b232021-03-04 18:58:47 +0900666 router.internal().forEach(srcNetwork -> {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900667 if (srcNetwork.equals(network.networkId())
668 || kubevirtNetworkService.network(srcNetwork) == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900669 return;
670 }
671
Daniel Parkbabde9c2021-03-09 13:37:42 +0900672 kubevirtPortService.ports(network.networkId()).forEach(port -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900673 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900674 port, gatewayNode, install);
675 });
Daniel Park2884b232021-03-04 18:58:47 +0900676 });
677 }
678
Daniel Parkf3136042021-03-10 07:49:11 +0900679 private void setGatewayInterNetworkRoutingFromNetworkToPort(KubevirtRouter router,
680 KubevirtNetwork srcNetwork,
681 KubevirtPort dstPort,
682 KubevirtNode gatewayNode,
683 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900684 Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
685
686 if (gwDevice == null) {
687 log.warn("Failed to set internal network routing rule because " +
688 "there's no device Id for device {}", gatewayNode.intgBridge());
689 return;
690 }
691
Daniel Parkf3136042021-03-10 07:49:11 +0900692 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900693
Daniel Parkf3136042021-03-10 07:49:11 +0900694 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900695 log.warn("Failed to set internal network routing rule because " +
696 "there's no br-int port for device {}", gatewayNode.intgBridge());
697 return;
698 }
699
Daniel Park4cb120b2021-03-24 12:30:50 +0900700 TrafficSelector.Builder sBuilder;
701 TrafficTreatment treatment;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900702
Daniel Park4cb120b2021-03-24 12:30:50 +0900703 if (srcNetwork.type() == FLAT || srcNetwork.type() == VLAN) {
704 sBuilder = DefaultTrafficSelector.builder()
705 .matchEthType(Ethernet.TYPE_IPV4)
706 .matchEthDst(routerMacAddress)
707 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
708 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
Daniel Parkbabde9c2021-03-09 13:37:42 +0900709
Daniel Park4cb120b2021-03-24 12:30:50 +0900710 treatment = DefaultTrafficTreatment.builder()
711 .setEthSrc(routerMacAddress)
712 .setEthDst(dstPort.macAddress())
713 .transition(FORWARDING_TABLE)
714 .build();
715
716 flowService.setRule(
717 appId,
718 gwDevice.id(),
719 sBuilder.build(),
720 treatment,
721 PRIORITY_INTERNAL_ROUTING_RULE,
722 PRE_FLAT_TABLE,
723 install);
724 } else {
725 KubevirtNetwork dstNetwork = kubevirtNetworkService.network(dstPort.networkId());
726 if (dstNetwork == null) {
727 return;
728 }
729
730 KubevirtNode dstPortWorkerNode = kubevirtNodeService.node(dstPort.deviceId());
731 if (dstPortWorkerNode == null) {
732 return;
733 }
734
735 sBuilder = DefaultTrafficSelector.builder()
736 .matchEthType(Ethernet.TYPE_IPV4)
737 .matchEthDst(routerMacAddress)
738 .matchTunnelId(Long.parseLong(srcNetwork.segmentId()))
739 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
740 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
741
742 treatment = DefaultTrafficTreatment.builder()
743 .setTunnelId(Long.parseLong(dstNetwork.segmentId()))
744 .setEthSrc(routerMacAddress)
745 .setEthDst(dstPort.macAddress())
746 .extension(buildExtension(
747 deviceService,
748 gatewayNode.tunBridge(),
749 dstPortWorkerNode.dataIp().getIp4Address()),
750 gatewayNode.tunBridge())
751 .setOutput(PortNumber.IN_PORT)
752 .build();
753
754 flowService.setRule(
755 appId,
756 gatewayNode.tunBridge(),
757 sBuilder.build(),
758 treatment,
759 PRIORITY_INTERNAL_ROUTING_RULE,
760 TUNNEL_DEFAULT_TABLE,
761 install);
762 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900763 }
764
Daniel Parkf3136042021-03-10 07:49:11 +0900765 private void setGatewayArpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
766 int tableNum, DeviceId gwDeviceId, boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900767
768
769 Device device = deviceService.getDevice(gwDeviceId);
Daniel Parkf3136042021-03-10 07:49:11 +0900770 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900771
Daniel Parkf3136042021-03-10 07:49:11 +0900772 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900773 log.warn("Setting gateway arp rule for internal network because " +
774 "there's no br-int port for device {}", gwDeviceId);
Daniel Park2884b232021-03-04 18:58:47 +0900775 return;
776 }
777
Jian Li858ccd72021-02-04 17:25:01 +0900778 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
779 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
780 .matchArpOp(ARP.OP_REQUEST)
781 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
782
783 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
784 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
785 .extension(buildMoveArpShaToThaExtension(device), device.id())
786 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
787 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900788 .setArpSha(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900789 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900790 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900791 .setOutput(PortNumber.IN_PORT);
792
793 flowService.setRule(
794 appId,
795 device.id(),
796 sBuilder.build(),
797 tBuilder.build(),
798 PRIORITY_ARP_GATEWAY_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900799 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900800 install
801 );
802 }
803
Daniel Park2884b232021-03-04 18:58:47 +0900804 /**
805 * Sends ICMP echo reply for the ICMP echo request from the kubevirt VM.
806 *
Daniel Parkf3136042021-03-10 07:49:11 +0900807 * @param router kubevirt router
Daniel Park2884b232021-03-04 18:58:47 +0900808 * @param network kubevirt network
809 * @param tableNum flow table number
810 * @param deviceId device id of the selected gateway for the network
811 * @param install install if true, remove otherwise
812 */
Daniel Parkf3136042021-03-10 07:49:11 +0900813 private void setGatewayIcmpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
814 int tableNum, DeviceId deviceId, boolean install) {
815 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900816
Daniel Parkf3136042021-03-10 07:49:11 +0900817 if (routerMacAddress == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900818 log.error("Setting gateway ICMP rule for internal network because " +
819 "there's no br-int port for device {}", deviceId);
820 return;
821 }
822
Jian Li858ccd72021-02-04 17:25:01 +0900823 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
824 .matchEthType(Ethernet.TYPE_IPV4)
825 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
826 .matchIcmpType(TYPE_ECHO_REQUEST)
827 .matchIcmpCode(CODE_ECHO_REQEUST)
828 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
829
830 Device device = deviceService.getDevice(deviceId);
831 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
832 .extension(buildMoveEthSrcToDstExtension(device), device.id())
833 .extension(buildMoveIpSrcToDstExtension(device), device.id())
834 .extension(buildLoadExtension(device,
835 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
836 .extension(buildLoadExtension(device,
837 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
838 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900839 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900840 .setOutput(PortNumber.IN_PORT);
841
842 flowService.setRule(
843 appId,
844 deviceId,
845 sBuilder.build(),
846 tBuilder.build(),
847 PRIORITY_ICMP_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900848 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900849 install);
850 }
851
Jian Lifc7e6cf2021-04-08 11:13:24 +0900852 private void reserveVrouterIp(KubevirtNetwork network) {
853 String networkId = network.networkId();
854 IpAddress vrouterIp = network.ipPool().start();
855
856 networkService.reserveIp(networkId, vrouterIp);
857 }
858
Daniel Park2884b232021-03-04 18:58:47 +0900859 private class InternalRouterEventListener implements KubevirtRouterListener {
860 private boolean isRelevantHelper() {
861 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Daniel Parka8968802021-02-25 09:14:22 +0900862 }
863
Daniel Park2884b232021-03-04 18:58:47 +0900864 @Override
865 public void event(KubevirtRouterEvent event) {
866 switch (event.type()) {
867 case KUBEVIRT_ROUTER_CREATED:
868 eventExecutor.execute(() -> processRouterCreation(event.subject()));
869 break;
870 case KUBEVIRT_ROUTER_REMOVED:
871 eventExecutor.execute(() -> processRouterDeletion(event.subject()));
872 break;
873 case KUBEVIRT_ROUTER_UPDATED:
874 eventExecutor.execute(() -> processRouterUpdate(event.subject()));
875 break;
876 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_ATTACHED:
877 eventExecutor.execute(() -> processRouterInternalNetworksAttached(event.subject(),
878 event.internal()));
879 break;
880 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_DETACHED:
881 eventExecutor.execute(() -> processRouterInternalNetworksDetached(event.subject(),
882 event.internal()));
883 break;
884 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
885 eventExecutor.execute(() -> processRouterGatewayNodeAttached(event.subject(),
886 event.gateway()));
887 break;
888 case KUBEVIRT_GATEWAY_NODE_DETACHED:
889 eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(),
890 event.gateway()));
891 break;
892 case KUBEVIRT_GATEWAY_NODE_CHANGED:
893 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
894 event.gateway()));
895 break;
Daniel Parka8968802021-02-25 09:14:22 +0900896
Daniel Park2884b232021-03-04 18:58:47 +0900897 default:
898 //do nothing
899 break;
900 }
901 }
902
903 private void processRouterCreation(KubevirtRouter router) {
904 // When a router is created, we performs the election process to associate the router
905 // to the specific gateway. After the election, KubevirtNetwork handler installs bunch of rules
906 // to elected gateway node so that VMs associated to the router can ping to their gateway IP.
907 // SNAT and floating ip rule setup is out of this handler's scope and would be done with the other handlers
908 if (!isRelevantHelper()) {
909 return;
910 }
911 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
912 if (electedGw == null) {
913 return;
914 }
915
916 router.internal().forEach(networkName -> {
917 KubevirtNetwork network = networkService.network(networkName);
918
919 if (network != null) {
920 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
921 }
922 });
923 kubevirtRouterService.updateRouter(router.updatedElectedGateway(electedGw.hostname()));
924 }
925
926 private void processRouterDeletion(KubevirtRouter router) {
927 if (!isRelevantHelper()) {
928 return;
929 }
930 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
931 if (electedGw == null) {
932 return;
933 }
934
935 router.internal().forEach(networkName -> {
936 KubevirtNetwork network = networkService.network(networkName);
937
938 if (network != null) {
939 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
940 }
941 });
942 }
943
944 private void processRouterUpdate(KubevirtRouter router) {
945 if (!isRelevantHelper()) {
946 return;
947 }
948 if (router.electedGateway() == null) {
949 return;
950 }
951
952 KubevirtNode electedGw = nodeService.node(router.electedGateway());
953
954 router.internal().forEach(networkName -> {
955 KubevirtNetwork network = networkService.network(networkName);
956
957 if (network != null) {
958 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
959 }
960 });
961 }
962
963 private void processRouterInternalNetworksAttached(KubevirtRouter router,
964 Set<String> attachedInternalNetworks) {
965 if (!isRelevantHelper()) {
966 return;
967 }
968 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
969 if (electedGw == null) {
970 return;
971 }
972
973 attachedInternalNetworks.forEach(networkName -> {
974 KubevirtNetwork network = networkService.network(networkName);
975
976 if (network != null) {
977 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
978 }
979 });
980 }
981
982 private void processRouterInternalNetworksDetached(KubevirtRouter router,
983 Set<String> detachedInternalNetworks) {
984 if (!isRelevantHelper()) {
985 return;
986 }
987 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
988 if (electedGw == null) {
989 return;
990 }
991
992 detachedInternalNetworks.forEach(networkName -> {
993 KubevirtNetwork network = networkService.network(networkName);
994
995 if (network != null) {
996 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
997 }
Daniel Park2884b232021-03-04 18:58:47 +0900998
Daniel Parkbabde9c2021-03-09 13:37:42 +0900999 removeDetachedInternalNetworkRules(network, router, electedGw);
1000 });
1001 }
1002
1003 private void removeDetachedInternalNetworkRules(KubevirtNetwork removedNetwork, KubevirtRouter router,
1004 KubevirtNode electedGw) {
Daniel Parkf3136042021-03-10 07:49:11 +09001005 router.internal().stream().filter(networkId -> kubevirtNetworkService.network(networkId) != null)
1006 .forEach(networkId -> {
1007 kubevirtPortService.ports(networkId).forEach(kubevirtPort -> {
1008 setGatewayInterNetworkRoutingFromNetworkToPort(
1009 router, removedNetwork, kubevirtPort, electedGw, false);
1010 });
Daniel Parkbabde9c2021-03-09 13:37:42 +09001011 });
Daniel Park2884b232021-03-04 18:58:47 +09001012 }
1013
1014 private void processRouterGatewayNodeAttached(KubevirtRouter router,
1015 String associatedGateway) {
1016 if (!isRelevantHelper()) {
1017 return;
1018 }
1019
1020 KubevirtNode gatewayNode = nodeService.node(associatedGateway);
1021 if (gatewayNode == null) {
1022 return;
1023 }
1024
1025 router.internal().forEach(networkName -> {
1026 KubevirtNetwork network = networkService.network(networkName);
1027
1028 if (network != null) {
1029 initGatewayNodeForInternalNetwork(network, router, gatewayNode, true);
1030 }
1031 });
1032 }
1033
1034 private void processRouterGatewayNodeDetached(KubevirtRouter router,
1035 String disAssociatedGateway) {
1036 if (!isRelevantHelper()) {
1037 return;
1038 }
1039
1040 KubevirtNode gatewayNode = nodeService.node(disAssociatedGateway);
1041 if (gatewayNode == null) {
1042 return;
1043 }
1044
1045 router.internal().forEach(networkName -> {
1046 KubevirtNetwork network = networkService.network(networkName);
1047
1048 if (network != null) {
1049 initGatewayNodeForInternalNetwork(network, router, gatewayNode, false);
1050 }
1051 });
1052 }
1053
1054 private void processRouterGatewayNodeChanged(KubevirtRouter router,
1055 String disAssociatedGateway) {
1056 if (!isRelevantHelper()) {
1057 return;
1058 }
1059
1060 KubevirtNode oldGatewayNode = nodeService.node(disAssociatedGateway);
1061 if (oldGatewayNode == null) {
1062 return;
1063 }
1064
1065 router.internal().forEach(networkName -> {
1066 KubevirtNetwork network = networkService.network(networkName);
1067
1068 if (network != null) {
1069 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, false);
1070 }
1071 });
1072
1073 KubevirtNode newGatewayNode = nodeService.node(router.electedGateway());
1074 if (newGatewayNode == null) {
1075 return;
1076 }
1077
1078 router.internal().forEach(networkName -> {
1079 KubevirtNetwork network = networkService.network(networkName);
1080
1081 if (network != null) {
1082 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, true);
1083 }
1084 });
1085 }
Daniel Parka8968802021-02-25 09:14:22 +09001086 }
1087
Jian Li556709c2021-02-03 17:54:28 +09001088 private class InternalNetworkEventListener implements KubevirtNetworkListener {
1089
1090 private boolean isRelevantHelper() {
1091 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1092 }
1093
1094 @Override
1095 public void event(KubevirtNetworkEvent event) {
1096 switch (event.type()) {
1097 case KUBEVIRT_NETWORK_CREATED:
1098 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
1099 break;
1100 case KUBEVIRT_NETWORK_REMOVED:
1101 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
1102 break;
1103 case KUBEVIRT_NETWORK_UPDATED:
1104 default:
1105 // do nothing
1106 break;
1107 }
1108 }
1109
1110 private void processNetworkCreation(KubevirtNetwork network) {
1111 if (!isRelevantHelper()) {
1112 return;
1113 }
1114
1115 switch (network.type()) {
1116 case VXLAN:
1117 case GRE:
1118 case GENEVE:
1119 initIntegrationTunnelBridge(network);
1120 break;
1121 case FLAT:
Jian Lifc7e6cf2021-04-08 11:13:24 +09001122 reserveVrouterIp(network);
1123 break;
Jian Li2ce718e2021-02-17 20:42:15 +09001124 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001125 break;
Jian Li556709c2021-02-03 17:54:28 +09001126 default:
1127 // do nothing
1128 break;
1129 }
1130 }
1131
1132 private void processNetworkRemoval(KubevirtNetwork network) {
1133 if (!isRelevantHelper()) {
1134 return;
1135 }
1136
1137 switch (network.type()) {
1138 case VXLAN:
1139 case GRE:
1140 case GENEVE:
1141 purgeIntegrationTunnelBridge(network);
1142 break;
1143 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001144 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001145 break;
Jian Li556709c2021-02-03 17:54:28 +09001146 default:
1147 // do nothing
1148 break;
1149 }
1150 }
1151
1152 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
1153 if (network.segmentId() == null) {
1154 return;
1155 }
1156
Jian Li94b6d162021-04-15 17:09:11 +09001157 nodeService.completeNodes(WORKER).forEach(n -> {
Jian Li556709c2021-02-03 17:54:28 +09001158 createBridge(n, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001159 createPatchTenantInterface(n, network);
1160 setDefaultRulesForTenantNetwork(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001161 });
1162 }
1163
1164 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
1165 if (network.segmentId() == null) {
1166 return;
1167 }
1168
1169 nodeService.completeNodes().forEach(n -> {
1170 removePatchInterface(n, network);
1171 removeBridge(n, network);
1172 });
1173 }
1174 }
1175
1176 private class InternalNodeEventListener implements KubevirtNodeListener {
1177
1178 private boolean isRelevantHelper() {
1179 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1180 }
1181
1182 @Override
1183 public void event(KubevirtNodeEvent event) {
1184 switch (event.type()) {
1185 case KUBEVIRT_NODE_COMPLETE:
1186 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
1187 break;
Daniel Park2884b232021-03-04 18:58:47 +09001188 case KUBEVIRT_NODE_REMOVED:
1189 eventExecutor.execute(() -> processNodeDeletion(event.subject()));
1190 break;
Jian Li556709c2021-02-03 17:54:28 +09001191 case KUBEVIRT_NODE_INCOMPLETE:
1192 case KUBEVIRT_NODE_UPDATED:
1193 default:
1194 // do nothing
1195 break;
1196 }
1197 }
1198
1199 private void processNodeCompletion(KubevirtNode node) {
1200 if (!isRelevantHelper()) {
1201 return;
1202 }
1203
Daniel Parka8968802021-02-25 09:14:22 +09001204 if (node.type().equals(WORKER)) {
1205 for (KubevirtNetwork network : networkService.networks()) {
1206 switch (network.type()) {
1207 case VXLAN:
1208 case GRE:
1209 case GENEVE:
1210 if (network.segmentId() == null) {
1211 continue;
1212 }
1213 createBridge(node, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001214 createPatchTenantInterface(node, network);
1215 setDefaultRulesForTenantNetwork(node, network);
1216 setArpRulesForTenantNetwork(node, network);
1217 setIcmpRulesForTenantNetwork(node, network);
1218 setDefaultGatewayRuleToWorkerNodeWhenNodeCreated(node, network);
Daniel Parka8968802021-02-25 09:14:22 +09001219 break;
1220 case FLAT:
Jian Lifc7e6cf2021-04-08 11:13:24 +09001221 reserveVrouterIp(network);
1222 break;
Daniel Parka8968802021-02-25 09:14:22 +09001223 case VLAN:
1224 default:
1225 // do nothing
1226 break;
1227 }
1228 }
1229 } else if (node.type().equals(GATEWAY)) {
Daniel Park2884b232021-03-04 18:58:47 +09001230 updateGatewayNodeForRouter();
Daniel Parka8968802021-02-25 09:14:22 +09001231 for (KubevirtNetwork network : networkService.networks()) {
1232 switch (network.type()) {
1233 case FLAT:
1234 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001235 break;
1236 case VXLAN:
1237 case GRE:
1238 case GENEVE:
1239 default:
1240 // do nothing
1241 break;
1242 }
Jian Li556709c2021-02-03 17:54:28 +09001243 }
1244 }
1245 }
Daniel Park2884b232021-03-04 18:58:47 +09001246
1247 private void processNodeDeletion(KubevirtNode node) {
1248 if (!isRelevantHelper()) {
1249 return;
1250 }
1251
1252 if (node.type().equals(GATEWAY)) {
1253 updateGatewayNodeForRouter();
1254 for (KubevirtNetwork network : networkService.networks()) {
1255 switch (network.type()) {
1256 case FLAT:
1257 case VLAN:
1258 break;
1259 case VXLAN:
1260 case GRE:
1261 case GENEVE:
1262 default:
1263 // do nothing
1264 break;
1265 }
1266 }
1267 }
1268 }
1269
1270 private void updateGatewayNodeForRouter() {
1271 kubevirtRouterService.routers().forEach(router -> {
1272 KubevirtNode newGwNode = gatewayNodeForSpecifiedRouter(nodeService, router);
1273
1274 if (newGwNode == null) {
1275 return;
1276 }
1277 kubevirtRouterService.updateRouter(router.updatedElectedGateway(newGwNode.hostname()));
1278 });
1279 }
Jian Li556709c2021-02-03 17:54:28 +09001280 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001281
1282 private class InternalKubevirtPortListener implements KubevirtPortListener {
1283
1284 private boolean isRelevantHelper() {
1285 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1286 }
1287
1288 @Override
1289 public void event(KubevirtPortEvent event) {
1290 switch (event.type()) {
1291 case KUBEVIRT_PORT_CREATED:
1292 eventExecutor.execute(() -> processPortCreation(event.subject()));
1293 break;
1294 case KUBEVIRT_PORT_UPDATED:
1295 eventExecutor.execute(() -> processPortUpdate(event.subject()));
1296 break;
1297 case KUBEVIRT_PORT_REMOVED:
1298 eventExecutor.execute(() -> processPortDeletion(event.subject()));
1299 break;
1300 default:
1301 //do nothing
1302 break;
1303 }
1304 }
1305
1306 private void processPortCreation(KubevirtPort kubevirtPort) {
1307 if (!isRelevantHelper()) {
1308 return;
1309 }
1310
1311 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1312 if (router == null) {
1313 return;
1314 }
1315
1316 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1317
1318 if (gwNode != null) {
1319
1320 router.internal().forEach(srcNetwork -> {
1321 if (srcNetwork.equals(kubevirtPort.networkId())
1322 || kubevirtNetworkService.network(srcNetwork) == null) {
1323 return;
1324 }
Daniel Parkf3136042021-03-10 07:49:11 +09001325 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001326 kubevirtPort, gwNode, true);
1327 });
1328 }
1329 }
1330
1331 private void processPortUpdate(KubevirtPort kubevirtPort) {
1332 if (!isRelevantHelper()) {
1333 return;
1334 }
1335
1336 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1337 if (router == null) {
1338 return;
1339 }
1340
1341 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1342
1343 if (gwNode != null) {
1344
1345 router.internal().forEach(srcNetwork -> {
1346 if (srcNetwork.equals(kubevirtPort.networkId())
1347 || kubevirtNetworkService.network(srcNetwork) == null) {
1348 return;
1349 }
Daniel Parkf3136042021-03-10 07:49:11 +09001350 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001351 kubevirtPort, gwNode, true);
1352 });
1353 }
1354 }
1355
1356 private void processPortDeletion(KubevirtPort kubevirtPort) {
1357 if (!isRelevantHelper()) {
1358 return;
1359 }
1360
1361 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1362 if (router == null) {
1363 return;
1364 }
1365
1366 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1367
1368 if (gwNode != null) {
1369
1370 router.internal().forEach(srcNetwork -> {
1371 if (srcNetwork.equals(kubevirtPort.networkId())
1372 || kubevirtNetworkService.network(srcNetwork) == null) {
1373 return;
1374 }
Daniel Parkf3136042021-03-10 07:49:11 +09001375 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001376 kubevirtPort, gwNode, false);
1377 });
1378 }
1379
1380 }
1381 }
Jian Li556709c2021-02-03 17:54:28 +09001382}