blob: 28bf1823085275327a045499b4027fe03ad149de [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;
Jian Li0c656f02021-06-07 13:32:39 +090055import org.onosproject.net.Port;
Jian Li556709c2021-02-03 17:54:28 +090056import org.onosproject.net.PortNumber;
57import org.onosproject.net.behaviour.BridgeConfig;
58import org.onosproject.net.behaviour.BridgeDescription;
59import org.onosproject.net.behaviour.BridgeName;
60import org.onosproject.net.behaviour.ControllerInfo;
61import org.onosproject.net.behaviour.DefaultBridgeDescription;
62import org.onosproject.net.behaviour.DefaultPatchDescription;
63import org.onosproject.net.behaviour.InterfaceConfig;
64import org.onosproject.net.behaviour.PatchDescription;
65import org.onosproject.net.device.DeviceAdminService;
Daniel Parka8968802021-02-25 09:14:22 +090066import org.onosproject.net.driver.DriverService;
Jian Li556709c2021-02-03 17:54:28 +090067import org.onosproject.net.flow.DefaultTrafficSelector;
68import org.onosproject.net.flow.DefaultTrafficTreatment;
69import org.onosproject.net.flow.TrafficSelector;
70import org.onosproject.net.flow.TrafficTreatment;
71import org.osgi.service.component.annotations.Activate;
72import org.osgi.service.component.annotations.Component;
73import org.osgi.service.component.annotations.Deactivate;
74import org.osgi.service.component.annotations.Reference;
75import org.osgi.service.component.annotations.ReferenceCardinality;
76import org.slf4j.Logger;
77
78import java.util.List;
79import java.util.Objects;
Daniel Park2884b232021-03-04 18:58:47 +090080import java.util.Set;
Jian Li556709c2021-02-03 17:54:28 +090081import java.util.concurrent.ExecutorService;
82
Jian Li556709c2021-02-03 17:54:28 +090083import 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 Lif89d9602021-04-27 19:05:49 +090089import static org.onosproject.kubevirtnetworking.api.Constants.GW_ENTRY_TABLE;
Jian Li556709c2021-02-03 17:54:28 +090090import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
Jian Li8f944d42021-03-23 00:43:29 +090091import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_DEFAULT_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090092import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
Jian Li556709c2021-02-03 17:54:28 +090093import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_DHCP_RULE;
Jian Li858ccd72021-02-04 17:25:01 +090094import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_FORWARDING_RULE;
95import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_ICMP_RULE;
Daniel Parkbabde9c2021-03-09 13:37:42 +090096import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
Jian Li8f944d42021-03-23 00:43:29 +090097import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_IP_EGRESS_RULE;
98import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_IP_INGRESS_RULE;
Daniel Parkf3136042021-03-10 07:49:11 +090099import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_TUNNEL_RULE;
Jian Li8f944d42021-03-23 00:43:29 +0900100import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_EGRESS_TABLE;
101import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_INGRESS_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900102import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ARP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +0900103import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_DHCP_TABLE;
104import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900105import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ICMP_TABLE;
Jian Li556709c2021-02-03 17:54:28 +0900106import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_INBOUND_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900107import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
Daniel Parkf3136042021-03-10 07:49:11 +0900108import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
Jian Li858ccd72021-02-04 17:25:01 +0900109import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Daniel Park4cb120b2021-03-24 12:30:50 +0900110import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
111import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
Daniel Park2884b232021-03-04 18:58:47 +0900112import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.gatewayNodeForSpecifiedRouter;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900113import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtNetwork;
114import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
Daniel Parkf3136042021-03-10 07:49:11 +0900115import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
116import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.portNumber;
Jian Li94b6d162021-04-15 17:09:11 +0900117import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.resolveHostname;
Jian Li556709c2021-02-03 17:54:28 +0900118import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
Daniel Parkf3136042021-03-10 07:49:11 +0900119import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
120import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelToTenantPort;
Jian Li0c656f02021-06-07 13:32:39 +0900121import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.waitFor;
Jian Li858ccd72021-02-04 17:25:01 +0900122import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
123import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.NXM_OF_ICMP_TYPE;
Daniel Parkf3136042021-03-10 07:49:11 +0900124import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
Jian Li858ccd72021-02-04 17:25:01 +0900125import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildLoadExtension;
126import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
127import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
128import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
129import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildMoveIpSrcToDstExtension;
Jian Li556709c2021-02-03 17:54:28 +0900130import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_BRIDGE;
Daniel Parkf3136042021-03-10 07:49:11 +0900131import static org.onosproject.kubevirtnode.api.Constants.TUNNEL_TO_INTEGRATION;
Daniel Parka8968802021-02-25 09:14:22 +0900132import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
133import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Jian Li0c656f02021-06-07 13:32:39 +0900134import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Jian Li556709c2021-02-03 17:54:28 +0900135import static org.slf4j.LoggerFactory.getLogger;
136
137/**
138 * Handles kubevirt network events.
139 */
140@Component(immediate = true)
141public class KubevirtNetworkHandler {
142 protected final Logger log = getLogger(getClass());
143 private static final String DEFAULT_OF_PROTO = "tcp";
144 private static final int DEFAULT_OFPORT = 6653;
145 private static final int DPID_BEGIN = 3;
Jian Li858ccd72021-02-04 17:25:01 +0900146 private static final int DEFAULT_TTL = 0xff;
Jian Li556709c2021-02-03 17:54:28 +0900147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY)
149 protected CoreService coreService;
150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY)
152 protected ClusterService clusterService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY)
155 protected LeadershipService leadershipService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY)
158 protected DeviceAdminService deviceService;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
161 protected KubevirtApiConfigService apiConfigService;
162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY)
164 protected KubevirtNodeService nodeService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lifc7e6cf2021-04-08 11:13:24 +0900167 protected KubevirtNetworkAdminService networkService;
Jian Li556709c2021-02-03 17:54:28 +0900168
169 @Reference(cardinality = ReferenceCardinality.MANDATORY)
170 protected KubevirtFlowRuleService flowService;
171
Daniel Parka8968802021-02-25 09:14:22 +0900172 @Reference(cardinality = ReferenceCardinality.MANDATORY)
173 protected DriverService driverService;
174
Daniel Park2884b232021-03-04 18:58:47 +0900175 @Reference(cardinality = ReferenceCardinality.MANDATORY)
176 protected KubevirtRouterAdminService kubevirtRouterService;
177
Daniel Parkbabde9c2021-03-09 13:37:42 +0900178 @Reference(cardinality = ReferenceCardinality.MANDATORY)
179 protected KubevirtPortService kubevirtPortService;
180
181 @Reference(cardinality = ReferenceCardinality.MANDATORY)
182 protected KubevirtNetworkService kubevirtNetworkService;
183
184 @Reference(cardinality = ReferenceCardinality.MANDATORY)
185 protected KubevirtNodeService kubevirtNodeService;
186
Jian Li556709c2021-02-03 17:54:28 +0900187 private final KubevirtNetworkListener networkListener = new InternalNetworkEventListener();
188 private final KubevirtNodeListener nodeListener = new InternalNodeEventListener();
Daniel Parkbabde9c2021-03-09 13:37:42 +0900189 private final KubevirtPortListener portListener = new InternalKubevirtPortListener();
Jian Li556709c2021-02-03 17:54:28 +0900190
Daniel Park2884b232021-03-04 18:58:47 +0900191 private final InternalRouterEventListener kubevirtRouterlistener =
192 new InternalRouterEventListener();
193
Jian Li556709c2021-02-03 17:54:28 +0900194 private final ExecutorService eventExecutor = newSingleThreadExecutor(
195 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
196
197 private ApplicationId appId;
198 private NodeId localNodeId;
199
200 @Activate
201 protected void activate() {
202 appId = coreService.registerApplication(KUBEVIRT_NETWORKING_APP_ID);
203 localNodeId = clusterService.getLocalNode().id();
Jian Li556709c2021-02-03 17:54:28 +0900204 leadershipService.runForLeadership(appId.name());
205
Daniel Parkbabde9c2021-03-09 13:37:42 +0900206 networkService.addListener(networkListener);
207 nodeService.addListener(nodeListener);
208 kubevirtPortService.addListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900209 kubevirtRouterService.addListener(kubevirtRouterlistener);
210
Jian Li556709c2021-02-03 17:54:28 +0900211 log.info("Started");
212 }
213
214 @Deactivate
215 protected void deactivate() {
216 networkService.removeListener(networkListener);
217 nodeService.removeListener(nodeListener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900218 kubevirtPortService.removeListener(portListener);
Daniel Park2884b232021-03-04 18:58:47 +0900219 kubevirtRouterService.removeListener(kubevirtRouterlistener);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900220 leadershipService.withdraw(appId.name());
Jian Li556709c2021-02-03 17:54:28 +0900221 eventExecutor.shutdown();
222
223 log.info("Stopped");
224 }
225
226 private void createBridge(KubevirtNode node, KubevirtNetwork network) {
227
Jian Li8f944d42021-03-23 00:43:29 +0900228 Device tenantBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
Jian Li7db46722021-06-14 21:28:31 +0900229 if (tenantBridge != null && deviceService.isAvailable(tenantBridge.id())) {
Jian Li8f944d42021-03-23 00:43:29 +0900230 log.warn("The tenant bridge {} already exists at node {}",
Jian Li556709c2021-02-03 17:54:28 +0900231 network.tenantBridgeName(), node.hostname());
Daniel Parkf3136042021-03-10 07:49:11 +0900232 setDefaultRulesForTenantNetwork(node, network);
Jian Li556709c2021-02-03 17:54:28 +0900233 return;
234 }
235
236 Device device = deviceService.getDevice(node.ovsdb());
237
Jian Li94b6d162021-04-15 17:09:11 +0900238 IpAddress serverIp;
239 String serviceFqdn = apiConfigService.apiConfig().serviceFqdn();
240 IpAddress serviceIp = null;
241
242 if (serviceFqdn != null) {
243 serviceIp = resolveHostname(serviceFqdn);
244 }
245
246 if (serviceIp != null) {
247 serverIp = serviceIp;
248 } else {
249 serverIp = apiConfigService.apiConfig().ipAddress();
250 }
251
Jian Li556709c2021-02-03 17:54:28 +0900252 ControllerInfo controlInfo =
253 new ControllerInfo(serverIp, DEFAULT_OFPORT, DEFAULT_OF_PROTO);
254 List<ControllerInfo> controllers = Lists.newArrayList(controlInfo);
255
256 String dpid = network.tenantDeviceId(
257 node.hostname()).toString().substring(DPID_BEGIN);
258
Jian Li0c656f02021-06-07 13:32:39 +0900259 // if the bridge is already available, we skip creating a new bridge
260 if (!deviceService.isAvailable(DeviceId.deviceId(dpid))) {
261 BridgeDescription.Builder builder = DefaultBridgeDescription.builder()
262 .name(network.tenantBridgeName())
263 .failMode(BridgeDescription.FailMode.SECURE)
264 .datapathId(dpid)
265 .disableInBand()
266 .controllers(controllers);
Jian Li556709c2021-02-03 17:54:28 +0900267
Jian Li0c656f02021-06-07 13:32:39 +0900268 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
269 bridgeConfig.addBridge(builder.build());
270
Jian Li7db46722021-06-14 21:28:31 +0900271 log.info("Created a new tunnel bridge for network {} at node {}",
272 network.networkId(), node.hostname());
273
Jian Li0c656f02021-06-07 13:32:39 +0900274 waitFor(3);
275 }
Jian Li556709c2021-02-03 17:54:28 +0900276 }
277
278 private void removeBridge(KubevirtNode node, KubevirtNetwork network) {
279 Device device = deviceService.getDevice(node.ovsdb());
280
281 BridgeName bridgeName = BridgeName.bridgeName(network.tenantBridgeName());
282
283 BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
284 bridgeConfig.deleteBridge(bridgeName);
285 deviceService.removeDevice(network.tenantDeviceId(node.hostname()));
286 }
287
Daniel Parkf3136042021-03-10 07:49:11 +0900288 private void createPatchTenantInterface(KubevirtNode node, KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900289 Device device = deviceService.getDevice(node.ovsdb());
290
291 if (device == null || !device.is(InterfaceConfig.class)) {
292 log.error("Failed to create patch interface on {}", node.ovsdb());
293 return;
294 }
295
296 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
297
Jian Li858ccd72021-02-04 17:25:01 +0900298 String tenantToTunIntf =
299 TENANT_TO_TUNNEL_PREFIX + segmentIdHex(network.segmentId());
300 String tunToTenantIntf =
301 TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900302
Jian Lif3a3c5a2021-06-30 10:21:31 +0900303 if (!hasPort(network.tenantDeviceId(node.hostname()), tenantToTunIntf)) {
304 // patch ports for tenant bridge -> tunnel bridge
Jian Li0c656f02021-06-07 13:32:39 +0900305 PatchDescription brTenantTunPatchDesc =
306 DefaultPatchDescription.builder()
307 .deviceId(network.tenantBridgeName())
308 .ifaceName(tenantToTunIntf)
309 .peer(tunToTenantIntf)
310 .build();
Jian Li556709c2021-02-03 17:54:28 +0900311
Jian Li0c656f02021-06-07 13:32:39 +0900312 ifaceConfig.addPatchMode(tenantToTunIntf, brTenantTunPatchDesc);
Jian Li556709c2021-02-03 17:54:28 +0900313
Jian Li0c656f02021-06-07 13:32:39 +0900314 waitFor(1);
315 }
316
Jian Lif3a3c5a2021-06-30 10:21:31 +0900317 if (!hasPort(node.tunBridge(), tunToTenantIntf)) {
Jian Li0c656f02021-06-07 13:32:39 +0900318 // tunnel bridge -> tenant bridge
319 PatchDescription brTunTenantPatchDesc =
320 DefaultPatchDescription.builder()
321 .deviceId(TUNNEL_BRIDGE)
322 .ifaceName(tunToTenantIntf)
323 .peer(tenantToTunIntf)
324 .build();
325 ifaceConfig.addPatchMode(tunToTenantIntf, brTunTenantPatchDesc);
326
327 waitFor(1);
328 }
Jian Li556709c2021-02-03 17:54:28 +0900329 }
330
Jian Liea1ead72021-05-28 11:00:07 +0900331 private void removeAllFlows(KubevirtNode node, KubevirtNetwork network) {
332 DeviceId deviceId = network.tenantDeviceId(node.hostname());
333 flowService.purgeRules(deviceId);
334 }
335
Jian Li556709c2021-02-03 17:54:28 +0900336 private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
337 Device device = deviceService.getDevice(node.ovsdb());
338
339 if (device == null || !device.is(InterfaceConfig.class)) {
340 log.error("Failed to create patch interface on {}", node.ovsdb());
341 return;
342 }
343
344 InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
345
Jian Li858ccd72021-02-04 17:25:01 +0900346 String tunToIntIntf = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li556709c2021-02-03 17:54:28 +0900347
348 ifaceConfig.removePatchMode(tunToIntIntf);
349 }
350
Jian Li8f944d42021-03-23 00:43:29 +0900351 private void setGatewayArpRulesForTenantNetwork(KubevirtNode node,
352 KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900353
354 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
355 if (router == null) {
356 return;
357 }
358
359 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
360 if (electedGw == null) {
361 return;
362 }
363
Jian Li8f944d42021-03-23 00:43:29 +0900364 setGatewayArpRuleForTenantInternalNetwork(router, network, TENANT_ARP_TABLE,
365 electedGw.intgBridge(), network.tenantDeviceId(node.hostname()), true);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900366 }
367
Jian Li8f944d42021-03-23 00:43:29 +0900368 private void setGatewayIcmpRulesForTenantNetwork(KubevirtNode node,
369 KubevirtNetwork network) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900370 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
371 if (router == null) {
372 return;
373 }
374
375 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
376 if (electedGw == null) {
377 return;
378 }
379
Jian Li8f944d42021-03-23 00:43:29 +0900380 setGatewayIcmpRuleForTenantInternalNetwork(router, network, TENANT_ICMP_TABLE,
381 electedGw.intgBridge(), network.tenantDeviceId(node.hostname()), true);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900382 }
383
Jian Li8f944d42021-03-23 00:43:29 +0900384 private void setGatewayRuleToWorkerNodeWhenNodeCreated(KubevirtNode node,
385 KubevirtNetwork network) {
Daniel Parkf3136042021-03-10 07:49:11 +0900386 KubevirtRouter router = getRouterForKubevirtNetwork(kubevirtRouterService, network);
387 if (router == null) {
388 return;
389 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900390
Daniel Parkf3136042021-03-10 07:49:11 +0900391 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
392 if (electedGw == null) {
393 return;
394 }
395
Jian Li8f944d42021-03-23 00:43:29 +0900396 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
397 electedGw.intgBridge(), node, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900398 }
399
Jian Li8f944d42021-03-23 00:43:29 +0900400 private void setDefaultRulesForTenantNetwork(KubevirtNode node,
401 KubevirtNetwork network) {
Jian Li556709c2021-02-03 17:54:28 +0900402 DeviceId deviceId = network.tenantDeviceId(node.hostname());
403
404 while (!deviceService.isAvailable(deviceId)) {
405 log.warn("Device {} is not ready for installing rules", deviceId);
Jian Li0c656f02021-06-07 13:32:39 +0900406 waitFor(3);
Jian Li556709c2021-02-03 17:54:28 +0900407 }
408
409 flowService.connectTables(deviceId, TENANT_INBOUND_TABLE, TENANT_DHCP_TABLE);
Jian Li858ccd72021-02-04 17:25:01 +0900410 flowService.connectTables(deviceId, TENANT_DHCP_TABLE, TENANT_ARP_TABLE);
411 flowService.connectTables(deviceId, TENANT_ARP_TABLE, TENANT_ICMP_TABLE);
412 flowService.connectTables(deviceId, TENANT_ICMP_TABLE, TENANT_FORWARDING_TABLE);
Jian Li556709c2021-02-03 17:54:28 +0900413
Jian Li8f944d42021-03-23 00:43:29 +0900414 setArpRuleForTenantNetwork(deviceId, true);
Daniel Parkf3136042021-03-10 07:49:11 +0900415 setDhcpRuleForTenantNetwork(deviceId, true);
Jian Li556709c2021-02-03 17:54:28 +0900416 setForwardingRule(deviceId, true);
417
Jian Li8f944d42021-03-23 00:43:29 +0900418 // security group related rules
419 setTenantIngressTransitionRule(network, network.tenantDeviceId(node.hostname()), true);
Jian Lif89d9602021-04-27 19:05:49 +0900420 setTenantEgressTransitionRule(network.tenantDeviceId(node.hostname()), true);
Jian Li8f944d42021-03-23 00:43:29 +0900421
Jian Li556709c2021-02-03 17:54:28 +0900422 log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
423 }
424
Daniel Parkf3136042021-03-10 07:49:11 +0900425 private void setDhcpRuleForTenantNetwork(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900426 TrafficSelector selector = DefaultTrafficSelector.builder()
427 .matchEthType(Ethernet.TYPE_IPV4)
428 .matchIPProtocol(IPv4.PROTOCOL_UDP)
429 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
430 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
431 .build();
432
433 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
434 .punt()
435 .build();
436
437 flowService.setRule(
438 appId,
439 deviceId,
440 selector,
441 treatment,
442 PRIORITY_DHCP_RULE,
443 TENANT_DHCP_TABLE,
444 install);
445 }
446
Jian Li858ccd72021-02-04 17:25:01 +0900447 private void setForwardingRule(DeviceId deviceId, boolean install) {
Jian Li556709c2021-02-03 17:54:28 +0900448 TrafficSelector selector = DefaultTrafficSelector.builder().build();
449 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
450 .setOutput(PortNumber.NORMAL)
451 .build();
452
453 flowService.setRule(
454 appId,
455 deviceId,
456 selector,
457 treatment,
Jian Li858ccd72021-02-04 17:25:01 +0900458 PRIORITY_FORWARDING_RULE,
Jian Li556709c2021-02-03 17:54:28 +0900459 TENANT_FORWARDING_TABLE,
460 install);
461 }
462
Daniel Park2884b232021-03-04 18:58:47 +0900463 private void initGatewayNodeForInternalNetwork(KubevirtNetwork network,
464 KubevirtRouter router,
465 KubevirtNode electedGateway,
466 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900467 switch (network.type()) {
468 case VXLAN:
469 case GRE:
470 case GENEVE:
Jian Li8f944d42021-03-23 00:43:29 +0900471 setDefaultEgressRuleToGatewayNode(router, network,
472 electedGateway.intgBridge(), install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900473 kubevirtNodeService.completeNodes(WORKER).forEach(node -> {
Jian Li8f944d42021-03-23 00:43:29 +0900474 setGatewayArpRuleForTenantInternalNetwork(router, network,
475 TENANT_ARP_TABLE, electedGateway.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900476 network.tenantDeviceId(node.hostname()), install);
Jian Li8f944d42021-03-23 00:43:29 +0900477 setGatewayIcmpRuleForTenantInternalNetwork(router, network,
478 TENANT_ICMP_TABLE, electedGateway.intgBridge(),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900479 network.tenantDeviceId(node.hostname()), install);
Jian Li517597a2021-03-22 11:04:52 +0900480 setDefaultGatewayRuleToWorkerNodeTunBridge(router, network,
Daniel Parkf3136042021-03-10 07:49:11 +0900481 electedGateway.intgBridge(), node, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900482 });
Daniel Park4cb120b2021-03-24 12:30:50 +0900483 setGatewayProviderInterNetworkRoutingWithinSameRouter(network, router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900484 break;
485 case FLAT:
486 case VLAN:
Jian Li8f944d42021-03-23 00:43:29 +0900487 setGatewayArpRuleForProviderInternalNetwork(router, network,
Jian Lif89d9602021-04-27 19:05:49 +0900488 GW_ENTRY_TABLE, electedGateway.intgBridge(), install);
Jian Li8f944d42021-03-23 00:43:29 +0900489 setGatewayIcmpRuleForProviderInternalNetwork(router, network,
Jian Lif89d9602021-04-27 19:05:49 +0900490 GW_ENTRY_TABLE, electedGateway.intgBridge(), install);
Jian Li8f944d42021-03-23 00:43:29 +0900491 setGatewayProviderInterNetworkRoutingWithinSameRouter(network,
492 router, electedGateway, install);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900493 break;
494 default:
495 // do nothing
496 break;
497 }
Daniel Park2884b232021-03-04 18:58:47 +0900498 }
499
Jian Li517597a2021-03-22 11:04:52 +0900500 private void setDefaultGatewayRuleToWorkerNodeTunBridge(KubevirtRouter router,
501 KubevirtNetwork network,
502 DeviceId gwDeviceId,
503 KubevirtNode workerNode,
504 boolean install) {
Daniel Parkf3136042021-03-10 07:49:11 +0900505 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900506
Daniel Parkf3136042021-03-10 07:49:11 +0900507 if (routerMacAddress == null) {
508 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
509 "there's no br-int port for device {}", gwDeviceId);
510 return;
511 }
512
513 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
514
515 if (gwNode == null) {
516 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
517 "there's no gateway node for device {}", gwDeviceId);
518 return;
519 }
520
521
522 PortNumber patchPortNumber = tunnelToTenantPort(workerNode, network);
523 if (patchPortNumber == null) {
524 return;
525 }
526
527 PortNumber tunnelPortNumber = tunnelPort(workerNode, network);
528 if (tunnelPortNumber == null) {
529 return;
530 }
531
532 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
533 .matchInPort(patchPortNumber)
534 .matchEthType(Ethernet.TYPE_IPV4)
535 .matchEthDst((routerMacAddress));
536
537 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
538 .setTunnelId(Long.parseLong(network.segmentId()))
539 .extension(buildExtension(
540 deviceService,
541 workerNode.tunBridge(),
542 gwNode.dataIp().getIp4Address()),
543 workerNode.tunBridge())
544 .setOutput(tunnelPortNumber);
545
546 flowService.setRule(
547 appId,
548 workerNode.tunBridge(),
549 sBuilder.build(),
550 tBuilder.build(),
551 PRIORITY_FORWARDING_RULE,
552 TUNNEL_DEFAULT_TABLE,
553 install);
554 }
555
Jian Li8f944d42021-03-23 00:43:29 +0900556 private void setTenantIngressTransitionRule(KubevirtNetwork network,
557 DeviceId deviceId, boolean install) {
558 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
559 sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
560 .matchInPort(network.tenantToTunnelPort(deviceId));
561
562 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
563 tBuilder.transition(TENANT_ACL_INGRESS_TABLE);
564
565 flowService.setRule(appId,
566 deviceId,
567 sBuilder.build(),
568 tBuilder.build(),
569 PRIORITY_IP_INGRESS_RULE,
570 TENANT_ICMP_TABLE,
571 install
572 );
573 }
574
Jian Lif89d9602021-04-27 19:05:49 +0900575 private void setTenantEgressTransitionRule(DeviceId deviceId, boolean install) {
Jian Li8f944d42021-03-23 00:43:29 +0900576 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
577 sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
578
579 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
580 tBuilder.transition(TENANT_ACL_EGRESS_TABLE);
581
582 flowService.setRule(appId,
583 deviceId,
584 sBuilder.build(),
585 tBuilder.build(),
586 PRIORITY_IP_EGRESS_RULE,
587 TENANT_ICMP_TABLE,
588 install
589 );
590 }
591
Daniel Parkf3136042021-03-10 07:49:11 +0900592 private void setDefaultEgressRuleToGatewayNode(KubevirtRouter router,
593 KubevirtNetwork network,
594 DeviceId gwDeviceId,
595 boolean install) {
596 MacAddress routerMacAddress = getRouterMacAddress(router);
597
598 if (routerMacAddress == null) {
599 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
600 "there's no br-int port for device {}", gwDeviceId);
601 return;
602 }
603
604 KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
605
606 if (gwNode == null) {
607 log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
608 "there's no gateway node for device {}", gwDeviceId);
609 return;
610 }
611
612 PortNumber tunToIntPortNum = portNumber(gwNode.tunBridge(), TUNNEL_TO_INTEGRATION);
613
614 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
615 .matchTunnelId(Long.parseLong(network.segmentId()));
616
617 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
618 .setOutput(tunToIntPortNum);
619
620 flowService.setRule(
621 appId,
622 gwNode.tunBridge(),
623 sBuilder.build(),
624 tBuilder.build(),
625 PRIORITY_TUNNEL_RULE,
626 TUNNEL_DEFAULT_TABLE,
627 install);
628 }
629
630
631 private void setGatewayIcmpRuleForTenantInternalNetwork(KubevirtRouter router,
632 KubevirtNetwork network,
633 int tableNum,
634 DeviceId gwDeviceId,
635 DeviceId tenantDeviceId,
636 boolean install) {
637 MacAddress routerMacAddress = getRouterMacAddress(router);
638
639 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900640 log.warn("Setting gateway ICMP rule for internal network because " +
641 "there's no br-int port for device {}", gwDeviceId);
642 return;
643 }
644
645 Device device = deviceService.getDevice(tenantDeviceId);
646
647 if (device == null) {
648 log.warn("Setting gateway icmp rule for internal network because " +
649 "there's no tenant device for {} to install gateway arp rule",
650 tenantDeviceId);
651 return;
652 }
653
654
655 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
656 .matchEthType(Ethernet.TYPE_IPV4)
657 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
658 .matchIcmpType(TYPE_ECHO_REQUEST)
659 .matchIcmpCode(CODE_ECHO_REQEUST)
660 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
661
662 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
663 .extension(buildMoveEthSrcToDstExtension(device), device.id())
664 .extension(buildMoveIpSrcToDstExtension(device), device.id())
665 .extension(buildLoadExtension(device,
666 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
667 .extension(buildLoadExtension(device,
668 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
669 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900670 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900671 .setOutput(PortNumber.IN_PORT);
672
673 flowService.setRule(
674 appId,
675 tenantDeviceId,
676 sBuilder.build(),
677 tBuilder.build(),
678 PRIORITY_ICMP_RULE,
679 tableNum,
680 install);
681 }
682
Jian Li8f944d42021-03-23 00:43:29 +0900683 private void setArpRuleForTenantNetwork(DeviceId tenantDeviceId,
684 boolean install) {
685 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
686 .matchEthType(EthType.EtherType.ARP.ethType().toShort());
687
688 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
689 .transition(TENANT_FORWARDING_TABLE);
690
691 flowService.setRule(
692 appId,
693 tenantDeviceId,
694 sBuilder.build(),
695 tBuilder.build(),
696 PRIORITY_ARP_DEFAULT_RULE,
697 TENANT_ARP_TABLE,
698 install
699 );
700 }
701
Daniel Parkf3136042021-03-10 07:49:11 +0900702 private void setGatewayArpRuleForTenantInternalNetwork(KubevirtRouter router,
703 KubevirtNetwork network,
704 int tableNum,
705 DeviceId gwDeviceId,
706 DeviceId tenantDeviceId,
707 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900708
Daniel Parkf3136042021-03-10 07:49:11 +0900709 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900710
Daniel Parkf3136042021-03-10 07:49:11 +0900711 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900712 log.warn("Setting gateway arp rule for internal network because " +
713 "there's no br-int port for device {}", gwDeviceId);
714 return;
715 }
716
717 Device device = deviceService.getDevice(tenantDeviceId);
718
719 if (device == null) {
720 log.warn("Setting gateway arp rule for internal network because " +
721 "there's no tenant device for {} to install gateway arp rule",
722 tenantDeviceId);
723 return;
724 }
725
726
727 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
728 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
729 .matchArpOp(ARP.OP_REQUEST)
730 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
731
732 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
733 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
734 .extension(buildMoveArpShaToThaExtension(device), device.id())
735 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
736 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900737 .setArpSha(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900738 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900739 .setEthSrc(routerMacAddress)
Daniel Parkbabde9c2021-03-09 13:37:42 +0900740 .setOutput(PortNumber.IN_PORT);
741
742 flowService.setRule(
743 appId,
744 device.id(),
745 sBuilder.build(),
746 tBuilder.build(),
747 PRIORITY_ARP_GATEWAY_RULE,
748 tableNum,
749 install
750 );
751 }
752
Daniel Parkf3136042021-03-10 07:49:11 +0900753 private void setGatewayProviderInterNetworkRoutingWithinSameRouter(
Daniel Parkbabde9c2021-03-09 13:37:42 +0900754 KubevirtNetwork network, KubevirtRouter router, KubevirtNode gatewayNode, boolean install) {
Daniel Park2884b232021-03-04 18:58:47 +0900755 router.internal().forEach(srcNetwork -> {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900756 if (srcNetwork.equals(network.networkId())
757 || kubevirtNetworkService.network(srcNetwork) == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900758 return;
759 }
760
Daniel Parkbabde9c2021-03-09 13:37:42 +0900761 kubevirtPortService.ports(network.networkId()).forEach(port -> {
Daniel Parkf3136042021-03-10 07:49:11 +0900762 setGatewayInterNetworkRoutingFromNetworkToPort(router, kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +0900763 port, gatewayNode, install);
764 });
Daniel Park2884b232021-03-04 18:58:47 +0900765 });
766 }
767
Daniel Parkf3136042021-03-10 07:49:11 +0900768 private void setGatewayInterNetworkRoutingFromNetworkToPort(KubevirtRouter router,
769 KubevirtNetwork srcNetwork,
770 KubevirtPort dstPort,
771 KubevirtNode gatewayNode,
772 boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900773 Device gwDevice = deviceService.getDevice(gatewayNode.intgBridge());
774
775 if (gwDevice == null) {
776 log.warn("Failed to set internal network routing rule because " +
777 "there's no device Id for device {}", gatewayNode.intgBridge());
778 return;
779 }
780
Daniel Parkf3136042021-03-10 07:49:11 +0900781 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900782
Daniel Parkf3136042021-03-10 07:49:11 +0900783 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900784 log.warn("Failed to set internal network routing rule because " +
785 "there's no br-int port for device {}", gatewayNode.intgBridge());
786 return;
787 }
788
Daniel Park4cb120b2021-03-24 12:30:50 +0900789 TrafficSelector.Builder sBuilder;
790 TrafficTreatment treatment;
Daniel Parkbabde9c2021-03-09 13:37:42 +0900791
Daniel Park4cb120b2021-03-24 12:30:50 +0900792 if (srcNetwork.type() == FLAT || srcNetwork.type() == VLAN) {
793 sBuilder = DefaultTrafficSelector.builder()
794 .matchEthType(Ethernet.TYPE_IPV4)
795 .matchEthDst(routerMacAddress)
796 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
797 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
Daniel Parkbabde9c2021-03-09 13:37:42 +0900798
Daniel Park4cb120b2021-03-24 12:30:50 +0900799 treatment = DefaultTrafficTreatment.builder()
800 .setEthSrc(routerMacAddress)
801 .setEthDst(dstPort.macAddress())
802 .transition(FORWARDING_TABLE)
803 .build();
804
805 flowService.setRule(
806 appId,
807 gwDevice.id(),
808 sBuilder.build(),
809 treatment,
810 PRIORITY_INTERNAL_ROUTING_RULE,
Jian Lif89d9602021-04-27 19:05:49 +0900811 GW_ENTRY_TABLE,
Daniel Park4cb120b2021-03-24 12:30:50 +0900812 install);
813 } else {
814 KubevirtNetwork dstNetwork = kubevirtNetworkService.network(dstPort.networkId());
815 if (dstNetwork == null) {
816 return;
817 }
818
819 KubevirtNode dstPortWorkerNode = kubevirtNodeService.node(dstPort.deviceId());
820 if (dstPortWorkerNode == null) {
821 return;
822 }
823
824 sBuilder = DefaultTrafficSelector.builder()
825 .matchEthType(Ethernet.TYPE_IPV4)
826 .matchEthDst(routerMacAddress)
827 .matchTunnelId(Long.parseLong(srcNetwork.segmentId()))
828 .matchIPSrc(IpPrefix.valueOf(srcNetwork.cidr()))
829 .matchIPDst(IpPrefix.valueOf(dstPort.ipAddress(), 32));
830
831 treatment = DefaultTrafficTreatment.builder()
832 .setTunnelId(Long.parseLong(dstNetwork.segmentId()))
833 .setEthSrc(routerMacAddress)
834 .setEthDst(dstPort.macAddress())
835 .extension(buildExtension(
836 deviceService,
837 gatewayNode.tunBridge(),
838 dstPortWorkerNode.dataIp().getIp4Address()),
839 gatewayNode.tunBridge())
840 .setOutput(PortNumber.IN_PORT)
841 .build();
842
843 flowService.setRule(
844 appId,
845 gatewayNode.tunBridge(),
846 sBuilder.build(),
847 treatment,
848 PRIORITY_INTERNAL_ROUTING_RULE,
849 TUNNEL_DEFAULT_TABLE,
850 install);
851 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900852 }
853
Daniel Parkf3136042021-03-10 07:49:11 +0900854 private void setGatewayArpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
855 int tableNum, DeviceId gwDeviceId, boolean install) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900856
857
858 Device device = deviceService.getDevice(gwDeviceId);
Daniel Parkf3136042021-03-10 07:49:11 +0900859 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Parkbabde9c2021-03-09 13:37:42 +0900860
Daniel Parkf3136042021-03-10 07:49:11 +0900861 if (routerMacAddress == null) {
Daniel Parkbabde9c2021-03-09 13:37:42 +0900862 log.warn("Setting gateway arp rule for internal network because " +
863 "there's no br-int port for device {}", gwDeviceId);
Daniel Park2884b232021-03-04 18:58:47 +0900864 return;
865 }
866
Jian Li858ccd72021-02-04 17:25:01 +0900867 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
868 sBuilder.matchEthType(EthType.EtherType.ARP.ethType().toShort())
869 .matchArpOp(ARP.OP_REQUEST)
870 .matchArpTpa(Ip4Address.valueOf(network.gatewayIp().toString()));
871
872 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
873 tBuilder.extension(buildMoveEthSrcToDstExtension(device), device.id())
874 .extension(buildMoveArpShaToThaExtension(device), device.id())
875 .extension(buildMoveArpSpaToTpaExtension(device), device.id())
876 .setArpOp(ARP.OP_REPLY)
Daniel Parkf3136042021-03-10 07:49:11 +0900877 .setArpSha(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900878 .setArpSpa(Ip4Address.valueOf(network.gatewayIp().toString()))
Daniel Parkf3136042021-03-10 07:49:11 +0900879 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900880 .setOutput(PortNumber.IN_PORT);
881
882 flowService.setRule(
883 appId,
884 device.id(),
885 sBuilder.build(),
886 tBuilder.build(),
887 PRIORITY_ARP_GATEWAY_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900888 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900889 install
890 );
891 }
892
Daniel Park2884b232021-03-04 18:58:47 +0900893 /**
894 * Sends ICMP echo reply for the ICMP echo request from the kubevirt VM.
895 *
Daniel Parkf3136042021-03-10 07:49:11 +0900896 * @param router kubevirt router
Daniel Park2884b232021-03-04 18:58:47 +0900897 * @param network kubevirt network
898 * @param tableNum flow table number
899 * @param deviceId device id of the selected gateway for the network
900 * @param install install if true, remove otherwise
901 */
Daniel Parkf3136042021-03-10 07:49:11 +0900902 private void setGatewayIcmpRuleForProviderInternalNetwork(KubevirtRouter router, KubevirtNetwork network,
903 int tableNum, DeviceId deviceId, boolean install) {
904 MacAddress routerMacAddress = getRouterMacAddress(router);
Daniel Park2884b232021-03-04 18:58:47 +0900905
Daniel Parkf3136042021-03-10 07:49:11 +0900906 if (routerMacAddress == null) {
Daniel Park2884b232021-03-04 18:58:47 +0900907 log.error("Setting gateway ICMP rule for internal network because " +
908 "there's no br-int port for device {}", deviceId);
909 return;
910 }
911
Jian Li858ccd72021-02-04 17:25:01 +0900912 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
913 .matchEthType(Ethernet.TYPE_IPV4)
914 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
915 .matchIcmpType(TYPE_ECHO_REQUEST)
916 .matchIcmpCode(CODE_ECHO_REQEUST)
917 .matchIPDst(IpPrefix.valueOf(network.gatewayIp(), 32));
918
919 Device device = deviceService.getDevice(deviceId);
920 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
921 .extension(buildMoveEthSrcToDstExtension(device), device.id())
922 .extension(buildMoveIpSrcToDstExtension(device), device.id())
923 .extension(buildLoadExtension(device,
924 NXM_NX_IP_TTL, DEFAULT_TTL), device.id())
925 .extension(buildLoadExtension(device,
926 NXM_OF_ICMP_TYPE, TYPE_ECHO_REPLY), device.id())
927 .setIpSrc(network.gatewayIp())
Daniel Parkf3136042021-03-10 07:49:11 +0900928 .setEthSrc(routerMacAddress)
Jian Li858ccd72021-02-04 17:25:01 +0900929 .setOutput(PortNumber.IN_PORT);
930
931 flowService.setRule(
932 appId,
933 deviceId,
934 sBuilder.build(),
935 tBuilder.build(),
936 PRIORITY_ICMP_RULE,
Daniel Parka8968802021-02-25 09:14:22 +0900937 tableNum,
Jian Li858ccd72021-02-04 17:25:01 +0900938 install);
939 }
940
Jian Li0c656f02021-06-07 13:32:39 +0900941 private boolean hasPort(DeviceId deviceId, String portName) {
Jian Li0c656f02021-06-07 13:32:39 +0900942 Port port = deviceService.getPorts(deviceId).stream()
943 .filter(p -> p.isEnabled() &&
944 Objects.equals(p.annotations().value(PORT_NAME), portName))
945 .findAny().orElse(null);
Jian Lif3a3c5a2021-06-30 10:21:31 +0900946 log.info("The port {} already existed on device {}", portName, deviceId);
947
Jian Li0c656f02021-06-07 13:32:39 +0900948 return port != null;
949 }
950
Daniel Park2884b232021-03-04 18:58:47 +0900951 private class InternalRouterEventListener implements KubevirtRouterListener {
952 private boolean isRelevantHelper() {
953 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Daniel Parka8968802021-02-25 09:14:22 +0900954 }
955
Daniel Park2884b232021-03-04 18:58:47 +0900956 @Override
957 public void event(KubevirtRouterEvent event) {
958 switch (event.type()) {
959 case KUBEVIRT_ROUTER_CREATED:
960 eventExecutor.execute(() -> processRouterCreation(event.subject()));
961 break;
962 case KUBEVIRT_ROUTER_REMOVED:
963 eventExecutor.execute(() -> processRouterDeletion(event.subject()));
964 break;
965 case KUBEVIRT_ROUTER_UPDATED:
966 eventExecutor.execute(() -> processRouterUpdate(event.subject()));
967 break;
968 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_ATTACHED:
969 eventExecutor.execute(() -> processRouterInternalNetworksAttached(event.subject(),
970 event.internal()));
971 break;
972 case KUBEVIRT_ROUTER_INTERNAL_NETWORKS_DETACHED:
973 eventExecutor.execute(() -> processRouterInternalNetworksDetached(event.subject(),
974 event.internal()));
975 break;
976 case KUBEVIRT_GATEWAY_NODE_ATTACHED:
977 eventExecutor.execute(() -> processRouterGatewayNodeAttached(event.subject(),
978 event.gateway()));
979 break;
980 case KUBEVIRT_GATEWAY_NODE_DETACHED:
981 eventExecutor.execute(() -> processRouterGatewayNodeDetached(event.subject(),
982 event.gateway()));
983 break;
984 case KUBEVIRT_GATEWAY_NODE_CHANGED:
985 eventExecutor.execute(() -> processRouterGatewayNodeChanged(event.subject(),
986 event.gateway()));
987 break;
Daniel Parka8968802021-02-25 09:14:22 +0900988
Daniel Park2884b232021-03-04 18:58:47 +0900989 default:
990 //do nothing
991 break;
992 }
993 }
994
995 private void processRouterCreation(KubevirtRouter router) {
996 // When a router is created, we performs the election process to associate the router
997 // to the specific gateway. After the election, KubevirtNetwork handler installs bunch of rules
998 // to elected gateway node so that VMs associated to the router can ping to their gateway IP.
999 // SNAT and floating ip rule setup is out of this handler's scope and would be done with the other handlers
1000 if (!isRelevantHelper()) {
1001 return;
1002 }
1003 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1004 if (electedGw == null) {
1005 return;
1006 }
1007
1008 router.internal().forEach(networkName -> {
1009 KubevirtNetwork network = networkService.network(networkName);
1010
1011 if (network != null) {
1012 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1013 }
1014 });
1015 kubevirtRouterService.updateRouter(router.updatedElectedGateway(electedGw.hostname()));
1016 }
1017
1018 private void processRouterDeletion(KubevirtRouter router) {
1019 if (!isRelevantHelper()) {
1020 return;
1021 }
1022 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1023 if (electedGw == null) {
1024 return;
1025 }
1026
1027 router.internal().forEach(networkName -> {
1028 KubevirtNetwork network = networkService.network(networkName);
1029
1030 if (network != null) {
1031 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
1032 }
1033 });
1034 }
1035
1036 private void processRouterUpdate(KubevirtRouter router) {
1037 if (!isRelevantHelper()) {
1038 return;
1039 }
1040 if (router.electedGateway() == null) {
1041 return;
1042 }
1043
1044 KubevirtNode electedGw = nodeService.node(router.electedGateway());
1045
1046 router.internal().forEach(networkName -> {
1047 KubevirtNetwork network = networkService.network(networkName);
1048
1049 if (network != null) {
1050 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1051 }
1052 });
1053 }
1054
1055 private void processRouterInternalNetworksAttached(KubevirtRouter router,
1056 Set<String> attachedInternalNetworks) {
1057 if (!isRelevantHelper()) {
1058 return;
1059 }
1060 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1061 if (electedGw == null) {
1062 return;
1063 }
1064
1065 attachedInternalNetworks.forEach(networkName -> {
1066 KubevirtNetwork network = networkService.network(networkName);
1067
1068 if (network != null) {
1069 initGatewayNodeForInternalNetwork(network, router, electedGw, true);
1070 }
1071 });
1072 }
1073
1074 private void processRouterInternalNetworksDetached(KubevirtRouter router,
1075 Set<String> detachedInternalNetworks) {
1076 if (!isRelevantHelper()) {
1077 return;
1078 }
1079 KubevirtNode electedGw = gatewayNodeForSpecifiedRouter(nodeService, router);
1080 if (electedGw == null) {
1081 return;
1082 }
1083
1084 detachedInternalNetworks.forEach(networkName -> {
1085 KubevirtNetwork network = networkService.network(networkName);
1086
1087 if (network != null) {
1088 initGatewayNodeForInternalNetwork(network, router, electedGw, false);
1089 }
Daniel Park2884b232021-03-04 18:58:47 +09001090
Daniel Parkbabde9c2021-03-09 13:37:42 +09001091 removeDetachedInternalNetworkRules(network, router, electedGw);
1092 });
1093 }
1094
Jian Li8f944d42021-03-23 00:43:29 +09001095 private void removeDetachedInternalNetworkRules(KubevirtNetwork removedNetwork,
1096 KubevirtRouter router,
Daniel Parkbabde9c2021-03-09 13:37:42 +09001097 KubevirtNode electedGw) {
Daniel Parkf3136042021-03-10 07:49:11 +09001098 router.internal().stream().filter(networkId -> kubevirtNetworkService.network(networkId) != null)
1099 .forEach(networkId -> {
1100 kubevirtPortService.ports(networkId).forEach(kubevirtPort -> {
1101 setGatewayInterNetworkRoutingFromNetworkToPort(
1102 router, removedNetwork, kubevirtPort, electedGw, false);
1103 });
Daniel Parkbabde9c2021-03-09 13:37:42 +09001104 });
Daniel Park2884b232021-03-04 18:58:47 +09001105 }
1106
1107 private void processRouterGatewayNodeAttached(KubevirtRouter router,
1108 String associatedGateway) {
1109 if (!isRelevantHelper()) {
1110 return;
1111 }
1112
1113 KubevirtNode gatewayNode = nodeService.node(associatedGateway);
1114 if (gatewayNode == null) {
1115 return;
1116 }
1117
1118 router.internal().forEach(networkName -> {
1119 KubevirtNetwork network = networkService.network(networkName);
1120
1121 if (network != null) {
1122 initGatewayNodeForInternalNetwork(network, router, gatewayNode, true);
1123 }
1124 });
1125 }
1126
1127 private void processRouterGatewayNodeDetached(KubevirtRouter router,
1128 String disAssociatedGateway) {
1129 if (!isRelevantHelper()) {
1130 return;
1131 }
1132
1133 KubevirtNode gatewayNode = nodeService.node(disAssociatedGateway);
1134 if (gatewayNode == null) {
1135 return;
1136 }
1137
1138 router.internal().forEach(networkName -> {
1139 KubevirtNetwork network = networkService.network(networkName);
1140
1141 if (network != null) {
1142 initGatewayNodeForInternalNetwork(network, router, gatewayNode, false);
1143 }
1144 });
1145 }
1146
1147 private void processRouterGatewayNodeChanged(KubevirtRouter router,
1148 String disAssociatedGateway) {
1149 if (!isRelevantHelper()) {
1150 return;
1151 }
1152
1153 KubevirtNode oldGatewayNode = nodeService.node(disAssociatedGateway);
1154 if (oldGatewayNode == null) {
1155 return;
1156 }
1157
1158 router.internal().forEach(networkName -> {
1159 KubevirtNetwork network = networkService.network(networkName);
1160
1161 if (network != null) {
1162 initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, false);
1163 }
1164 });
1165
1166 KubevirtNode newGatewayNode = nodeService.node(router.electedGateway());
1167 if (newGatewayNode == null) {
1168 return;
1169 }
1170
1171 router.internal().forEach(networkName -> {
1172 KubevirtNetwork network = networkService.network(networkName);
1173
1174 if (network != null) {
Daniel Parka5ba88d2021-05-28 15:46:46 +09001175 initGatewayNodeForInternalNetwork(network, router, newGatewayNode, true);
Daniel Park2884b232021-03-04 18:58:47 +09001176 }
1177 });
1178 }
Daniel Parka8968802021-02-25 09:14:22 +09001179 }
1180
Jian Li556709c2021-02-03 17:54:28 +09001181 private class InternalNetworkEventListener implements KubevirtNetworkListener {
1182
1183 private boolean isRelevantHelper() {
1184 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1185 }
1186
1187 @Override
1188 public void event(KubevirtNetworkEvent event) {
1189 switch (event.type()) {
1190 case KUBEVIRT_NETWORK_CREATED:
1191 eventExecutor.execute(() -> processNetworkCreation(event.subject()));
1192 break;
1193 case KUBEVIRT_NETWORK_REMOVED:
1194 eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
1195 break;
1196 case KUBEVIRT_NETWORK_UPDATED:
1197 default:
1198 // do nothing
1199 break;
1200 }
1201 }
1202
1203 private void processNetworkCreation(KubevirtNetwork network) {
1204 if (!isRelevantHelper()) {
1205 return;
1206 }
1207
1208 switch (network.type()) {
1209 case VXLAN:
1210 case GRE:
1211 case GENEVE:
1212 initIntegrationTunnelBridge(network);
1213 break;
1214 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001215 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001216 break;
Jian Li556709c2021-02-03 17:54:28 +09001217 default:
1218 // do nothing
1219 break;
1220 }
1221 }
1222
1223 private void processNetworkRemoval(KubevirtNetwork network) {
1224 if (!isRelevantHelper()) {
1225 return;
1226 }
1227
1228 switch (network.type()) {
1229 case VXLAN:
1230 case GRE:
1231 case GENEVE:
1232 purgeIntegrationTunnelBridge(network);
1233 break;
1234 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +09001235 case VLAN:
Daniel Parka8968802021-02-25 09:14:22 +09001236 break;
Jian Li556709c2021-02-03 17:54:28 +09001237 default:
1238 // do nothing
1239 break;
1240 }
1241 }
1242
1243 private void initIntegrationTunnelBridge(KubevirtNetwork network) {
1244 if (network.segmentId() == null) {
1245 return;
1246 }
1247
Jian Li94b6d162021-04-15 17:09:11 +09001248 nodeService.completeNodes(WORKER).forEach(n -> {
Jian Li556709c2021-02-03 17:54:28 +09001249 createBridge(n, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001250 createPatchTenantInterface(n, network);
1251 setDefaultRulesForTenantNetwork(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001252 });
1253 }
1254
1255 private void purgeIntegrationTunnelBridge(KubevirtNetwork network) {
1256 if (network.segmentId() == null) {
1257 return;
1258 }
1259
Jian Li567b25c2021-05-27 15:17:59 +09001260 nodeService.completeNodes(WORKER).forEach(n -> {
Jian Liea1ead72021-05-28 11:00:07 +09001261 removeAllFlows(n, network);
Jian Li556709c2021-02-03 17:54:28 +09001262 removePatchInterface(n, network);
Jian Liea1ead72021-05-28 11:00:07 +09001263
Jian Li0c656f02021-06-07 13:32:39 +09001264 waitFor(5);
Jian Liea1ead72021-05-28 11:00:07 +09001265
Jian Li556709c2021-02-03 17:54:28 +09001266 removeBridge(n, network);
1267 });
1268 }
1269 }
1270
1271 private class InternalNodeEventListener implements KubevirtNodeListener {
1272
1273 private boolean isRelevantHelper() {
1274 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1275 }
1276
1277 @Override
1278 public void event(KubevirtNodeEvent event) {
1279 switch (event.type()) {
1280 case KUBEVIRT_NODE_COMPLETE:
1281 eventExecutor.execute(() -> processNodeCompletion(event.subject()));
1282 break;
Daniel Parka5ba88d2021-05-28 15:46:46 +09001283 case KUBEVIRT_NODE_INCOMPLETE:
Daniel Park2884b232021-03-04 18:58:47 +09001284 case KUBEVIRT_NODE_REMOVED:
1285 eventExecutor.execute(() -> processNodeDeletion(event.subject()));
1286 break;
Jian Li556709c2021-02-03 17:54:28 +09001287 case KUBEVIRT_NODE_UPDATED:
1288 default:
1289 // do nothing
1290 break;
1291 }
1292 }
1293
1294 private void processNodeCompletion(KubevirtNode node) {
1295 if (!isRelevantHelper()) {
1296 return;
1297 }
1298
Daniel Parka8968802021-02-25 09:14:22 +09001299 if (node.type().equals(WORKER)) {
1300 for (KubevirtNetwork network : networkService.networks()) {
1301 switch (network.type()) {
1302 case VXLAN:
1303 case GRE:
1304 case GENEVE:
1305 if (network.segmentId() == null) {
1306 continue;
1307 }
1308 createBridge(node, network);
Daniel Parkf3136042021-03-10 07:49:11 +09001309 createPatchTenantInterface(node, network);
1310 setDefaultRulesForTenantNetwork(node, network);
Jian Li8f944d42021-03-23 00:43:29 +09001311 setGatewayArpRulesForTenantNetwork(node, network);
1312 setGatewayIcmpRulesForTenantNetwork(node, network);
1313 setGatewayRuleToWorkerNodeWhenNodeCreated(node, network);
Daniel Parka8968802021-02-25 09:14:22 +09001314 break;
1315 case FLAT:
1316 case VLAN:
1317 default:
1318 // do nothing
1319 break;
1320 }
1321 }
1322 } else if (node.type().equals(GATEWAY)) {
Daniel Park2884b232021-03-04 18:58:47 +09001323 updateGatewayNodeForRouter();
Jian Li556709c2021-02-03 17:54:28 +09001324 }
1325 }
Daniel Park2884b232021-03-04 18:58:47 +09001326
1327 private void processNodeDeletion(KubevirtNode node) {
1328 if (!isRelevantHelper()) {
1329 return;
1330 }
Daniel Park2884b232021-03-04 18:58:47 +09001331 if (node.type().equals(GATEWAY)) {
Daniel Parka5ba88d2021-05-28 15:46:46 +09001332 kubevirtRouterService.routers()
1333 .stream()
1334 .filter(router -> router.electedGateway().equals(node.hostname()))
1335 .forEach(router -> {
1336 router.internal().forEach(networkName -> {
1337 KubevirtNetwork network = networkService.network(networkName);
1338
1339 if (network != null) {
1340 initGatewayNodeForInternalNetwork(network, router, node, false);
1341 }
1342 });
1343 });
Daniel Park2884b232021-03-04 18:58:47 +09001344 updateGatewayNodeForRouter();
Daniel Park2884b232021-03-04 18:58:47 +09001345 }
1346 }
1347
1348 private void updateGatewayNodeForRouter() {
1349 kubevirtRouterService.routers().forEach(router -> {
1350 KubevirtNode newGwNode = gatewayNodeForSpecifiedRouter(nodeService, router);
1351
1352 if (newGwNode == null) {
1353 return;
1354 }
1355 kubevirtRouterService.updateRouter(router.updatedElectedGateway(newGwNode.hostname()));
1356 });
1357 }
Jian Li556709c2021-02-03 17:54:28 +09001358 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001359
1360 private class InternalKubevirtPortListener implements KubevirtPortListener {
1361
1362 private boolean isRelevantHelper() {
1363 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
1364 }
1365
1366 @Override
1367 public void event(KubevirtPortEvent event) {
1368 switch (event.type()) {
1369 case KUBEVIRT_PORT_CREATED:
1370 eventExecutor.execute(() -> processPortCreation(event.subject()));
1371 break;
1372 case KUBEVIRT_PORT_UPDATED:
1373 eventExecutor.execute(() -> processPortUpdate(event.subject()));
1374 break;
1375 case KUBEVIRT_PORT_REMOVED:
1376 eventExecutor.execute(() -> processPortDeletion(event.subject()));
1377 break;
1378 default:
1379 //do nothing
1380 break;
1381 }
1382 }
1383
1384 private void processPortCreation(KubevirtPort kubevirtPort) {
1385 if (!isRelevantHelper()) {
1386 return;
1387 }
1388
1389 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1390 if (router == null) {
1391 return;
1392 }
1393
1394 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1395
1396 if (gwNode != null) {
1397
1398 router.internal().forEach(srcNetwork -> {
1399 if (srcNetwork.equals(kubevirtPort.networkId())
1400 || kubevirtNetworkService.network(srcNetwork) == null) {
1401 return;
1402 }
Jian Li8f944d42021-03-23 00:43:29 +09001403 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1404 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001405 kubevirtPort, gwNode, true);
1406 });
1407 }
1408 }
1409
1410 private void processPortUpdate(KubevirtPort kubevirtPort) {
1411 if (!isRelevantHelper()) {
1412 return;
1413 }
1414
1415 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1416 if (router == null) {
1417 return;
1418 }
1419
1420 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1421
1422 if (gwNode != null) {
1423
1424 router.internal().forEach(srcNetwork -> {
1425 if (srcNetwork.equals(kubevirtPort.networkId())
1426 || kubevirtNetworkService.network(srcNetwork) == null) {
1427 return;
1428 }
Jian Li8f944d42021-03-23 00:43:29 +09001429 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1430 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001431 kubevirtPort, gwNode, true);
1432 });
1433 }
1434 }
1435
1436 private void processPortDeletion(KubevirtPort kubevirtPort) {
1437 if (!isRelevantHelper()) {
1438 return;
1439 }
1440
1441 KubevirtRouter router = getRouterForKubevirtPort(kubevirtRouterService, kubevirtPort);
1442 if (router == null) {
1443 return;
1444 }
1445
1446 KubevirtNode gwNode = gatewayNodeForSpecifiedRouter(kubevirtNodeService, router);
1447
1448 if (gwNode != null) {
1449
1450 router.internal().forEach(srcNetwork -> {
1451 if (srcNetwork.equals(kubevirtPort.networkId())
1452 || kubevirtNetworkService.network(srcNetwork) == null) {
1453 return;
1454 }
Jian Li8f944d42021-03-23 00:43:29 +09001455 setGatewayInterNetworkRoutingFromNetworkToPort(router,
1456 kubevirtNetworkService.network(srcNetwork),
Daniel Parkbabde9c2021-03-09 13:37:42 +09001457 kubevirtPort, gwNode, false);
1458 });
1459 }
Daniel Parkbabde9c2021-03-09 13:37:42 +09001460 }
1461 }
Jian Li556709c2021-02-03 17:54:28 +09001462}