blob: ed8e1e44697c7a5bede79ee182909b5637add592 [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 Li0c656f02021-06-07 13:32:39 +090019import org.onlab.osgi.DefaultServiceDirectory;
Jian Li858ccd72021-02-04 17:25:01 +090020import org.onlab.packet.ARP;
21import org.onlab.packet.EthType;
Jian Li556709c2021-02-03 17:54:28 +090022import org.onlab.packet.Ethernet;
23import org.onlab.packet.IPv4;
Jian Li858ccd72021-02-04 17:25:01 +090024import org.onlab.packet.Ip4Address;
Jian Li556709c2021-02-03 17:54:28 +090025import org.onlab.packet.IpAddress;
Jian Li858ccd72021-02-04 17:25:01 +090026import org.onlab.packet.IpPrefix;
Daniel Park2884b232021-03-04 18:58:47 +090027import org.onlab.packet.MacAddress;
Jian Li556709c2021-02-03 17:54:28 +090028import org.onlab.packet.TpPort;
29import org.onlab.packet.UDP;
30import org.onosproject.cluster.ClusterService;
31import org.onosproject.cluster.LeadershipService;
32import org.onosproject.cluster.NodeId;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
36import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
Jian Lifc7e6cf2021-04-08 11:13:24 +090037import org.onosproject.kubevirtnetworking.api.KubevirtNetworkAdminService;
Jian Li556709c2021-02-03 17:54:28 +090038import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
39import org.onosproject.kubevirtnetworking.api.KubevirtNetworkListener;
40import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
Daniel Parkbabde9c2021-03-09 13:37:42 +090041import org.onosproject.kubevirtnetworking.api.KubevirtPort;
42import org.onosproject.kubevirtnetworking.api.KubevirtPortEvent;
43import org.onosproject.kubevirtnetworking.api.KubevirtPortListener;
44import org.onosproject.kubevirtnetworking.api.KubevirtPortService;
Daniel Park2884b232021-03-04 18:58:47 +090045import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
46import org.onosproject.kubevirtnetworking.api.KubevirtRouterAdminService;
47import org.onosproject.kubevirtnetworking.api.KubevirtRouterEvent;
48import org.onosproject.kubevirtnetworking.api.KubevirtRouterListener;
Jian Li556709c2021-02-03 17:54:28 +090049import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
50import org.onosproject.kubevirtnode.api.KubevirtNode;
51import org.onosproject.kubevirtnode.api.KubevirtNodeEvent;
52import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
53import org.onosproject.kubevirtnode.api.KubevirtNodeService;
54import org.onosproject.net.Device;
55import org.onosproject.net.DeviceId;
Jian Li0c656f02021-06-07 13:32:39 +090056import org.onosproject.net.Port;
Jian Li556709c2021-02-03 17:54:28 +090057import org.onosproject.net.PortNumber;
58import org.onosproject.net.behaviour.BridgeConfig;
59import org.onosproject.net.behaviour.BridgeDescription;
60import org.onosproject.net.behaviour.BridgeName;
61import org.onosproject.net.behaviour.ControllerInfo;
62import org.onosproject.net.behaviour.DefaultBridgeDescription;
63import org.onosproject.net.behaviour.DefaultPatchDescription;
64import org.onosproject.net.behaviour.InterfaceConfig;
65import org.onosproject.net.behaviour.PatchDescription;
66import org.onosproject.net.device.DeviceAdminService;
Jian Li0c656f02021-06-07 13:32:39 +090067import org.onosproject.net.device.DeviceService;
Daniel Parka8968802021-02-25 09:14:22 +090068import org.onosproject.net.driver.DriverService;
Jian Li556709c2021-02-03 17:54:28 +090069import org.onosproject.net.flow.DefaultTrafficSelector;
70import org.onosproject.net.flow.DefaultTrafficTreatment;
71import org.onosproject.net.flow.TrafficSelector;
72import org.onosproject.net.flow.TrafficTreatment;
73import org.osgi.service.component.annotations.Activate;
74import org.osgi.service.component.annotations.Component;
75import org.osgi.service.component.annotations.Deactivate;
76import org.osgi.service.component.annotations.Reference;
77import org.osgi.service.component.annotations.ReferenceCardinality;
78import org.slf4j.Logger;
79
80import java.util.List;
81import java.util.Objects;
Daniel Park2884b232021-03-04 18:58:47 +090082import java.util.Set;
Jian Li556709c2021-02-03 17:54:28 +090083import java.util.concurrent.ExecutorService;
84
Jian Li556709c2021-02-03 17:54:28 +090085import static java.util.concurrent.Executors.newSingleThreadExecutor;
Jian Li858ccd72021-02-04 17:25:01 +090086import static org.onlab.packet.ICMP.CODE_ECHO_REQEUST;
87import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
88import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
Jian Li556709c2021-02-03 17:54:28 +090089import static org.onlab.util.Tools.groupedThreads;
Daniel Parkbabde9c2021-03-09 13:37:42 +090090import static org.onosproject.kubevirtnetworking.api.Constants.FORWARDING_TABLE;
Jian Lif89d9602021-04-27 19:05:49 +090091import static org.onosproject.kubevirtnetworking.api.Constants.GW_ENTRY_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090092import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Jian Li8f944d42021-03-23 00:43:29 +090093import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_DEFAULT_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090094import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li556709c2021-02-03 17:54:28 +090095import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090096import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FORWARDING_RULE;
97import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ICMP_RULE;
Daniel Parkbabde9c2021-03-09 13:37:42 +090098import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
Jian Li8f944d42021-03-23 00:43:29 +090099import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_IP_EGRESS_RULE;
100import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_IP_INGRESS_RULE;
Daniel Parkf3136042021-03-10 07:49:11 +0900101import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_TUNNEL_RULE;
Jian Li8f944d42021-03-23 00:43:29 +0900102import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_EGRESS_TABLE;
103import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_INGRESS_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900104import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ARP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +0900105import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_DHCP_TABLE;
106import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900107import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +0900108import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900109import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
Daniel Parkf3136042021-03-10 07:49:11 +0900110import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900111import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Daniel Park4cb120b2021-03-24 12:30:50 +0900112import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
113import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
Daniel Park2884b232021-03-04 18:58:47 +0900114import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.gatewayNodeForSpecifiedRouter;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900115import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtNetwork;
116import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
Daniel Parkf3136042021-03-10 07:49:11 +0900117import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
118import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.portNumber;
Jian Li94b6d162021-04-15 17:09:11 +0900119import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.resolveHostname;
Jian Li556709c2021-02-03 17:54:28 +0900120import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Daniel Parkf3136042021-03-10 07:49:11 +0900121import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
122import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelToTenantPort;
Jian Li0c656f02021-06-07 13:32:39 +0900123import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.waitFor;
Jian Li858ccd72021-02-04 17:25:01 +0900124import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
125import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
Daniel Parkf3136042021-03-10 07:49:11 +0900126import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
Jian Li858ccd72021-02-04 17:25:01 +0900127import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
128import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
129import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
130import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
131import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Li556709c2021-02-03 17:54:28 +0900132import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Parkf3136042021-03-10 07:49:11 +0900133import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_TO_INTEGRATION;
Daniel Parka8968802021-02-25 09:14:22 +0900134import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
135import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Li0c656f02021-06-07 13:32:39 +0900136import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Jian Li556709c2021-02-03 17:54:28 +0900137import static org.slf4j.LoggerFactory.getLogger;
138
139/**
140 * Handles kubevirt network events.
141 */
142@Component(immediate = true)
143public class KubevirtNetworkHandler {
144 protected final Logger log = getLogger(getClass());
145 private static final String DEFAULT_OF_PROTO = "tcp";
146 private static final int DEFAULT_OFPORT = 6653;
147 private static final int DPID_BEGIN = 3;
Jian Li858ccd72021-02-04 17:25:01 +0900148 private static final int DEFAULT_TTL = 0xff;
Jian Li556709c2021-02-03 17:54:28 +0900149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
151 protected CoreService coreService;
152
153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
154 protected ClusterService clusterService;
155
156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
157 protected LeadershipService leadershipService;
158
159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
160 protected DeviceAdminService deviceService;
161
162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
163 protected KubevirtApiConfigService apiConfigService;
164
165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
166 protected KubevirtNodeService nodeService;
167
168 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lifc7e6cf2021-04-08 11:13:24 +0900169 protected KubevirtNetworkAdminService networkService;
Jian Li556709c2021-02-03 17:54:28 +0900170
171 @Reference(cardinality = ReferenceCardinality.MANDATORY)
172 protected KubevirtFlowRuleService flowService;
173
Daniel Parka8968802021-02-25 09:14:22 +0900174 @Reference(cardinality = ReferenceCardinality.MANDATORY)
175 protected DriverService driverService;
176
Daniel Park2884b232021-03-04 18:58:47 +0900177 @Reference(cardinality = ReferenceCardinality.MANDATORY)
178 protected KubevirtRouterAdminService kubevirtRouterService;
179
Daniel Parkbabde9c2021-03-09 13:37:42 +0900180 @Reference(cardinality = ReferenceCardinality.MANDATORY)
181 protected KubevirtPortService kubevirtPortService;
182
183 @Reference(cardinality = ReferenceCardinality.MANDATORY)
184 protected KubevirtNetworkService kubevirtNetworkService;
185
186 @Reference(cardinality = ReferenceCardinality.MANDATORY)
187 protected KubevirtNodeService kubevirtNodeService;
188
Jian Li556709c2021-02-03 17:54:28 +0900189 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
190 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
Daniel Parkbabde9c2021-03-09 13:37:42 +0900191 private final KubevirtPortListener portListener = new InternalKubevirtPortListener();
Jian Li556709c2021-02-03 17:54:28 +0900192
Daniel Park2884b232021-03-04 18:58:47 +0900193 private final InternalRouterEventListener kubevirtRouterlistener =
194 new InternalRouterEventListener();
195
Jian Li556709c2021-02-03 17:54:28 +0900196 private final ExecutorService eventExecutor = newSingleThreadExecutor(
197 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
198
199 private ApplicationId appId;
200 private NodeId localNodeId;
201
202 @Activate
203 protected void activate() {
204 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
205 localNodeId = clusterService.getLocalNode().id();
Jian Li556709c2021-02-03 17:54:28 +0900206 leadershipService.runForLeadership(appId.name());
207
Daniel Parkbabde9c2021-03-09 13:37:42 +0900208 networkService.addListener(networkListener);
209 nodeService.addListener(nodeListener);
210 kubevirtPortService.addListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900211 kubevirtRouterService.addListener(kubevirtRouterlistener);
212
Jian Li556709c2021-02-03 17:54:28 +0900213 log.info("Started");
214 }
215
216 @Deactivate
217 protected void deactivate() {
218 networkService.removeListener(networkListener);
219 nodeService.removeListener(nodeListener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900220 kubevirtPortService.removeListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900221 kubevirtRouterService.removeListener(kubevirtRouterlistener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900222 leadershipService.withdraw(appId.name());
Jian Li556709c2021-02-03 17:54:28 +0900223 eventExecutor.shutdown();
224
225 log.info("Stopped");
226 }
227
228 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
229
Jian Li8f944d42021-03-23 00:43:29 +0900230 Device tenantBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
Jian Li7db46722021-06-14 21:28:31 +0900231 if (tenantBridge != null && deviceService.isAvailable(tenantBridge.id())) {
Jian Li8f944d42021-03-23 00:43:29 +0900232 log.warn("The tenant bridge {} already exists at node {}",
Jian Li556709c2021-02-03 17:54:28 +0900233 network.tenantBridgeName(), node.hostname());
Daniel Parkf3136042021-03-10 07:49:11 +0900234 setDefaultRulesForTenantNetwork(node, network);
Jian Li556709c2021-02-03 17:54:28 +0900235 return;
236 }
237
238 Device device = deviceService.getDevice(node.ovsdb());
239
Jian Li94b6d162021-04-15 17:09:11 +0900240 IpAddress serverIp;
241 String serviceFqdn = apiConfigService.apiConfig().serviceFqdn();
242 IpAddress serviceIp = null;
243
244 if (serviceFqdn != null) {
245 serviceIp = resolveHostname(serviceFqdn);
246 }
247
248 if (serviceIp != null) {
249 serverIp = serviceIp;
250 } else {
251 serverIp = apiConfigService.apiConfig().ipAddress();
252 }
253
Jian Li556709c2021-02-03 17:54:28 +0900254 ControllerInfo controlInfo =
255 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
256 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
257
258 String dpid = network.tenantDeviceId(
259 node.hostname()).toString().substring(DPID_BEGIN);
260
Jian Li0c656f02021-06-07 13:32:39 +0900261 // if the bridge is already available, we skip creating a new bridge
262 if (!deviceService.isAvailable(DeviceId.deviceId(dpid))) {
263 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
264 .name(network.tenantBridgeName())
265 .failMode(BridgeDescription.FailMode.SECURE)
266 .datapathId(dpid)
267 .disableInBand()
268 .controllers(controllers);
Jian Li556709c2021-02-03 17:54:28 +0900269
Jian Li0c656f02021-06-07 13:32:39 +0900270 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
271 bridgeConfig.addBridge(builder.build());
272
Jian Li7db46722021-06-14 21:28:31 +0900273 log.info("Created a new tunnel bridge for network {} at node {}",
274 network.networkId(), node.hostname());
275
Jian Li0c656f02021-06-07 13:32:39 +0900276 waitFor(3);
277 }
Jian Li556709c2021-02-03 17:54:28 +0900278 }
279
280 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
281 Device device = deviceService.getDevice(node.ovsdb());
282
283 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
284
285 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
286 bridgeConfig.deleteBridge(bridgeName);
287 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
288 }
289
Daniel Parkf3136042021-03-10 07:49:11 +0900290 private void createPatchTenantInterface(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900291 Device device = deviceService.getDevice(node.ovsdb());
292
293 if (device == null || !device.is(InterfaceConfig.class)) {
294 log.error("Failed to create patch interface on {}", node.ovsdb());
295 return;
296 }
297
298 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
299
Jian Li858ccd72021-02-04 17:25:01 +0900300 String tenantToTunIntf =
301 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
302 String tunToTenantIntf =
303 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900304
Jian Li0c656f02021-06-07 13:32:39 +0900305 if (!hasPort(DeviceId.deviceId(network.tenantBridgeName()), tenantToTunIntf)) {
306 // tenant bridge -> tunnel bridge
307 PatchDescription brTenantTunPatchDesc =
308 DefaultPatchDescription.builder()
309 .deviceId(network.tenantBridgeName())
310 .ifaceName(tenantToTunIntf)
311 .peer(tunToTenantIntf)
312 .build();
Jian Li556709c2021-02-03 17:54:28 +0900313
Jian Li0c656f02021-06-07 13:32:39 +0900314 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900315
Jian Li0c656f02021-06-07 13:32:39 +0900316 waitFor(1);
317 }
318
319 if (!hasPort(DeviceId.deviceId(TUNNEL_BRIDGE), tunToTenantIntf)) {
320 // tunnel bridge -> tenant bridge
321 PatchDescription brTunTenantPatchDesc =
322 DefaultPatchDescription.builder()
323 .deviceId(TUNNEL_BRIDGE)
324 .ifaceName(tunToTenantIntf)
325 .peer(tenantToTunIntf)
326 .build();
327 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
328
329 waitFor(1);
330 }
Jian Li556709c2021-02-03 17:54:28 +0900331 }
332
Jian Liea1ead72021-05-28 11:00:07 +0900333 private void removeAllFlows(KubevirtNode node, KubevirtNetwork network) {
334 DeviceId deviceId = network.tenantDeviceId(node.hostname());
335 flowService.purgeRules(deviceId);
336 }
337
Jian Li556709c2021-02-03 17:54:28 +0900338 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
339 Device device = deviceService.getDevice(node.ovsdb());
340
341 if (device == null || !device.is(InterfaceConfig.class)) {
342 log.error("Failed to create patch interface on {}", node.ovsdb());
343 return;
344 }
345
346 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
347
Jian Li858ccd72021-02-04 17:25:01 +0900348 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900349
350 ifaceConfig.removePatchMode(tunToIntIntf);
351 }
352
Jian Li8f944d42021-03-23 00:43:29 +0900353 private void setGatewayArpRulesForTenantNetwork(KubevirtNode node,
354 KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900355
356 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
357 if (router == null) {
358 return;
359 }
360
361 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
362 if (electedGw == null) {
363 return;
364 }
365
Jian Li8f944d42021-03-23 00:43:29 +0900366 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE,
367 electedGw.intgBridge(), network.tenantDeviceId(node.hostname()), true);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900368 }
369
Jian Li8f944d42021-03-23 00:43:29 +0900370 private void setGatewayIcmpRulesForTenantNetwork(KubevirtNode node,
371 KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900372 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
373 if (router == null) {
374 return;
375 }
376
377 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
378 if (electedGw == null) {
379 return;
380 }
381
Jian Li8f944d42021-03-23 00:43:29 +0900382 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE,
383 electedGw.intgBridge(), network.tenantDeviceId(node.hostname()), true);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900384 }
385
Jian Li8f944d42021-03-23 00:43:29 +0900386 private void setGatewayRuleToWorkerNodeWhenNodeCreated(KubevirtNode node,
387 KubevirtNetwork network) {
Daniel Parkf3136042021-03-10 07:49:11 +0900388 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
389 if (router == null) {
390 return;
391 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900392
Daniel Parkf3136042021-03-10 07:49:11 +0900393 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
394 if (electedGw == null) {
395 return;
396 }
397
Jian Li8f944d42021-03-23 00:43:29 +0900398 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
399 electedGw.intgBridge(), node, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900400 }
401
Jian Li8f944d42021-03-23 00:43:29 +0900402 private void setDefaultRulesForTenantNetwork(KubevirtNode node,
403 KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900404 DeviceId deviceId = network.tenantDeviceId(node.hostname());
405
406 while (!deviceService.isAvailable(deviceId)) {
407 log.warn("Device {} is not ready for installing rules", deviceId);
Jian Li0c656f02021-06-07 13:32:39 +0900408 waitFor(3);
Jian Li556709c2021-02-03 17:54:28 +0900409 }
410
411 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li858ccd72021-02-04 17:25:01 +0900412 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
413 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
414 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Li556709c2021-02-03 17:54:28 +0900415
Jian Li8f944d42021-03-23 00:43:29 +0900416 setArpRuleForTenantNetwork(deviceId, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900417 setDhcpRuleForTenantNetwork(deviceId, true);
Jian Li556709c2021-02-03 17:54:28 +0900418 setForwardingRule(deviceId, true);
419
Jian Li8f944d42021-03-23 00:43:29 +0900420 // security group related rules
421 setTenantIngressTransitionRule(network, network.tenantDeviceId(node.hostname()), true);
Jian Lif89d9602021-04-27 19:05:49 +0900422 setTenantEgressTransitionRule(network.tenantDeviceId(node.hostname()), true);
Jian Li8f944d42021-03-23 00:43:29 +0900423
Jian Li556709c2021-02-03 17:54:28 +0900424 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
425 }
426
Daniel Parkf3136042021-03-10 07:49:11 +0900427 private void setDhcpRuleForTenantNetwork(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900428 TrafficSelector selector = DefaultTrafficSelector.builder()
429 .matchEthType(Ethernet.TYPE_IPV4)
430 .matchIPProtocol(IPv4.PROTOCOL_UDP)
431 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
432 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
433 .build();
434
435 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
436 .punt()
437 .build();
438
439 flowService.setRule(
440 appId,
441 deviceId,
442 selector,
443 treatment,
444 PRIORITY_DHCP_RULE,
445 TENANT_DHCP_TABLE,
446 install);
447 }
448
Jian Li858ccd72021-02-04 17:25:01 +0900449 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900450 TrafficSelector selector = DefaultTrafficSelector.builder().build();
451 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
452 .setOutput(PortNumber.NORMAL)
453 .build();
454
455 flowService.setRule(
456 appId,
457 deviceId,
458 selector,
459 treatment,
Jian Li858ccd72021-02-04 17:25:01 +0900460 PRIORITY_FORWARDING_RULE,
Jian Li556709c2021-02-03 17:54:28 +0900461 TENANT_FORWARDING_TABLE,
462 install);
463 }
464
Daniel Park2884b232021-03-04 18:58:47 +0900465 private void initGatewayNodeForInternalNetwork(KubevirtNetwork network,
466 KubevirtRouter router,
467 KubevirtNode electedGateway,
468 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900469 switch (network.type()) {
470 case VXLAN:
471 case GRE:
472 case GENEVE:
Jian Li8f944d42021-03-23 00:43:29 +0900473 setDefaultEgressRuleToGatewayNode(router, network,
474 electedGateway.intgBridge(), install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900475 kubevirtNodeService.completeNodes(WORKER).forEach(node -> {
Jian Li8f944d42021-03-23 00:43:29 +0900476 setGatewayArpRuleForTenantInternalNetwork(router, network,
477 TENANT_ARP_TABLE, electedGateway.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900478 network.tenantDeviceId(node.hostname()), install);
Jian Li8f944d42021-03-23 00:43:29 +0900479 setGatewayIcmpRuleForTenantInternalNetwork(router, network,
480 TENANT_ICMP_TABLE, electedGateway.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900481 network.tenantDeviceId(node.hostname()), install);
Jian Li517597a2021-03-22 11:04:52 +0900482 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
Daniel Parkf3136042021-03-10 07:49:11 +0900483 electedGateway.intgBridge(), node, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900484 });
Daniel Park4cb120b2021-03-24 12:30:50 +0900485 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900486 break;
487 case FLAT:
488 case VLAN:
Jian Li8f944d42021-03-23 00:43:29 +0900489 setGatewayArpRuleForProviderInternalNetwork(router, network,
Jian Lif89d9602021-04-27 19:05:49 +0900490 GW_ENTRY_TABLE, electedGateway.intgBridge(), install);
Jian Li8f944d42021-03-23 00:43:29 +0900491 setGatewayIcmpRuleForProviderInternalNetwork(router, network,
Jian Lif89d9602021-04-27 19:05:49 +0900492 GW_ENTRY_TABLE, electedGateway.intgBridge(), install);
Jian Li8f944d42021-03-23 00:43:29 +0900493 setGatewayProviderInterNetworkRoutingWithinSameRouter(network,
494 router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900495 break;
496 default:
497 // do nothing
498 break;
499 }
Daniel Park2884b232021-03-04 18:58:47 +0900500 }
501
Jian Li517597a2021-03-22 11:04:52 +0900502 private void setDefaultGatewayRuleToWorkerNodeTunBridge(KubevirtRouter router,
503 KubevirtNetwork network,
504 DeviceId gwDeviceId,
505 KubevirtNode workerNode,
506 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900507 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900508
Daniel Parkf3136042021-03-10 07:49:11 +0900509 if (routerMacAddress == null) {
510 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
511 "there's no br-int port for device {}", gwDeviceId);
512 return;
513 }
514
515 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
516
517 if (gwNode == null) {
518 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
519 "there's no gateway node for device {}", gwDeviceId);
520 return;
521 }
522
523
524 PortNumber patchPortNumber = tunnelToTenantPort(workerNode, network);
525 if (patchPortNumber == null) {
526 return;
527 }
528
529 PortNumber tunnelPortNumber = tunnelPort(workerNode, network);
530 if (tunnelPortNumber == null) {
531 return;
532 }
533
534 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
535 .matchInPort(patchPortNumber)
536 .matchEthType(Ethernet.TYPE_IPV4)
537 .matchEthDst((routerMacAddress));
538
539 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
540 .setTunnelId(Long.parseLong(network.segmentId()))
541 .extension(buildExtension(
542 deviceService,
543 workerNode.tunBridge(),
544 gwNode.dataIp().getIp4Address()),
545 workerNode.tunBridge())
546 .setOutput(tunnelPortNumber);
547
548 flowService.setRule(
549 appId,
550 workerNode.tunBridge(),
551 sBuilder.build(),
552 tBuilder.build(),
553 PRIORITY_FORWARDING_RULE,
554 TUNNEL_DEFAULT_TABLE,
555 install);
556 }
557
Jian Li8f944d42021-03-23 00:43:29 +0900558 private void setTenantIngressTransitionRule(KubevirtNetwork network,
559 DeviceId deviceId, boolean install) {
560 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
561 sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
562 .matchInPort(network.tenantToTunnelPort(deviceId));
563
564 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
565 tBuilder.transition(TENANT_ACL_INGRESS_TABLE);
566
567 flowService.setRule(appId,
568 deviceId,
569 sBuilder.build(),
570 tBuilder.build(),
571 PRIORITY_IP_INGRESS_RULE,
572 TENANT_ICMP_TABLE,
573 install
574 );
575 }
576
Jian Lif89d9602021-04-27 19:05:49 +0900577 private void setTenantEgressTransitionRule(DeviceId deviceId, boolean install) {
Jian Li8f944d42021-03-23 00:43:29 +0900578 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
579 sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
580
581 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
582 tBuilder.transition(TENANT_ACL_EGRESS_TABLE);
583
584 flowService.setRule(appId,
585 deviceId,
586 sBuilder.build(),
587 tBuilder.build(),
588 PRIORITY_IP_EGRESS_RULE,
589 TENANT_ICMP_TABLE,
590 install
591 );
592 }
593
Daniel Parkf3136042021-03-10 07:49:11 +0900594 private void setDefaultEgressRuleToGatewayNode(KubevirtRouter router,
595 KubevirtNetwork network,
596 DeviceId gwDeviceId,
597 boolean install) {
598 MacAddress routerMacAddress = getRouterMacAddress(router);
599
600 if (routerMacAddress == null) {
601 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
602 "there's no br-int port for device {}", gwDeviceId);
603 return;
604 }
605
606 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
607
608 if (gwNode == null) {
609 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
610 "there's no gateway node for device {}", gwDeviceId);
611 return;
612 }
613
614 PortNumber tunToIntPortNum = portNumber(gwNode.tunBridge(), TUNNEL_TO_INTEGRATION);
615
616 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
617 .matchTunnelId(Long.parseLong(network.segmentId()));
618
619 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
620 .setOutput(tunToIntPortNum);
621
622 flowService.setRule(
623 appId,
624 gwNode.tunBridge(),
625 sBuilder.build(),
626 tBuilder.build(),
627 PRIORITY_TUNNEL_RULE,
628 TUNNEL_DEFAULT_TABLE,
629 install);
630 }
631
632
633 private void setGatewayIcmpRuleForTenantInternalNetwork(KubevirtRouter router,
634 KubevirtNetwork network,
635 int tableNum,
636 DeviceId gwDeviceId,
637 DeviceId tenantDeviceId,
638 boolean install) {
639 MacAddress routerMacAddress = getRouterMacAddress(router);
640
641 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900642 log.warn("Setting gateway ICMP rule for internal network because " +
643 "there's no br-int port for device {}", gwDeviceId);
644 return;
645 }
646
647 Device device = deviceService.getDevice(tenantDeviceId);
648
649 if (device == null) {
650 log.warn("Setting gateway icmp rule for internal network because " +
651 "there's no tenant device for {} to install gateway arp rule",
652 tenantDeviceId);
653 return;
654 }
655
656
657 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
658 .matchEthType(Ethernet.TYPE_IPV4)
659 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
660 .matchIcmpType(TYPE_ECHO_REQUEST)
661 .matchIcmpCode(CODE_ECHO_REQEUST)
662 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
663
664 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
665 .extension(buildMoveEthSrcToDstExtension(device), device.id())
666 .extension(buildMoveIpSrcToDstExtension(device), device.id())
667 .extension(buildLoadExtension(device,
668 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
669 .extension(buildLoadExtension(device,
670 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
671 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900672 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900673 .setOutput(PortNumber.IN_PORT);
674
675 flowService.setRule(
676 appId,
677 tenantDeviceId,
678 sBuilder.build(),
679 tBuilder.build(),
680 PRIORITY_ICMP_RULE,
681 tableNum,
682 install);
683 }
684
Jian Li8f944d42021-03-23 00:43:29 +0900685 private void setArpRuleForTenantNetwork(DeviceId tenantDeviceId,
686 boolean install) {
687 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
688 .matchEthType(EthType.EtherType.ARP.ethType().toShort());
689
690 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
691 .transition(TENANT_FORWARDING_TABLE);
692
693 flowService.setRule(
694 appId,
695 tenantDeviceId,
696 sBuilder.build(),
697 tBuilder.build(),
698 PRIORITY_ARP_DEFAULT_RULE,
699 TENANT_ARP_TABLE,
700 install
701 );
702 }
703
Daniel Parkf3136042021-03-10 07:49:11 +0900704 private void setGatewayArpRuleForTenantInternalNetwork(KubevirtRouter router,
705 KubevirtNetwork network,
706 int tableNum,
707 DeviceId gwDeviceId,
708 DeviceId tenantDeviceId,
709 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900710
Daniel Parkf3136042021-03-10 07:49:11 +0900711 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900712
Daniel Parkf3136042021-03-10 07:49:11 +0900713 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900714 log.warn("Setting gateway arp rule for internal network because " +
715 "there's no br-int port for device {}", gwDeviceId);
716 return;
717 }
718
719 Device device = deviceService.getDevice(tenantDeviceId);
720
721 if (device == null) {
722 log.warn("Setting gateway arp rule for internal network because " +
723 "there's no tenant device for {} to install gateway arp rule",
724 tenantDeviceId);
725 return;
726 }
727
728
729 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
730 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
731 .matchArpOp(ARP.OP_REQUEST)
732 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
733
734 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
735 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
736 .extension(buildMoveArpShaToThaExtension(device), device.id())
737 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
738 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900739 .setArpSha(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900740 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900741 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900742 .setOutput(PortNumber.IN_PORT);
743
744 flowService.setRule(
745 appId,
746 device.id(),
747 sBuilder.build(),
748 tBuilder.build(),
749 PRIORITY_ARP_GATEWAY_RULE,
750 tableNum,
751 install
752 );
753 }
754
Daniel Parkf3136042021-03-10 07:49:11 +0900755 private void setGatewayProviderInterNetworkRoutingWithinSameRouter(
Daniel Parkbabde9c2021-03-09 13:37:42 +0900756 KubevirtNetwork network, KubevirtRouter router, KubevirtNode gatewayNode, boolean install) {
Daniel Park2884b232021-03-04 18:58:47 +0900757 router.internal().forEach(srcNetwork -> {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900758 if (srcNetwork.equals(network.networkId())
759 || kubevirtNetworkService.network(srcNetwork) == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900760 return;
761 }
762
Daniel Parkbabde9c2021-03-09 13:37:42 +0900763 kubevirtPortService.ports(network.networkId()).forEach(port -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900764 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900765 port, gatewayNode, install);
766 });
Daniel Park2884b232021-03-04 18:58:47 +0900767 });
768 }
769
Daniel Parkf3136042021-03-10 07:49:11 +0900770 private void setGatewayInterNetworkRoutingFromNetworkToPort(KubevirtRouter router,
771 KubevirtNetwork srcNetwork,
772 KubevirtPort dstPort,
773 KubevirtNode gatewayNode,
774 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900775 Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
776
777 if (gwDevice == null) {
778 log.warn("Failed to set internal network routing rule because " +
779 "there's no device Id for device {}", gatewayNode.intgBridge());
780 return;
781 }
782
Daniel Parkf3136042021-03-10 07:49:11 +0900783 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900784
Daniel Parkf3136042021-03-10 07:49:11 +0900785 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900786 log.warn("Failed to set internal network routing rule because " +
787 "there's no br-int port for device {}", gatewayNode.intgBridge());
788 return;
789 }
790
Daniel Park4cb120b2021-03-24 12:30:50 +0900791 TrafficSelector.Builder sBuilder;
792 TrafficTreatment treatment;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900793
Daniel Park4cb120b2021-03-24 12:30:50 +0900794 if (srcNetwork.type() == FLAT || srcNetwork.type() == VLAN) {
795 sBuilder = DefaultTrafficSelector.builder()
796 .matchEthType(Ethernet.TYPE_IPV4)
797 .matchEthDst(routerMacAddress)
798 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
799 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
Daniel Parkbabde9c2021-03-09 13:37:42 +0900800
Daniel Park4cb120b2021-03-24 12:30:50 +0900801 treatment = DefaultTrafficTreatment.builder()
802 .setEthSrc(routerMacAddress)
803 .setEthDst(dstPort.macAddress())
804 .transition(FORWARDING_TABLE)
805 .build();
806
807 flowService.setRule(
808 appId,
809 gwDevice.id(),
810 sBuilder.build(),
811 treatment,
812 PRIORITY_INTERNAL_ROUTING_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900813 GW_ENTRY_TABLE,
Daniel Park4cb120b2021-03-24 12:30:50 +0900814 install);
815 } else {
816 KubevirtNetwork dstNetwork = kubevirtNetworkService.network(dstPort.networkId());
817 if (dstNetwork == null) {
818 return;
819 }
820
821 KubevirtNode dstPortWorkerNode = kubevirtNodeService.node(dstPort.deviceId());
822 if (dstPortWorkerNode == null) {
823 return;
824 }
825
826 sBuilder = DefaultTrafficSelector.builder()
827 .matchEthType(Ethernet.TYPE_IPV4)
828 .matchEthDst(routerMacAddress)
829 .matchTunnelId(Long.parseLong(srcNetwork.segmentId()))
830 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
831 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
832
833 treatment = DefaultTrafficTreatment.builder()
834 .setTunnelId(Long.parseLong(dstNetwork.segmentId()))
835 .setEthSrc(routerMacAddress)
836 .setEthDst(dstPort.macAddress())
837 .extension(buildExtension(
838 deviceService,
839 gatewayNode.tunBridge(),
840 dstPortWorkerNode.dataIp().getIp4Address()),
841 gatewayNode.tunBridge())
842 .setOutput(PortNumber.IN_PORT)
843 .build();
844
845 flowService.setRule(
846 appId,
847 gatewayNode.tunBridge(),
848 sBuilder.build(),
849 treatment,
850 PRIORITY_INTERNAL_ROUTING_RULE,
851 TUNNEL_DEFAULT_TABLE,
852 install);
853 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900854 }
855
Daniel Parkf3136042021-03-10 07:49:11 +0900856 private void setGatewayArpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
857 int tableNum, DeviceId gwDeviceId, boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900858
859
860 Device device = deviceService.getDevice(gwDeviceId);
Daniel Parkf3136042021-03-10 07:49:11 +0900861 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900862
Daniel Parkf3136042021-03-10 07:49:11 +0900863 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900864 log.warn("Setting gateway arp rule for internal network because " +
865 "there's no br-int port for device {}", gwDeviceId);
Daniel Park2884b232021-03-04 18:58:47 +0900866 return;
867 }
868
Jian Li858ccd72021-02-04 17:25:01 +0900869 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
870 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
871 .matchArpOp(ARP.OP_REQUEST)
872 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
873
874 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
875 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
876 .extension(buildMoveArpShaToThaExtension(device), device.id())
877 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
878 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900879 .setArpSha(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900880 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900881 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900882 .setOutput(PortNumber.IN_PORT);
883
884 flowService.setRule(
885 appId,
886 device.id(),
887 sBuilder.build(),
888 tBuilder.build(),
889 PRIORITY_ARP_GATEWAY_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900890 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900891 install
892 );
893 }
894
Daniel Park2884b232021-03-04 18:58:47 +0900895 /**
896 * Sends ICMP echo reply for the ICMP echo request from the kubevirt VM.
897 *
Daniel Parkf3136042021-03-10 07:49:11 +0900898 * @param router kubevirt router
Daniel Park2884b232021-03-04 18:58:47 +0900899 * @param network kubevirt network
900 * @param tableNum flow table number
901 * @param deviceId device id of the selected gateway for the network
902 * @param install install if true, remove otherwise
903 */
Daniel Parkf3136042021-03-10 07:49:11 +0900904 private void setGatewayIcmpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
905 int tableNum, DeviceId deviceId, boolean install) {
906 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900907
Daniel Parkf3136042021-03-10 07:49:11 +0900908 if (routerMacAddress == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900909 log.error("Setting gateway ICMP rule for internal network because " +
910 "there's no br-int port for device {}", deviceId);
911 return;
912 }
913
Jian Li858ccd72021-02-04 17:25:01 +0900914 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
915 .matchEthType(Ethernet.TYPE_IPV4)
916 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
917 .matchIcmpType(TYPE_ECHO_REQUEST)
918 .matchIcmpCode(CODE_ECHO_REQEUST)
919 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
920
921 Device device = deviceService.getDevice(deviceId);
922 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
923 .extension(buildMoveEthSrcToDstExtension(device), device.id())
924 .extension(buildMoveIpSrcToDstExtension(device), device.id())
925 .extension(buildLoadExtension(device,
926 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
927 .extension(buildLoadExtension(device,
928 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
929 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900930 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900931 .setOutput(PortNumber.IN_PORT);
932
933 flowService.setRule(
934 appId,
935 deviceId,
936 sBuilder.build(),
937 tBuilder.build(),
938 PRIORITY_ICMP_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900939 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900940 install);
941 }
942
Jian Li0c656f02021-06-07 13:32:39 +0900943 private boolean hasPort(DeviceId deviceId, String portName) {
944 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
945 Port port = deviceService.getPorts(deviceId).stream()
946 .filter(p -> p.isEnabled() &&
947 Objects.equals(p.annotations().value(PORT_NAME), portName))
948 .findAny().orElse(null);
949 return port != null;
950 }
951
Daniel Park2884b232021-03-04 18:58:47 +0900952 private class InternalRouterEventListener implements KubevirtRouterListener {
953 private boolean isRelevantHelper() {
954 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Daniel Parka8968802021-02-25 09:14:22 +0900955 }
956
Daniel Park2884b232021-03-04 18:58:47 +0900957 @Override
958 public void event(KubevirtRouterEvent event) {
959 switch (event.type()) {
960 case KUBEVIRT_ROUTER_CREATED:
961 eventExecutor.execute(() -> processRouterCreation(event.subject()));
962 break;
963 case KUBEVIRT_ROUTER_REMOVED:
964 eventExecutor.execute(() -> processRouterDeletion(event.subject()));
965 break;
966 case KUBEVIRT_ROUTER_UPDATED:
967 eventExecutor.execute(() -> processRouterUpdate(event.subject()));
968 break;
969 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_ATTACHED:
970 eventExecutor.execute(() -> processRouterInternalNetworksAttached(event.subject(),
971 event.internal()));
972 break;
973 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_DETACHED:
974 eventExecutor.execute(() -> processRouterInternalNetworksDetached(event.subject(),
975 event.internal()));
976 break;
977 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
978 eventExecutor.execute(() -> processRouterGatewayNodeAttached(event.subject(),
979 event.gateway()));
980 break;
981 case KUBEVIRT_GATEWAY_NODE_DETACHED:
982 eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(),
983 event.gateway()));
984 break;
985 case KUBEVIRT_GATEWAY_NODE_CHANGED:
986 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
987 event.gateway()));
988 break;
Daniel Parka8968802021-02-25 09:14:22 +0900989
Daniel Park2884b232021-03-04 18:58:47 +0900990 default:
991 //do nothing
992 break;
993 }
994 }
995
996 private void processRouterCreation(KubevirtRouter router) {
997 // When a router is created, we performs the election process to associate the router
998 // to the specific gateway. After the election, KubevirtNetwork handler installs bunch of rules
999 // to elected gateway node so that VMs associated to the router can ping to their gateway IP.
1000 // SNAT and floating ip rule setup is out of this handler's scope and would be done with the other handlers
1001 if (!isRelevantHelper()) {
1002 return;
1003 }
1004 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1005 if (electedGw == null) {
1006 return;
1007 }
1008
1009 router.internal().forEach(networkName -> {
1010 KubevirtNetwork network = networkService.network(networkName);
1011
1012 if (network != null) {
1013 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1014 }
1015 });
1016 kubevirtRouterService.updateRouter(router.updatedElectedGateway(electedGw.hostname()));
1017 }
1018
1019 private void processRouterDeletion(KubevirtRouter router) {
1020 if (!isRelevantHelper()) {
1021 return;
1022 }
1023 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1024 if (electedGw == null) {
1025 return;
1026 }
1027
1028 router.internal().forEach(networkName -> {
1029 KubevirtNetwork network = networkService.network(networkName);
1030
1031 if (network != null) {
1032 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
1033 }
1034 });
1035 }
1036
1037 private void processRouterUpdate(KubevirtRouter router) {
1038 if (!isRelevantHelper()) {
1039 return;
1040 }
1041 if (router.electedGateway() == null) {
1042 return;
1043 }
1044
1045 KubevirtNode electedGw = nodeService.node(router.electedGateway());
1046
1047 router.internal().forEach(networkName -> {
1048 KubevirtNetwork network = networkService.network(networkName);
1049
1050 if (network != null) {
1051 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1052 }
1053 });
1054 }
1055
1056 private void processRouterInternalNetworksAttached(KubevirtRouter router,
1057 Set<String> attachedInternalNetworks) {
1058 if (!isRelevantHelper()) {
1059 return;
1060 }
1061 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1062 if (electedGw == null) {
1063 return;
1064 }
1065
1066 attachedInternalNetworks.forEach(networkName -> {
1067 KubevirtNetwork network = networkService.network(networkName);
1068
1069 if (network != null) {
1070 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1071 }
1072 });
1073 }
1074
1075 private void processRouterInternalNetworksDetached(KubevirtRouter router,
1076 Set<String> detachedInternalNetworks) {
1077 if (!isRelevantHelper()) {
1078 return;
1079 }
1080 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1081 if (electedGw == null) {
1082 return;
1083 }
1084
1085 detachedInternalNetworks.forEach(networkName -> {
1086 KubevirtNetwork network = networkService.network(networkName);
1087
1088 if (network != null) {
1089 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
1090 }
Daniel Park2884b232021-03-04 18:58:47 +09001091
Daniel Parkbabde9c2021-03-09 13:37:42 +09001092 removeDetachedInternalNetworkRules(network, router, electedGw);
1093 });
1094 }
1095
Jian Li8f944d42021-03-23 00:43:29 +09001096 private void removeDetachedInternalNetworkRules(KubevirtNetwork removedNetwork,
1097 KubevirtRouter router,
Daniel Parkbabde9c2021-03-09 13:37:42 +09001098 KubevirtNode electedGw) {
Daniel Parkf3136042021-03-10 07:49:11 +09001099 router.internal().stream().filter(networkId -> kubevirtNetworkService.network(networkId) != null)
1100 .forEach(networkId -> {
1101 kubevirtPortService.ports(networkId).forEach(kubevirtPort -> {
1102 setGatewayInterNetworkRoutingFromNetworkToPort(
1103 router, removedNetwork, kubevirtPort, electedGw, false);
1104 });
Daniel Parkbabde9c2021-03-09 13:37:42 +09001105 });
Daniel Park2884b232021-03-04 18:58:47 +09001106 }
1107
1108 private void processRouterGatewayNodeAttached(KubevirtRouter router,
1109 String associatedGateway) {
1110 if (!isRelevantHelper()) {
1111 return;
1112 }
1113
1114 KubevirtNode gatewayNode = nodeService.node(associatedGateway);
1115 if (gatewayNode == null) {
1116 return;
1117 }
1118
1119 router.internal().forEach(networkName -> {
1120 KubevirtNetwork network = networkService.network(networkName);
1121
1122 if (network != null) {
1123 initGatewayNodeForInternalNetwork(network, router, gatewayNode, true);
1124 }
1125 });
1126 }
1127
1128 private void processRouterGatewayNodeDetached(KubevirtRouter router,
1129 String disAssociatedGateway) {
1130 if (!isRelevantHelper()) {
1131 return;
1132 }
1133
1134 KubevirtNode gatewayNode = nodeService.node(disAssociatedGateway);
1135 if (gatewayNode == null) {
1136 return;
1137 }
1138
1139 router.internal().forEach(networkName -> {
1140 KubevirtNetwork network = networkService.network(networkName);
1141
1142 if (network != null) {
1143 initGatewayNodeForInternalNetwork(network, router, gatewayNode, false);
1144 }
1145 });
1146 }
1147
1148 private void processRouterGatewayNodeChanged(KubevirtRouter router,
1149 String disAssociatedGateway) {
1150 if (!isRelevantHelper()) {
1151 return;
1152 }
1153
1154 KubevirtNode oldGatewayNode = nodeService.node(disAssociatedGateway);
1155 if (oldGatewayNode == null) {
1156 return;
1157 }
1158
1159 router.internal().forEach(networkName -> {
1160 KubevirtNetwork network = networkService.network(networkName);
1161
1162 if (network != null) {
1163 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, false);
1164 }
1165 });
1166
1167 KubevirtNode newGatewayNode = nodeService.node(router.electedGateway());
1168 if (newGatewayNode == null) {
1169 return;
1170 }
1171
1172 router.internal().forEach(networkName -> {
1173 KubevirtNetwork network = networkService.network(networkName);
1174
1175 if (network != null) {
Daniel Parka5ba88d2021-05-28 15:46:46 +09001176 initGatewayNodeForInternalNetwork(network, router, newGatewayNode, true);
Daniel Park2884b232021-03-04 18:58:47 +09001177 }
1178 });
1179 }
Daniel Parka8968802021-02-25 09:14:22 +09001180 }
1181
Jian Li556709c2021-02-03 17:54:28 +09001182 private class InternalNetworkEventListener implements KubevirtNetworkListener {
1183
1184 private boolean isRelevantHelper() {
1185 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1186 }
1187
1188 @Override
1189 public void event(KubevirtNetworkEvent event) {
1190 switch (event.type()) {
1191 case KUBEVIRT_NETWORK_CREATED:
1192 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
1193 break;
1194 case KUBEVIRT_NETWORK_REMOVED:
1195 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
1196 break;
1197 case KUBEVIRT_NETWORK_UPDATED:
1198 default:
1199 // do nothing
1200 break;
1201 }
1202 }
1203
1204 private void processNetworkCreation(KubevirtNetwork network) {
1205 if (!isRelevantHelper()) {
1206 return;
1207 }
1208
1209 switch (network.type()) {
1210 case VXLAN:
1211 case GRE:
1212 case GENEVE:
1213 initIntegrationTunnelBridge(network);
1214 break;
1215 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001216 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001217 break;
Jian Li556709c2021-02-03 17:54:28 +09001218 default:
1219 // do nothing
1220 break;
1221 }
1222 }
1223
1224 private void processNetworkRemoval(KubevirtNetwork network) {
1225 if (!isRelevantHelper()) {
1226 return;
1227 }
1228
1229 switch (network.type()) {
1230 case VXLAN:
1231 case GRE:
1232 case GENEVE:
1233 purgeIntegrationTunnelBridge(network);
1234 break;
1235 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001236 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001237 break;
Jian Li556709c2021-02-03 17:54:28 +09001238 default:
1239 // do nothing
1240 break;
1241 }
1242 }
1243
1244 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
1245 if (network.segmentId() == null) {
1246 return;
1247 }
1248
Jian Li94b6d162021-04-15 17:09:11 +09001249 nodeService.completeNodes(WORKER).forEach(n -> {
Jian Li556709c2021-02-03 17:54:28 +09001250 createBridge(n, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001251 createPatchTenantInterface(n, network);
1252 setDefaultRulesForTenantNetwork(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001253 });
1254 }
1255
1256 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
1257 if (network.segmentId() == null) {
1258 return;
1259 }
1260
Jian Li567b25c2021-05-27 15:17:59 +09001261 nodeService.completeNodes(WORKER).forEach(n -> {
Jian Liea1ead72021-05-28 11:00:07 +09001262 removeAllFlows(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001263 removePatchInterface(n, network);
Jian Liea1ead72021-05-28 11:00:07 +09001264
Jian Li0c656f02021-06-07 13:32:39 +09001265 waitFor(5);
Jian Liea1ead72021-05-28 11:00:07 +09001266
Jian Li556709c2021-02-03 17:54:28 +09001267 removeBridge(n, network);
1268 });
1269 }
1270 }
1271
1272 private class InternalNodeEventListener implements KubevirtNodeListener {
1273
1274 private boolean isRelevantHelper() {
1275 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1276 }
1277
1278 @Override
1279 public void event(KubevirtNodeEvent event) {
1280 switch (event.type()) {
1281 case KUBEVIRT_NODE_COMPLETE:
1282 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
1283 break;
Daniel Parka5ba88d2021-05-28 15:46:46 +09001284 case KUBEVIRT_NODE_INCOMPLETE:
Daniel Park2884b232021-03-04 18:58:47 +09001285 case KUBEVIRT_NODE_REMOVED:
1286 eventExecutor.execute(() -> processNodeDeletion(event.subject()));
1287 break;
Jian Li556709c2021-02-03 17:54:28 +09001288 case KUBEVIRT_NODE_UPDATED:
1289 default:
1290 // do nothing
1291 break;
1292 }
1293 }
1294
1295 private void processNodeCompletion(KubevirtNode node) {
1296 if (!isRelevantHelper()) {
1297 return;
1298 }
1299
Daniel Parka8968802021-02-25 09:14:22 +09001300 if (node.type().equals(WORKER)) {
1301 for (KubevirtNetwork network : networkService.networks()) {
1302 switch (network.type()) {
1303 case VXLAN:
1304 case GRE:
1305 case GENEVE:
1306 if (network.segmentId() == null) {
1307 continue;
1308 }
1309 createBridge(node, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001310 createPatchTenantInterface(node, network);
1311 setDefaultRulesForTenantNetwork(node, network);
Jian Li8f944d42021-03-23 00:43:29 +09001312 setGatewayArpRulesForTenantNetwork(node, network);
1313 setGatewayIcmpRulesForTenantNetwork(node, network);
1314 setGatewayRuleToWorkerNodeWhenNodeCreated(node, network);
Daniel Parka8968802021-02-25 09:14:22 +09001315 break;
1316 case FLAT:
1317 case VLAN:
1318 default:
1319 // do nothing
1320 break;
1321 }
1322 }
1323 } else if (node.type().equals(GATEWAY)) {
Daniel Park2884b232021-03-04 18:58:47 +09001324 updateGatewayNodeForRouter();
Jian Li556709c2021-02-03 17:54:28 +09001325 }
1326 }
Daniel Park2884b232021-03-04 18:58:47 +09001327
1328 private void processNodeDeletion(KubevirtNode node) {
1329 if (!isRelevantHelper()) {
1330 return;
1331 }
Daniel Park2884b232021-03-04 18:58:47 +09001332 if (node.type().equals(GATEWAY)) {
Daniel Parka5ba88d2021-05-28 15:46:46 +09001333 kubevirtRouterService.routers()
1334 .stream()
1335 .filter(router -> router.electedGateway().equals(node.hostname()))
1336 .forEach(router -> {
1337 router.internal().forEach(networkName -> {
1338 KubevirtNetwork network = networkService.network(networkName);
1339
1340 if (network != null) {
1341 initGatewayNodeForInternalNetwork(network, router, node, false);
1342 }
1343 });
1344 });
Daniel Park2884b232021-03-04 18:58:47 +09001345 updateGatewayNodeForRouter();
Daniel Park2884b232021-03-04 18:58:47 +09001346 }
1347 }
1348
1349 private void updateGatewayNodeForRouter() {
1350 kubevirtRouterService.routers().forEach(router -> {
1351 KubevirtNode newGwNode = gatewayNodeForSpecifiedRouter(nodeService, router);
1352
1353 if (newGwNode == null) {
1354 return;
1355 }
1356 kubevirtRouterService.updateRouter(router.updatedElectedGateway(newGwNode.hostname()));
1357 });
1358 }
Jian Li556709c2021-02-03 17:54:28 +09001359 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001360
1361 private class InternalKubevirtPortListener implements KubevirtPortListener {
1362
1363 private boolean isRelevantHelper() {
1364 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1365 }
1366
1367 @Override
1368 public void event(KubevirtPortEvent event) {
1369 switch (event.type()) {
1370 case KUBEVIRT_PORT_CREATED:
1371 eventExecutor.execute(() -> processPortCreation(event.subject()));
1372 break;
1373 case KUBEVIRT_PORT_UPDATED:
1374 eventExecutor.execute(() -> processPortUpdate(event.subject()));
1375 break;
1376 case KUBEVIRT_PORT_REMOVED:
1377 eventExecutor.execute(() -> processPortDeletion(event.subject()));
1378 break;
1379 default:
1380 //do nothing
1381 break;
1382 }
1383 }
1384
1385 private void processPortCreation(KubevirtPort kubevirtPort) {
1386 if (!isRelevantHelper()) {
1387 return;
1388 }
1389
1390 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1391 if (router == null) {
1392 return;
1393 }
1394
1395 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1396
1397 if (gwNode != null) {
1398
1399 router.internal().forEach(srcNetwork -> {
1400 if (srcNetwork.equals(kubevirtPort.networkId())
1401 || kubevirtNetworkService.network(srcNetwork) == null) {
1402 return;
1403 }
Jian Li8f944d42021-03-23 00:43:29 +09001404 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1405 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001406 kubevirtPort, gwNode, true);
1407 });
1408 }
1409 }
1410
1411 private void processPortUpdate(KubevirtPort kubevirtPort) {
1412 if (!isRelevantHelper()) {
1413 return;
1414 }
1415
1416 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1417 if (router == null) {
1418 return;
1419 }
1420
1421 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1422
1423 if (gwNode != null) {
1424
1425 router.internal().forEach(srcNetwork -> {
1426 if (srcNetwork.equals(kubevirtPort.networkId())
1427 || kubevirtNetworkService.network(srcNetwork) == null) {
1428 return;
1429 }
Jian Li8f944d42021-03-23 00:43:29 +09001430 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1431 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001432 kubevirtPort, gwNode, true);
1433 });
1434 }
1435 }
1436
1437 private void processPortDeletion(KubevirtPort kubevirtPort) {
1438 if (!isRelevantHelper()) {
1439 return;
1440 }
1441
1442 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1443 if (router == null) {
1444 return;
1445 }
1446
1447 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1448
1449 if (gwNode != null) {
1450
1451 router.internal().forEach(srcNetwork -> {
1452 if (srcNetwork.equals(kubevirtPort.networkId())
1453 || kubevirtNetworkService.network(srcNetwork) == null) {
1454 return;
1455 }
Jian Li8f944d42021-03-23 00:43:29 +09001456 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1457 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001458 kubevirtPort, gwNode, false);
1459 });
1460 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001461 }
1462 }
Jian Li556709c2021-02-03 17:54:28 +09001463}