blob: c30ea73552b2b3e11f13c30c7ba63639c7c68f48 [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Jian Li26949762018-03-30 15:46:37 +09002 * Copyright 2016-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 */
Hyunsun Moon44aac662017-02-18 02:07:01 +090016
17package org.onosproject.openstacknetworking.impl;
18
19import com.google.common.base.Strings;
Hyunsun Moon44aac662017-02-18 02:07:01 +090020import org.onlab.packet.Ethernet;
daniel parka792cf72017-04-14 16:25:35 +090021import org.onlab.packet.VlanId;
Jian Li5c09e212018-10-24 18:23:58 +090022import org.onosproject.cfg.ComponentConfigService;
23import org.onosproject.cfg.ConfigProperty;
Jian Li91be8cd2018-07-22 00:44:46 +090024import org.onosproject.cluster.ClusterService;
25import org.onosproject.cluster.LeadershipService;
26import org.onosproject.cluster.NodeId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090027import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.mastership.MastershipService;
daniel park796c2eb2018-03-22 17:01:51 +090030import org.onosproject.net.PortNumber;
Hyunsun Moon44aac662017-02-18 02:07:01 +090031import org.onosproject.net.device.DeviceService;
sangho1aaa7882017-05-31 13:22:47 +090032import org.onosproject.net.driver.DriverService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090033import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090037import org.onosproject.openstacknetworking.api.InstancePort;
38import org.onosproject.openstacknetworking.api.InstancePortEvent;
39import org.onosproject.openstacknetworking.api.InstancePortListener;
40import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090041import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
SONA Project6bc5c4a2018-12-14 23:49:52 +090042import org.onosproject.openstacknetworking.api.OpenstackNetwork.Type;
Jian Li91be8cd2018-07-22 00:44:46 +090043import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
44import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
Hyunsun Moon44aac662017-02-18 02:07:01 +090045import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090046import org.onosproject.openstacknode.api.OpenstackNode;
47import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090048import org.openstack4j.model.network.Network;
Frank Wangf9571662017-06-06 18:01:29 +080049import org.openstack4j.model.network.Port;
Jian Li34220ea2018-11-14 01:30:24 +090050import org.osgi.service.component.annotations.Activate;
51import org.osgi.service.component.annotations.Component;
52import org.osgi.service.component.annotations.Deactivate;
53import org.osgi.service.component.annotations.Reference;
54import org.osgi.service.component.annotations.ReferenceCardinality;
Hyunsun Moon44aac662017-02-18 02:07:01 +090055import org.slf4j.Logger;
56
Jian Li91be8cd2018-07-22 00:44:46 +090057import java.util.Objects;
Jian Li5c09e212018-10-24 18:23:58 +090058import java.util.Set;
Hyunsun Moon44aac662017-02-18 02:07:01 +090059import java.util.concurrent.ExecutorService;
60
61import static java.util.concurrent.Executors.newSingleThreadExecutor;
62import static org.onlab.util.Tools.groupedThreads;
Jian Lidaa91152019-09-08 00:35:11 +090063import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Jian Li1e9cb732018-11-25 23:17:21 +090064import static org.onosproject.openstacknetworking.api.Constants.ACL_EGRESS_TABLE;
Jian Li5c09e212018-10-24 18:23:58 +090065import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
66import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
67import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
Jian Li70a2c3f2018-04-13 17:26:31 +090068import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
sanghodc375372017-06-08 10:41:30 +090069import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
70import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Frank Wangf9571662017-06-06 18:01:29 +080071import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
Daniel Parkd1b14d32018-06-12 16:10:28 +090072import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_DOWNSTREAM_RULE;
Daniel Parkd1b14d32018-06-12 16:10:28 +090073import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_UPSTREAM_RULE;
74import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_UPSTREAM_RULE;
sanghodc375372017-06-08 10:41:30 +090075import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
76import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
Jian Li960ae512018-07-03 22:50:56 +090077import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
Jian Li70a2c3f2018-04-13 17:26:31 +090078import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
Jian Li34220ea2018-11-14 01:30:24 +090079import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
Jian Li5c09e212018-10-24 18:23:58 +090080import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
Jian Lidaa91152019-09-08 00:35:11 +090081import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
Jian Liec5c32b2018-07-13 14:28:58 +090082import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
Jian Li2d68c192018-12-13 15:52:59 +090083import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
Jian Li26949762018-03-30 15:46:37 +090084import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Jian Lidaa91152019-09-08 00:35:11 +090085import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
Hyunsun Moon0d457362017-06-27 17:19:41 +090086import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
Hyunsun Moon44aac662017-02-18 02:07:01 +090087import static org.slf4j.LoggerFactory.getLogger;
88
89
90/**
91 * Populates switching flow rules on OVS for the basic connectivity among the
92 * virtual instances in the same network.
93 */
94@Component(immediate = true)
Jian Li4d138702018-11-27 17:25:28 +090095public class OpenstackSwitchingHandler {
Hyunsun Moon44aac662017-02-18 02:07:01 +090096
97 private final Logger log = getLogger(getClass());
98
Jian Li5c09e212018-10-24 18:23:58 +090099 private static final String ARP_MODE = "arpMode";
Jian Li4d138702018-11-27 17:25:28 +0900100 private static final String ERR_SET_FLOWS_VNI = "Failed to set flows for " +
101 "%s: Failed to get VNI for %s";
102 private static final String STR_NONE = "<none>";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900105 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900106
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900108 protected MastershipService mastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900109
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900111 protected DeviceService deviceService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900112
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li91be8cd2018-07-22 00:44:46 +0900114 protected DriverService driverService;
115
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li91be8cd2018-07-22 00:44:46 +0900117 protected ClusterService clusterService;
118
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li5c09e212018-10-24 18:23:58 +0900120 protected ComponentConfigService configService;
121
Ray Milkey956bb162018-10-26 10:53:44 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li91be8cd2018-07-22 00:44:46 +0900123 protected LeadershipService leadershipService;
124
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900126 protected OpenstackFlowRuleService osFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900127
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900129 protected InstancePortService instancePortService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700131 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900132 protected OpenstackNetworkService osNetworkService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900135 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136
137 private final ExecutorService eventExecutor = newSingleThreadExecutor(
138 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
139 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Jian Li91be8cd2018-07-22 00:44:46 +0900140 private final InternalOpenstackNetworkListener osNetworkListener =
141 new InternalOpenstackNetworkListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900142 private ApplicationId appId;
Jian Li91be8cd2018-07-22 00:44:46 +0900143 private NodeId localNodeId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900144
145 @Activate
Jian Li4d138702018-11-27 17:25:28 +0900146 protected void activate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900147 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
Jian Li91be8cd2018-07-22 00:44:46 +0900148 localNodeId = clusterService.getLocalNode().id();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900149 instancePortService.addListener(instancePortListener);
Jian Li91be8cd2018-07-22 00:44:46 +0900150 osNetworkService.addListener(osNetworkListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900151
152 log.info("Started");
153 }
154
155 @Deactivate
Jian Li4d138702018-11-27 17:25:28 +0900156 protected void deactivate() {
Jian Li91be8cd2018-07-22 00:44:46 +0900157 osNetworkService.removeListener(osNetworkListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900158 instancePortService.removeListener(instancePortListener);
159 eventExecutor.shutdown();
160
161 log.info("Stopped");
162 }
163
Jian Lidaa91152019-09-08 00:35:11 +0900164 private void setJumpRulesForFlat(InstancePort port, boolean install) {
165 TrafficSelector selector = DefaultTrafficSelector.builder()
166 .matchInPort(port.portNumber())
167 .build();
Jian Li70a2c3f2018-04-13 17:26:31 +0900168
Jian Lidaa91152019-09-08 00:35:11 +0900169 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
170 .transition(STAT_FLAT_OUTBOUND_TABLE)
171 .build();
Jian Li70a2c3f2018-04-13 17:26:31 +0900172
173 osFlowRuleService.setRule(
174 appId,
175 port.deviceId(),
Jian Lidaa91152019-09-08 00:35:11 +0900176 selector,
177 treatment,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900178 PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
Jian Li5c09e212018-10-24 18:23:58 +0900179 DHCP_TABLE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900180 install);
Jian Li70a2c3f2018-04-13 17:26:31 +0900181 }
182
Jian Lidaa91152019-09-08 00:35:11 +0900183 private void setDownstreamRuleForFlat(InstancePort instPort,
184 short ethType, boolean install) {
185 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
186
187 if (ethType == Ethernet.TYPE_IPV4) {
188 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
189 .matchIPDst(instPort.ipAddress().toIpPrefix());
190 } else if (ethType == Ethernet.TYPE_ARP) {
191 sBuilder.matchEthType(Ethernet.TYPE_ARP)
192 .matchArpTpa(instPort.ipAddress().getIp4Address());
193 }
194
daniel park796c2eb2018-03-22 17:01:51 +0900195 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
196 .setOutput(instPort.portNumber())
197 .build();
198
199 osFlowRuleService.setRule(
200 appId,
201 instPort.deviceId(),
Jian Lidaa91152019-09-08 00:35:11 +0900202 sBuilder.build(),
daniel park796c2eb2018-03-22 17:01:51 +0900203 treatment,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900204 PRIORITY_FLAT_DOWNSTREAM_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900205 FLAT_TABLE,
daniel park796c2eb2018-03-22 17:01:51 +0900206 install);
Jian Lidaa91152019-09-08 00:35:11 +0900207 }
daniel park796c2eb2018-03-22 17:01:51 +0900208
Jian Lidaa91152019-09-08 00:35:11 +0900209 private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
210 setDownstreamRuleForFlat(instPort, Ethernet.TYPE_IPV4, install);
211 setDownstreamRuleForFlat(instPort, Ethernet.TYPE_ARP, install);
daniel park796c2eb2018-03-22 17:01:51 +0900212 }
213
Jian Li9a921b42018-06-18 02:44:50 +0900214 private void setUpstreamRulesForFlat(InstancePort instPort, boolean install) {
daniel park796c2eb2018-03-22 17:01:51 +0900215 TrafficSelector selector = DefaultTrafficSelector.builder()
216 .matchInPort(instPort.portNumber())
217 .build();
218
219 Network network = osNetworkService.network(instPort.networkId());
220
221 if (network == null) {
222 log.warn("The network does not exist");
223 return;
224 }
225
Jian Lidaa91152019-09-08 00:35:11 +0900226 deviceService.getPorts(instPort.deviceId()).stream()
227 .filter(port -> {
228 String annotPortName = port.annotations().value(PORT_NAME);
229 String portName = structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
230 + network.getProviderPhyNet());
231 return Objects.equals(annotPortName, portName);
232 })
233 .findAny().ifPresent(port -> {
234 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
235 .setOutput(port.number())
236 .build();
daniel park796c2eb2018-03-22 17:01:51 +0900237
Jian Lidaa91152019-09-08 00:35:11 +0900238 osFlowRuleService.setRule(
239 appId,
240 instPort.deviceId(),
241 selector,
242 treatment,
243 PRIORITY_FLAT_UPSTREAM_RULE,
244 FLAT_TABLE,
245 install);
246 });
daniel park796c2eb2018-03-22 17:01:51 +0900247 }
248
Jian Liea1b9662018-03-02 18:07:32 +0900249 /**
250 * Configures the flow rules which are used for L2 packet switching.
251 * Note that these rules will be inserted in switching table (table 5).
252 *
253 * @param instPort instance port object
254 * @param install install flag, add the rule if true, remove it otherwise
255 */
Jian Li2d68c192018-12-13 15:52:59 +0900256 private void setForwardingRulesForTunnel(InstancePort instPort, boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900257 // switching rules for the instPorts in the same node
258 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900259 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900260 .matchEthType(Ethernet.TYPE_IPV4)
261 .matchIPDst(instPort.ipAddress().toIpPrefix())
262 .matchTunnelId(getVni(instPort))
263 .build();
264
265 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900266 // TODO: this might not be necessary for the VMs located in the same subnet
Hyunsun Moon44aac662017-02-18 02:07:01 +0900267 .setEthDst(instPort.macAddress())
268 .setOutput(instPort.portNumber())
269 .build();
270
sanghodc375372017-06-08 10:41:30 +0900271 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900272 appId,
273 instPort.deviceId(),
274 selector,
275 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900276 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900277 FORWARDING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900278 install);
279
280 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900281 OpenstackNode localNode = osNodeService.node(instPort.deviceId());
282 if (localNode == null) {
283 final String error = String.format("Cannot find openstack node for %s",
284 instPort.deviceId());
285 throw new IllegalStateException(error);
286 }
287 osNodeService.completeNodes(COMPUTE).stream()
288 .filter(remoteNode -> !remoteNode.intgBridge().equals(localNode.intgBridge()))
289 .forEach(remoteNode -> {
Jian Li2d68c192018-12-13 15:52:59 +0900290 PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
291 osNetworkService, remoteNode);
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900292 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
293 .extension(buildExtension(
294 deviceService,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900295 remoteNode.intgBridge(),
296 localNode.dataIp().getIp4Address()),
297 remoteNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900298 .setOutput(portNum)
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900299 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900300
sanghodc375372017-06-08 10:41:30 +0900301 osFlowRuleService.setRule(
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900302 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900303 remoteNode.intgBridge(),
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900304 selector,
305 treatmentToRemote,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900306 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900307 FORWARDING_TABLE,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900308 install);
309 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900310 }
311
Jian Liea1b9662018-03-02 18:07:32 +0900312 /**
313 * Configures the flow rules which are used for L2 VLAN packet switching.
314 * Note that these rules will be inserted in switching table (table 5).
315 *
316 * @param instPort instance port object
317 * @param install install flag, add the rule if true, remove it otherwise
318 */
daniel parka792cf72017-04-14 16:25:35 +0900319 private void setForwardingRulesForVlan(InstancePort instPort, boolean install) {
320 // switching rules for the instPorts in the same node
321 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900322 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900323 .matchEthType(Ethernet.TYPE_IPV4)
324 .matchIPDst(instPort.ipAddress().toIpPrefix())
325 .matchVlanId(getVlanId(instPort))
326 .build();
327
328 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
329 .popVlan()
Jian Liea1b9662018-03-02 18:07:32 +0900330 // TODO: this might not be necessary for the VMs located in the same subnet
daniel parka792cf72017-04-14 16:25:35 +0900331 .setEthDst(instPort.macAddress())
332 .setOutput(instPort.portNumber())
333 .build();
334
sanghodc375372017-06-08 10:41:30 +0900335 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900336 appId,
337 instPort.deviceId(),
338 selector,
339 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900340 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900341 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900342 install);
343
344 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900345 osNodeService.completeNodes(COMPUTE).stream()
346 .filter(remoteNode -> !remoteNode.intgBridge().equals(instPort.deviceId()) &&
347 remoteNode.vlanIntf() != null)
348 .forEach(remoteNode -> {
daniel parka792cf72017-04-14 16:25:35 +0900349 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
Daniel Parkc64b4c62018-05-09 18:13:39 +0900350 .setEthDst(instPort.macAddress())
351 .setOutput(remoteNode.vlanPortNum())
352 .build();
daniel parka792cf72017-04-14 16:25:35 +0900353
sanghodc375372017-06-08 10:41:30 +0900354 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900355 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900356 remoteNode.intgBridge(),
daniel parka792cf72017-04-14 16:25:35 +0900357 selector,
358 treatmentToRemote,
daniel parka792cf72017-04-14 16:25:35 +0900359 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900360 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900361 install);
362 });
daniel parka792cf72017-04-14 16:25:35 +0900363 }
364
Jian Li5c09e212018-10-24 18:23:58 +0900365 private void setTunnelTagArpFlowRules(InstancePort instPort, boolean install) {
366 setTunnelTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
367 }
368
369 private void setTunnelTagIpFlowRules(InstancePort instPort, boolean install) {
370 setTunnelTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
371 }
372
Jian Liea1b9662018-03-02 18:07:32 +0900373 /**
Jian Li2d68c192018-12-13 15:52:59 +0900374 * Configures the flow rule which is for using VXLAN/GRE to tag the packet
Jian Liea1b9662018-03-02 18:07:32 +0900375 * based on the in_port number of a virtual instance.
Jian Li5c09e212018-10-24 18:23:58 +0900376 * Note that this rule will be inserted in vTag table.
Jian Liea1b9662018-03-02 18:07:32 +0900377 *
378 * @param instPort instance port object
379 * @param install install flag, add the rule if true, remove it otherwise
380 */
Jian Li5c09e212018-10-24 18:23:58 +0900381 private void setTunnelTagFlowRules(InstancePort instPort,
382 short ethType,
383 boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900384 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li5c09e212018-10-24 18:23:58 +0900385 .matchEthType(ethType)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900386 .matchInPort(instPort.portNumber())
387 .build();
388
Jian Li28ec77f2018-10-31 07:07:25 +0900389 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
390 .setTunnelId(getVni(instPort));
sangho1aaa7882017-05-31 13:22:47 +0900391
sanghoe6457a32017-08-24 14:31:19 +0900392
Jian Li28ec77f2018-10-31 07:07:25 +0900393 if (ethType == Ethernet.TYPE_ARP) {
394 tBuilder.transition(ARP_TABLE);
395 } else if (ethType == Ethernet.TYPE_IPV4) {
Jian Li1e9cb732018-11-25 23:17:21 +0900396 tBuilder.transition(ACL_EGRESS_TABLE);
sanghoe6457a32017-08-24 14:31:19 +0900397 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900398
sanghodc375372017-06-08 10:41:30 +0900399 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900400 appId,
401 instPort.deviceId(),
402 selector,
Jian Li28ec77f2018-10-31 07:07:25 +0900403 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900404 PRIORITY_TUNNEL_TAG_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900405 VTAG_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900406 install);
407 }
408
Jian Li5c09e212018-10-24 18:23:58 +0900409 private void setVlanTagIpFlowRules(InstancePort instPort, boolean install) {
410 setVlanTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
411 }
412
413 private void setVlanTagArpFlowRules(InstancePort instPort, boolean install) {
414 setVlanTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
415 }
416
Jian Liea1b9662018-03-02 18:07:32 +0900417 /**
418 * Configures the flow rule which is for using VLAN to tag the packet
419 * based on the in_port number of a virtual instance.
Jian Li5c09e212018-10-24 18:23:58 +0900420 * Note that this rule will be inserted in vTag table.
Jian Liea1b9662018-03-02 18:07:32 +0900421 *
422 * @param instPort instance port object
423 * @param install install flag, add the rule if true, remove it otherwise
424 */
Jian Li5c09e212018-10-24 18:23:58 +0900425 private void setVlanTagFlowRules(InstancePort instPort,
426 short ethType,
427 boolean install) {
daniel parka792cf72017-04-14 16:25:35 +0900428 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li5c09e212018-10-24 18:23:58 +0900429 .matchEthType(ethType)
daniel parka792cf72017-04-14 16:25:35 +0900430 .matchInPort(instPort.portNumber())
431 .build();
432
Daniel Park8a9220f2018-11-19 18:58:35 +0900433 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
daniel parka792cf72017-04-14 16:25:35 +0900434 .pushVlan()
Daniel Park8a9220f2018-11-19 18:58:35 +0900435 .setVlanId(getVlanId(instPort));
436
437 if (ethType == Ethernet.TYPE_ARP) {
438 tBuilder.transition(ARP_TABLE);
439 } else if (ethType == Ethernet.TYPE_IPV4) {
Jian Li1e9cb732018-11-25 23:17:21 +0900440 tBuilder.transition(ACL_EGRESS_TABLE);
Daniel Park8a9220f2018-11-19 18:58:35 +0900441 }
daniel parka792cf72017-04-14 16:25:35 +0900442
sanghodc375372017-06-08 10:41:30 +0900443 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900444 appId,
445 instPort.deviceId(),
446 selector,
Daniel Park8a9220f2018-11-19 18:58:35 +0900447 tBuilder.build(),
daniel parka792cf72017-04-14 16:25:35 +0900448 PRIORITY_TUNNEL_TAG_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900449 VTAG_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900450 install);
daniel parka792cf72017-04-14 16:25:35 +0900451 }
452
Jian Li91be8cd2018-07-22 00:44:46 +0900453 private void setNetworkBlockRules(Network network, boolean install) {
Frank Wangf9571662017-06-06 18:01:29 +0800454
SONA Project6bc5c4a2018-12-14 23:49:52 +0900455 Type type = osNetworkService.networkType(network.getId());
Jian Li91be8cd2018-07-22 00:44:46 +0900456
457 // TODO: we block a network traffic by referring to segment ID for now
458 // we might need to find a better way to block the traffic of a network
Jian Li2d68c192018-12-13 15:52:59 +0900459 // in case the segment ID is overlapped in different types network (VXLAN, GRE, VLAN)
Jian Li91be8cd2018-07-22 00:44:46 +0900460 switch (type) {
461 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900462 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900463 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900464 setNetworkBlockRulesForTunnel(network.getProviderSegID(), install);
Jian Li91be8cd2018-07-22 00:44:46 +0900465 break;
466 case VLAN:
467 setNetworkBlockRulesForVlan(network.getProviderSegID(), install);
468 break;
469 case FLAT:
470 // TODO: need to find a way to block flat typed network
471 break;
472 default:
473 break;
Frank Wangf9571662017-06-06 18:01:29 +0800474 }
Jian Li91be8cd2018-07-22 00:44:46 +0900475 }
476
Jian Li2d68c192018-12-13 15:52:59 +0900477 private void setNetworkBlockRulesForTunnel(String segmentId, boolean install) {
Jian Li91be8cd2018-07-22 00:44:46 +0900478 TrafficSelector selector = DefaultTrafficSelector.builder()
479 .matchTunnelId(Long.valueOf(segmentId))
480 .build();
Frank Wangf9571662017-06-06 18:01:29 +0800481
482 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
483 .drop()
484 .build();
485
Jian Li91be8cd2018-07-22 00:44:46 +0900486 osNodeService.completeNodes(COMPUTE)
Jian Liea1b9662018-03-02 18:07:32 +0900487 .forEach(osNode ->
Frank Wangf9571662017-06-06 18:01:29 +0800488 osFlowRuleService.setRule(
Jian Li91be8cd2018-07-22 00:44:46 +0900489 appId,
490 osNode.intgBridge(),
491 selector,
492 treatment,
493 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900494 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900495 install)
Jian Liea1b9662018-03-02 18:07:32 +0900496 );
Frank Wangf9571662017-06-06 18:01:29 +0800497 }
498
Jian Li91be8cd2018-07-22 00:44:46 +0900499 private void setNetworkBlockRulesForVlan(String segmentId, boolean install) {
Frank Wangf9571662017-06-06 18:01:29 +0800500 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li91be8cd2018-07-22 00:44:46 +0900501 .matchTunnelId(Long.valueOf(segmentId))
502 .build();
503
504 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
505 .drop()
506 .build();
507
508 osNodeService.completeNodes(COMPUTE)
509 .forEach(osNode ->
510 osFlowRuleService.setRule(
511 appId,
512 osNode.intgBridge(),
513 selector,
514 treatment,
515 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900516 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900517 install)
518 );
519 }
520
521 private void setPortBlockRules(InstancePort instPort, boolean install) {
522 TrafficSelector selector = DefaultTrafficSelector.builder()
523 .matchInPort(instPort.portNumber())
Frank Wangf9571662017-06-06 18:01:29 +0800524 .build();
525
526 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
527 .drop()
528 .build();
529
530 osFlowRuleService.setRule(
531 appId,
Jian Li91be8cd2018-07-22 00:44:46 +0900532 instPort.deviceId(),
Frank Wangf9571662017-06-06 18:01:29 +0800533 selector,
534 treatment,
535 PRIORITY_ADMIN_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900536 VTAG_TABLE,
Frank Wangf9571662017-06-06 18:01:29 +0800537 install);
538 }
539
Jian Liea1b9662018-03-02 18:07:32 +0900540 /**
541 * Obtains the VLAN ID from the given instance port.
542 *
543 * @param instPort instance port object
544 * @return VLAN ID
545 */
daniel parka792cf72017-04-14 16:25:35 +0900546 private VlanId getVlanId(InstancePort instPort) {
547 Network osNet = osNetworkService.network(instPort.networkId());
548
549 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900550 final String error =
551 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900552 instPort, osNet == null ? STR_NONE : osNet.getName());
daniel parka792cf72017-04-14 16:25:35 +0900553 throw new IllegalStateException(error);
554 }
555
556 return VlanId.vlanId(osNet.getProviderSegID());
557 }
558
Jian Liea1b9662018-03-02 18:07:32 +0900559 /**
560 * Obtains the VNI from the given instance port.
561 *
562 * @param instPort instance port object
Jian Li2d68c192018-12-13 15:52:59 +0900563 * @return Virtual Network Identifier (VNI)
Jian Liea1b9662018-03-02 18:07:32 +0900564 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900565 private Long getVni(InstancePort instPort) {
566 Network osNet = osNetworkService.network(instPort.networkId());
567 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900568 final String error =
569 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900570 instPort, osNet == null ? STR_NONE : osNet.getName());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900571 throw new IllegalStateException(error);
572 }
573 return Long.valueOf(osNet.getProviderSegID());
574 }
575
Jian Li5c09e212018-10-24 18:23:58 +0900576 private String getArpMode() {
Jian Li34220ea2018-11-14 01:30:24 +0900577 Set<ConfigProperty> properties =
578 configService.getProperties(OpenstackSwitchingArpHandler.class.getName());
Jian Li5c09e212018-10-24 18:23:58 +0900579 return getPropertyValue(properties, ARP_MODE);
580 }
581
Jian Liea1b9662018-03-02 18:07:32 +0900582 /**
583 * An internal instance port listener which listens the port events generated
584 * from VM. The corresponding L2 forwarding rules will be generated and
585 * inserted to integration bridge only if a new VM port is detected. If the
586 * existing detected VM port is removed due to VM purge, we will remove the
587 * corresponding L2 forwarding to as well for the sake of resource saving.
588 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900589 private class InternalInstancePortListener implements InstancePortListener {
590
Jian Li34220ea2018-11-14 01:30:24 +0900591 private boolean isRelevantHelper(InstancePortEvent event) {
592 return mastershipService.isLocalMaster(event.subject().deviceId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900593 }
594
595 @Override
596 public void event(InstancePortEvent event) {
597 InstancePort instPort = event.subject();
Jian Li9a921b42018-06-18 02:44:50 +0900598
Hyunsun Moon44aac662017-02-18 02:07:01 +0900599 switch (event.type()) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900600 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +0900601 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li34220ea2018-11-14 01:30:24 +0900602 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li46b74002018-07-15 18:39:08 +0900603 case OPENSTACK_INSTANCE_RESTARTED:
Jian Li4d138702018-11-27 17:25:28 +0900604 eventExecutor.execute(() ->
605 processInstanceDetection(event, instPort));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900606 break;
Jian Li46b74002018-07-15 18:39:08 +0900607 case OPENSTACK_INSTANCE_TERMINATED:
Jian Li4d138702018-11-27 17:25:28 +0900608 eventExecutor.execute(() ->
609 processInstanceTermination(event, instPort));
Jian Li46b74002018-07-15 18:39:08 +0900610 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900611 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +0900612 eventExecutor.execute(() ->
613 processInstanceRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +0900614 break;
615 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +0900616 eventExecutor.execute(() ->
617 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +0900618 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900619 default:
620 break;
621 }
622 }
623
Jian Li4d138702018-11-27 17:25:28 +0900624 private void processInstanceDetection(InstancePortEvent event,
625 InstancePort instPort) {
626 if (!isRelevantHelper(event)) {
627 return;
628 }
629
630 if (event.type() == OPENSTACK_INSTANCE_MIGRATION_STARTED) {
631 log.info("SwitchingHandler: Migration started at MAC:{} IP:{}",
632 instPort.macAddress(),
633 instPort.ipAddress());
634 } else {
635 log.info("SwitchingHandler: Instance port detected MAC:{} IP:{}",
636 instPort.macAddress(),
637 instPort.ipAddress());
638 }
639
640 instPortDetected(instPort);
641
642 Port osPort = osNetworkService.port(instPort.portId());
643
644 if (osPort != null) {
645 setPortBlockRules(instPort, !osPort.isAdminStateUp());
646 }
647 }
648
649 private void processInstanceTermination(InstancePortEvent event,
650 InstancePort instPort) {
651 if (!isRelevantHelper(event)) {
652 return;
653 }
654
655 log.info("SwitchingHandler: Instance port terminated MAC:{} IP:{}",
656 instPort.macAddress(),
657 instPort.ipAddress());
658
659 removeVportRules(instPort);
660 }
661
662 private void processInstanceRemoval(InstancePortEvent event,
663 InstancePort instPort) {
664 if (!isRelevantHelper(event)) {
665 return;
666 }
667
668 log.info("SwitchingHandler: Instance port vanished MAC:{} IP:{}",
669 instPort.macAddress(),
670 instPort.ipAddress());
671
672 instPortRemoved(instPort);
673
674 Port osPort = osNetworkService.port(instPort.portId());
675
676 if (osPort != null) {
677 setPortBlockRules(instPort, false);
678 }
679 }
680
681 private void processInstanceMigrationEnd(InstancePortEvent event,
682 InstancePort instPort) {
683 if (!isRelevantHelper(event)) {
684 return;
685 }
686
687 log.info("SwitchingHandler: Migration finished for MAC:{} IP:{}",
688 instPort.macAddress(),
689 instPort.ipAddress());
690
691 InstancePort revisedInstPort = swapStaleLocation(instPort);
692
693 removeVportRules(revisedInstPort);
694 }
695
696 /**
697 * Configures L2 forwarding rules.
Jian Li621f73c2018-12-15 01:49:22 +0900698 * Currently, SONA supports Flat, VXLAN, GRE, GENEVE and VLAN modes.
Jian Li4d138702018-11-27 17:25:28 +0900699 *
700 * @param instPort instance port object
701 * @param install install flag, add the rule if true, remove it otherwise
702 */
703 private void setNetworkRules(InstancePort instPort, boolean install) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900704 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900705
706 switch (type) {
707 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900708 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900709 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900710 setNetworkRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900711 break;
712 case VLAN:
713 setNetworkRulesForVlan(instPort, install);
714 break;
715 case FLAT:
716 setNetworkRulesForFlat(instPort, install);
717 break;
718 default:
719 log.warn("Unsupported network tunnel type {}", type.name());
720 break;
721 }
722 }
723
Jian Li2d68c192018-12-13 15:52:59 +0900724 private void setNetworkRulesForTunnel(InstancePort instPort, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900725 setTunnelTagIpFlowRules(instPort, install);
Jian Li2d68c192018-12-13 15:52:59 +0900726 setForwardingRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900727
728 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
729 setTunnelTagArpFlowRules(instPort, install);
730 }
731 }
732
733 private void setNetworkRulesForVlan(InstancePort instPort, boolean install) {
734 setVlanTagIpFlowRules(instPort, install);
735 setForwardingRulesForVlan(instPort, install);
736
737 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
738 setVlanTagArpFlowRules(instPort, install);
739 }
740 }
741
742 private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
Jian Lidaa91152019-09-08 00:35:11 +0900743 setJumpRulesForFlat(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900744 setDownstreamRulesForFlat(instPort, install);
745 setUpstreamRulesForFlat(instPort, install);
746 }
747
748 /**
749 * Removes virtual port related flow rules.
750 *
751 * @param instPort instance port
752 */
753 private void removeVportRules(InstancePort instPort) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900754 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900755
756 switch (type) {
757 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900758 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900759 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900760 removeVportRulesForTunnel(instPort);
Jian Li4d138702018-11-27 17:25:28 +0900761 break;
762 case VLAN:
763 removeVportRulesForVlan(instPort);
764 break;
765 case FLAT:
766 removeVportRulesForFlat(instPort);
767 break;
768 default:
769 log.warn("Unsupported network type {}", type.name());
770 break;
771 }
772 }
773
Jian Li2d68c192018-12-13 15:52:59 +0900774 private void removeVportRulesForTunnel(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +0900775 setTunnelTagIpFlowRules(instPort, false);
776
777 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
778 setTunnelTagArpFlowRules(instPort, false);
779 }
780 }
781
782 private void removeVportRulesForVlan(InstancePort instPort) {
783 setVlanTagIpFlowRules(instPort, false);
784
785 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
786 setVlanTagArpFlowRules(instPort, false);
787 }
788 }
789
790 private void removeVportRulesForFlat(InstancePort instPort) {
Jian Lidaa91152019-09-08 00:35:11 +0900791 setJumpRulesForFlat(instPort, false);
Jian Li4d138702018-11-27 17:25:28 +0900792 setUpstreamRulesForFlat(instPort, false);
793 setDownstreamRulesForFlat(instPort, false);
794 }
795
Hyunsun Moon44aac662017-02-18 02:07:01 +0900796 private void instPortDetected(InstancePort instPort) {
797 setNetworkRules(instPort, true);
798 // TODO add something else if needed
799 }
800
801 private void instPortRemoved(InstancePort instPort) {
802 setNetworkRules(instPort, false);
803 // TODO add something else if needed
804 }
805 }
Jian Li91be8cd2018-07-22 00:44:46 +0900806
807 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
808
809 @Override
810 public boolean isRelevant(OpenstackNetworkEvent event) {
Jian Li34220ea2018-11-14 01:30:24 +0900811 return event.subject() != null && event.port() != null;
812 }
Jian Li91be8cd2018-07-22 00:44:46 +0900813
Jian Li34220ea2018-11-14 01:30:24 +0900814 private boolean isRelevantHelper() {
815 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Jian Li91be8cd2018-07-22 00:44:46 +0900816 }
817
818 @Override
819 public void event(OpenstackNetworkEvent event) {
Jian Li91be8cd2018-07-22 00:44:46 +0900820 switch (event.type()) {
821 case OPENSTACK_NETWORK_CREATED:
822 case OPENSTACK_NETWORK_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900823 eventExecutor.execute(() -> processNetworkAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900824 break;
Jian Li15a3c2e2020-02-25 03:30:20 +0900825 case OPENSTACK_NETWORK_PRE_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900826 eventExecutor.execute(() -> processNetworkRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900827 break;
828 case OPENSTACK_PORT_CREATED:
829 case OPENSTACK_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900830 eventExecutor.execute(() -> processPortAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900831 break;
832 case OPENSTACK_PORT_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900833 eventExecutor.execute(() -> processPortRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900834 break;
835 default:
836 break;
837 }
838 }
Jian Li4d138702018-11-27 17:25:28 +0900839
840 private void processNetworkAddition(OpenstackNetworkEvent event) {
841 if (!isRelevantHelper()) {
842 return;
843 }
844
845 boolean isNwAdminStateUp = event.subject().isAdminStateUp();
846 setNetworkBlockRules(event.subject(), !isNwAdminStateUp);
847 }
848
849 private void processNetworkRemoval(OpenstackNetworkEvent event) {
850 if (!isRelevantHelper()) {
851 return;
852 }
853
854 setNetworkBlockRules(event.subject(), false);
855 }
856
857 private void processPortAddition(OpenstackNetworkEvent event) {
858 if (!isRelevantHelper()) {
859 return;
860 }
861
862 boolean isPortAdminStateUp = event.port().isAdminStateUp();
863 String portId = event.port().getId();
864 InstancePort instPort = instancePortService.instancePort(portId);
865 if (instPort != null) {
866 setPortBlockRules(instPort, !isPortAdminStateUp);
867 }
868 }
869
870 private void processPortRemoval(OpenstackNetworkEvent event) {
871 if (!isRelevantHelper()) {
872 return;
873 }
874
875 String portId = event.port().getId();
876 InstancePort instPort = instancePortService.instancePort(portId);
877 if (instPort != null) {
878 setPortBlockRules(instPort, false);
879 }
880 }
Jian Li91be8cd2018-07-22 00:44:46 +0900881 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900882}