blob: 79883751bd60599f5545c8125605fcfdff1ac469 [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;
Jian Li91be8cd2018-07-22 00:44:46 +090042import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
43import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090045import org.onosproject.openstacknode.api.OpenstackNode;
46import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090047import org.openstack4j.model.network.Network;
Frank Wangf9571662017-06-06 18:01:29 +080048import org.openstack4j.model.network.NetworkType;
49import 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 Li1e9cb732018-11-25 23:17:21 +090063import static org.onosproject.openstacknetworking.api.Constants.ACL_EGRESS_TABLE;
Jian Li5c09e212018-10-24 18:23:58 +090064import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
65import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
66import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
Jian Li70a2c3f2018-04-13 17:26:31 +090067import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
sanghodc375372017-06-08 10:41:30 +090068import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
69import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Frank Wangf9571662017-06-06 18:01:29 +080070import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
Daniel Parkd1b14d32018-06-12 16:10:28 +090071import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_DOWNSTREAM_RULE;
72import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE;
73import 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 Liec5c32b2018-07-13 14:28:58 +090081import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
Jian Li2d68c192018-12-13 15:52:59 +090082import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
Jian Li26949762018-03-30 15:46:37 +090083import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090084import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
Hyunsun Moon44aac662017-02-18 02:07:01 +090085import static org.slf4j.LoggerFactory.getLogger;
86
87
88/**
89 * Populates switching flow rules on OVS for the basic connectivity among the
90 * virtual instances in the same network.
91 */
92@Component(immediate = true)
Jian Li4d138702018-11-27 17:25:28 +090093public class OpenstackSwitchingHandler {
Hyunsun Moon44aac662017-02-18 02:07:01 +090094
95 private final Logger log = getLogger(getClass());
96
Jian Li5c09e212018-10-24 18:23:58 +090097 private static final String ARP_MODE = "arpMode";
Jian Li4d138702018-11-27 17:25:28 +090098 private static final String ERR_SET_FLOWS_VNI = "Failed to set flows for " +
99 "%s: Failed to get VNI for %s";
100 private static final String STR_NONE = "<none>";
Hyunsun Moon44aac662017-02-18 02:07:01 +0900101
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900103 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900104
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900106 protected MastershipService mastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900107
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900109 protected DeviceService deviceService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900110
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700111 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li91be8cd2018-07-22 00:44:46 +0900112 protected DriverService driverService;
113
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700114 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li91be8cd2018-07-22 00:44:46 +0900115 protected ClusterService clusterService;
116
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700117 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li5c09e212018-10-24 18:23:58 +0900118 protected ComponentConfigService configService;
119
Ray Milkey956bb162018-10-26 10:53:44 -0700120 @Reference(cardinality = ReferenceCardinality.MANDATORY)
121
Jian Li91be8cd2018-07-22 00:44:46 +0900122 protected LeadershipService leadershipService;
123
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700124 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900125 protected OpenstackFlowRuleService osFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900126
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700127 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900128 protected InstancePortService instancePortService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900129
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700130 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900131 protected OpenstackNetworkService osNetworkService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900132
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700133 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Liea1b9662018-03-02 18:07:32 +0900134 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900135
136 private final ExecutorService eventExecutor = newSingleThreadExecutor(
137 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
138 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Jian Li91be8cd2018-07-22 00:44:46 +0900139 private final InternalOpenstackNetworkListener osNetworkListener =
140 new InternalOpenstackNetworkListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900141 private ApplicationId appId;
Jian Li91be8cd2018-07-22 00:44:46 +0900142 private NodeId localNodeId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900143
144 @Activate
Jian Li4d138702018-11-27 17:25:28 +0900145 protected void activate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900146 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
Jian Li91be8cd2018-07-22 00:44:46 +0900147 localNodeId = clusterService.getLocalNode().id();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900148 instancePortService.addListener(instancePortListener);
Jian Li91be8cd2018-07-22 00:44:46 +0900149 osNetworkService.addListener(osNetworkListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900150
151 log.info("Started");
152 }
153
154 @Deactivate
Jian Li4d138702018-11-27 17:25:28 +0900155 protected void deactivate() {
Jian Li91be8cd2018-07-22 00:44:46 +0900156 osNetworkService.removeListener(osNetworkListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900157 instancePortService.removeListener(instancePortListener);
158 eventExecutor.shutdown();
159
160 log.info("Stopped");
161 }
162
Jian Li70a2c3f2018-04-13 17:26:31 +0900163 private void setFlatJumpRules(InstancePort port, boolean install) {
164 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
165 selector.matchInPort(port.portNumber());
166
167 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
Jian Li960ae512018-07-03 22:50:56 +0900168 treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
Jian Li70a2c3f2018-04-13 17:26:31 +0900169
170 osFlowRuleService.setRule(
171 appId,
172 port.deviceId(),
173 selector.build(),
174 treatment.build(),
Daniel Parkd1b14d32018-06-12 16:10:28 +0900175 PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
Jian Li5c09e212018-10-24 18:23:58 +0900176 DHCP_TABLE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900177 install);
178
179 Network network = osNetworkService.network(port.networkId());
180
181 if (network == null) {
182 log.warn("The network does not exist");
183 return;
184 }
Jian Li70a2c3f2018-04-13 17:26:31 +0900185 PortNumber portNumber = osNodeService.node(port.deviceId())
186 .phyIntfPortNum(network.getProviderPhyNet());
187
188 if (portNumber == null) {
189 log.warn("The port number does not exist");
190 return;
191 }
192
193 selector = DefaultTrafficSelector.builder();
Daniel Parkd1b14d32018-06-12 16:10:28 +0900194 selector.matchInPort(portNumber)
195 .matchEthType(Ethernet.TYPE_IPV4)
196 .matchIPDst(port.ipAddress().toIpPrefix());
Jian Li70a2c3f2018-04-13 17:26:31 +0900197
198 osFlowRuleService.setRule(
199 appId,
200 port.deviceId(),
201 selector.build(),
202 treatment.build(),
Daniel Parkd1b14d32018-06-12 16:10:28 +0900203 PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
Jian Li5c09e212018-10-24 18:23:58 +0900204 DHCP_TABLE,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900205 install);
206
207 selector = DefaultTrafficSelector.builder();
208 selector.matchInPort(portNumber)
209 .matchEthType(Ethernet.TYPE_ARP)
210 .matchArpTpa(port.ipAddress().getIp4Address());
211
212 osFlowRuleService.setRule(
213 appId,
214 port.deviceId(),
215 selector.build(),
216 treatment.build(),
217 PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
Jian Li5c09e212018-10-24 18:23:58 +0900218 DHCP_TABLE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900219 install);
220 }
221
Jian Li9a921b42018-06-18 02:44:50 +0900222 private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
daniel park796c2eb2018-03-22 17:01:51 +0900223 TrafficSelector selector = DefaultTrafficSelector.builder()
224 .matchEthType(Ethernet.TYPE_IPV4)
225 .matchIPDst(instPort.ipAddress().toIpPrefix())
226 .build();
227 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
228 .setOutput(instPort.portNumber())
229 .build();
230
231 osFlowRuleService.setRule(
232 appId,
233 instPort.deviceId(),
234 selector,
235 treatment,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900236 PRIORITY_FLAT_DOWNSTREAM_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900237 FLAT_TABLE,
daniel park796c2eb2018-03-22 17:01:51 +0900238 install);
239
240 selector = DefaultTrafficSelector.builder()
241 .matchEthType(Ethernet.TYPE_ARP)
242 .matchArpTpa(instPort.ipAddress().getIp4Address())
243 .build();
244
245 osFlowRuleService.setRule(
246 appId,
247 instPort.deviceId(),
248 selector,
249 treatment,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900250 PRIORITY_FLAT_DOWNSTREAM_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900251 FLAT_TABLE,
daniel park796c2eb2018-03-22 17:01:51 +0900252 install);
253 }
254
Jian Li9a921b42018-06-18 02:44:50 +0900255 private void setUpstreamRulesForFlat(InstancePort instPort, boolean install) {
daniel park796c2eb2018-03-22 17:01:51 +0900256 TrafficSelector selector = DefaultTrafficSelector.builder()
257 .matchInPort(instPort.portNumber())
258 .build();
259
260 Network network = osNetworkService.network(instPort.networkId());
261
262 if (network == null) {
263 log.warn("The network does not exist");
264 return;
265 }
266
267 PortNumber portNumber = osNodeService.node(instPort.deviceId())
268 .phyIntfPortNum(network.getProviderPhyNet());
269
270 if (portNumber == null) {
271 log.warn("The port number does not exist");
272 return;
273 }
274
275 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
276 .setOutput(portNumber)
277 .build();
278
279 osFlowRuleService.setRule(
280 appId,
281 instPort.deviceId(),
282 selector,
283 treatment,
Daniel Parkd1b14d32018-06-12 16:10:28 +0900284 PRIORITY_FLAT_UPSTREAM_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900285 FLAT_TABLE,
daniel park796c2eb2018-03-22 17:01:51 +0900286 install);
287 }
288
Jian Liea1b9662018-03-02 18:07:32 +0900289 /**
290 * Configures the flow rules which are used for L2 packet switching.
291 * Note that these rules will be inserted in switching table (table 5).
292 *
293 * @param instPort instance port object
294 * @param install install flag, add the rule if true, remove it otherwise
295 */
Jian Li2d68c192018-12-13 15:52:59 +0900296 private void setForwardingRulesForTunnel(InstancePort instPort, boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900297 // switching rules for the instPorts in the same node
298 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900299 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900300 .matchEthType(Ethernet.TYPE_IPV4)
301 .matchIPDst(instPort.ipAddress().toIpPrefix())
302 .matchTunnelId(getVni(instPort))
303 .build();
304
305 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900306 // TODO: this might not be necessary for the VMs located in the same subnet
Hyunsun Moon44aac662017-02-18 02:07:01 +0900307 .setEthDst(instPort.macAddress())
308 .setOutput(instPort.portNumber())
309 .build();
310
sanghodc375372017-06-08 10:41:30 +0900311 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900312 appId,
313 instPort.deviceId(),
314 selector,
315 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900316 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900317 FORWARDING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900318 install);
319
320 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900321 OpenstackNode localNode = osNodeService.node(instPort.deviceId());
322 if (localNode == null) {
323 final String error = String.format("Cannot find openstack node for %s",
324 instPort.deviceId());
325 throw new IllegalStateException(error);
326 }
327 osNodeService.completeNodes(COMPUTE).stream()
328 .filter(remoteNode -> !remoteNode.intgBridge().equals(localNode.intgBridge()))
329 .forEach(remoteNode -> {
Jian Li2d68c192018-12-13 15:52:59 +0900330 PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
331 osNetworkService, remoteNode);
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900332 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
333 .extension(buildExtension(
334 deviceService,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900335 remoteNode.intgBridge(),
336 localNode.dataIp().getIp4Address()),
337 remoteNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900338 .setOutput(portNum)
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900339 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900340
sanghodc375372017-06-08 10:41:30 +0900341 osFlowRuleService.setRule(
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900342 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900343 remoteNode.intgBridge(),
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900344 selector,
345 treatmentToRemote,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900346 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900347 FORWARDING_TABLE,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900348 install);
349 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900350 }
351
Jian Liea1b9662018-03-02 18:07:32 +0900352 /**
353 * Configures the flow rules which are used for L2 VLAN packet switching.
354 * Note that these rules will be inserted in switching table (table 5).
355 *
356 * @param instPort instance port object
357 * @param install install flag, add the rule if true, remove it otherwise
358 */
daniel parka792cf72017-04-14 16:25:35 +0900359 private void setForwardingRulesForVlan(InstancePort instPort, boolean install) {
360 // switching rules for the instPorts in the same node
361 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900362 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900363 .matchEthType(Ethernet.TYPE_IPV4)
364 .matchIPDst(instPort.ipAddress().toIpPrefix())
365 .matchVlanId(getVlanId(instPort))
366 .build();
367
368 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
369 .popVlan()
Jian Liea1b9662018-03-02 18:07:32 +0900370 // TODO: this might not be necessary for the VMs located in the same subnet
daniel parka792cf72017-04-14 16:25:35 +0900371 .setEthDst(instPort.macAddress())
372 .setOutput(instPort.portNumber())
373 .build();
374
sanghodc375372017-06-08 10:41:30 +0900375 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900376 appId,
377 instPort.deviceId(),
378 selector,
379 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900380 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900381 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900382 install);
383
384 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900385 osNodeService.completeNodes(COMPUTE).stream()
386 .filter(remoteNode -> !remoteNode.intgBridge().equals(instPort.deviceId()) &&
387 remoteNode.vlanIntf() != null)
388 .forEach(remoteNode -> {
daniel parka792cf72017-04-14 16:25:35 +0900389 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
Daniel Parkc64b4c62018-05-09 18:13:39 +0900390 .setEthDst(instPort.macAddress())
391 .setOutput(remoteNode.vlanPortNum())
392 .build();
daniel parka792cf72017-04-14 16:25:35 +0900393
sanghodc375372017-06-08 10:41:30 +0900394 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900395 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900396 remoteNode.intgBridge(),
daniel parka792cf72017-04-14 16:25:35 +0900397 selector,
398 treatmentToRemote,
daniel parka792cf72017-04-14 16:25:35 +0900399 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900400 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900401 install);
402 });
daniel parka792cf72017-04-14 16:25:35 +0900403 }
404
Jian Li5c09e212018-10-24 18:23:58 +0900405 private void setTunnelTagArpFlowRules(InstancePort instPort, boolean install) {
406 setTunnelTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
407 }
408
409 private void setTunnelTagIpFlowRules(InstancePort instPort, boolean install) {
410 setTunnelTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
411 }
412
Jian Liea1b9662018-03-02 18:07:32 +0900413 /**
Jian Li2d68c192018-12-13 15:52:59 +0900414 * Configures the flow rule which is for using VXLAN/GRE to tag the packet
Jian Liea1b9662018-03-02 18:07:32 +0900415 * based on the in_port number of a virtual instance.
Jian Li5c09e212018-10-24 18:23:58 +0900416 * Note that this rule will be inserted in vTag table.
Jian Liea1b9662018-03-02 18:07:32 +0900417 *
418 * @param instPort instance port object
419 * @param install install flag, add the rule if true, remove it otherwise
420 */
Jian Li5c09e212018-10-24 18:23:58 +0900421 private void setTunnelTagFlowRules(InstancePort instPort,
422 short ethType,
423 boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900424 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li5c09e212018-10-24 18:23:58 +0900425 .matchEthType(ethType)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900426 .matchInPort(instPort.portNumber())
427 .build();
428
Jian Li28ec77f2018-10-31 07:07:25 +0900429 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
430 .setTunnelId(getVni(instPort));
sangho1aaa7882017-05-31 13:22:47 +0900431
sanghoe6457a32017-08-24 14:31:19 +0900432
Jian Li28ec77f2018-10-31 07:07:25 +0900433 if (ethType == Ethernet.TYPE_ARP) {
434 tBuilder.transition(ARP_TABLE);
435 } else if (ethType == Ethernet.TYPE_IPV4) {
Jian Li1e9cb732018-11-25 23:17:21 +0900436 tBuilder.transition(ACL_EGRESS_TABLE);
sanghoe6457a32017-08-24 14:31:19 +0900437 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900438
sanghodc375372017-06-08 10:41:30 +0900439 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900440 appId,
441 instPort.deviceId(),
442 selector,
Jian Li28ec77f2018-10-31 07:07:25 +0900443 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900444 PRIORITY_TUNNEL_TAG_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900445 VTAG_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900446 install);
447 }
448
Jian Li5c09e212018-10-24 18:23:58 +0900449 private void setVlanTagIpFlowRules(InstancePort instPort, boolean install) {
450 setVlanTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
451 }
452
453 private void setVlanTagArpFlowRules(InstancePort instPort, boolean install) {
454 setVlanTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
455 }
456
Jian Liea1b9662018-03-02 18:07:32 +0900457 /**
458 * Configures the flow rule which is for using VLAN to tag the packet
459 * based on the in_port number of a virtual instance.
Jian Li5c09e212018-10-24 18:23:58 +0900460 * Note that this rule will be inserted in vTag table.
Jian Liea1b9662018-03-02 18:07:32 +0900461 *
462 * @param instPort instance port object
463 * @param install install flag, add the rule if true, remove it otherwise
464 */
Jian Li5c09e212018-10-24 18:23:58 +0900465 private void setVlanTagFlowRules(InstancePort instPort,
466 short ethType,
467 boolean install) {
daniel parka792cf72017-04-14 16:25:35 +0900468 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li5c09e212018-10-24 18:23:58 +0900469 .matchEthType(ethType)
daniel parka792cf72017-04-14 16:25:35 +0900470 .matchInPort(instPort.portNumber())
471 .build();
472
Daniel Park8a9220f2018-11-19 18:58:35 +0900473 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
daniel parka792cf72017-04-14 16:25:35 +0900474 .pushVlan()
Daniel Park8a9220f2018-11-19 18:58:35 +0900475 .setVlanId(getVlanId(instPort));
476
477 if (ethType == Ethernet.TYPE_ARP) {
478 tBuilder.transition(ARP_TABLE);
479 } else if (ethType == Ethernet.TYPE_IPV4) {
Jian Li1e9cb732018-11-25 23:17:21 +0900480 tBuilder.transition(ACL_EGRESS_TABLE);
Daniel Park8a9220f2018-11-19 18:58:35 +0900481 }
daniel parka792cf72017-04-14 16:25:35 +0900482
sanghodc375372017-06-08 10:41:30 +0900483 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900484 appId,
485 instPort.deviceId(),
486 selector,
Daniel Park8a9220f2018-11-19 18:58:35 +0900487 tBuilder.build(),
daniel parka792cf72017-04-14 16:25:35 +0900488 PRIORITY_TUNNEL_TAG_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900489 VTAG_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900490 install);
daniel parka792cf72017-04-14 16:25:35 +0900491 }
492
Jian Li91be8cd2018-07-22 00:44:46 +0900493 private void setNetworkBlockRules(Network network, boolean install) {
Frank Wangf9571662017-06-06 18:01:29 +0800494
Jian Li91be8cd2018-07-22 00:44:46 +0900495 NetworkType type = network.getNetworkType();
496
497 // TODO: we block a network traffic by referring to segment ID for now
498 // we might need to find a better way to block the traffic of a network
Jian Li2d68c192018-12-13 15:52:59 +0900499 // in case the segment ID is overlapped in different types network (VXLAN, GRE, VLAN)
Jian Li91be8cd2018-07-22 00:44:46 +0900500 switch (type) {
501 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900502 case GRE:
503 setNetworkBlockRulesForTunnel(network.getProviderSegID(), install);
Jian Li91be8cd2018-07-22 00:44:46 +0900504 break;
505 case VLAN:
506 setNetworkBlockRulesForVlan(network.getProviderSegID(), install);
507 break;
508 case FLAT:
509 // TODO: need to find a way to block flat typed network
510 break;
511 default:
512 break;
Frank Wangf9571662017-06-06 18:01:29 +0800513 }
Jian Li91be8cd2018-07-22 00:44:46 +0900514 }
515
Jian Li2d68c192018-12-13 15:52:59 +0900516 private void setNetworkBlockRulesForTunnel(String segmentId, boolean install) {
Jian Li91be8cd2018-07-22 00:44:46 +0900517 TrafficSelector selector = DefaultTrafficSelector.builder()
518 .matchTunnelId(Long.valueOf(segmentId))
519 .build();
Frank Wangf9571662017-06-06 18:01:29 +0800520
521 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
522 .drop()
523 .build();
524
Jian Li91be8cd2018-07-22 00:44:46 +0900525 osNodeService.completeNodes(COMPUTE)
Jian Liea1b9662018-03-02 18:07:32 +0900526 .forEach(osNode ->
Frank Wangf9571662017-06-06 18:01:29 +0800527 osFlowRuleService.setRule(
Jian Li91be8cd2018-07-22 00:44:46 +0900528 appId,
529 osNode.intgBridge(),
530 selector,
531 treatment,
532 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900533 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900534 install)
Jian Liea1b9662018-03-02 18:07:32 +0900535 );
Frank Wangf9571662017-06-06 18:01:29 +0800536 }
537
Jian Li91be8cd2018-07-22 00:44:46 +0900538 private void setNetworkBlockRulesForVlan(String segmentId, boolean install) {
Frank Wangf9571662017-06-06 18:01:29 +0800539 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li91be8cd2018-07-22 00:44:46 +0900540 .matchTunnelId(Long.valueOf(segmentId))
541 .build();
542
543 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
544 .drop()
545 .build();
546
547 osNodeService.completeNodes(COMPUTE)
548 .forEach(osNode ->
549 osFlowRuleService.setRule(
550 appId,
551 osNode.intgBridge(),
552 selector,
553 treatment,
554 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900555 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900556 install)
557 );
558 }
559
560 private void setPortBlockRules(InstancePort instPort, boolean install) {
561 TrafficSelector selector = DefaultTrafficSelector.builder()
562 .matchInPort(instPort.portNumber())
Frank Wangf9571662017-06-06 18:01:29 +0800563 .build();
564
565 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
566 .drop()
567 .build();
568
569 osFlowRuleService.setRule(
570 appId,
Jian Li91be8cd2018-07-22 00:44:46 +0900571 instPort.deviceId(),
Frank Wangf9571662017-06-06 18:01:29 +0800572 selector,
573 treatment,
574 PRIORITY_ADMIN_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900575 VTAG_TABLE,
Frank Wangf9571662017-06-06 18:01:29 +0800576 install);
577 }
578
Jian Liea1b9662018-03-02 18:07:32 +0900579 /**
580 * Obtains the VLAN ID from the given instance port.
581 *
582 * @param instPort instance port object
583 * @return VLAN ID
584 */
daniel parka792cf72017-04-14 16:25:35 +0900585 private VlanId getVlanId(InstancePort instPort) {
586 Network osNet = osNetworkService.network(instPort.networkId());
587
588 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900589 final String error =
590 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900591 instPort, osNet == null ? STR_NONE : osNet.getName());
daniel parka792cf72017-04-14 16:25:35 +0900592 throw new IllegalStateException(error);
593 }
594
595 return VlanId.vlanId(osNet.getProviderSegID());
596 }
597
Jian Liea1b9662018-03-02 18:07:32 +0900598 /**
599 * Obtains the VNI from the given instance port.
600 *
601 * @param instPort instance port object
Jian Li2d68c192018-12-13 15:52:59 +0900602 * @return Virtual Network Identifier (VNI)
Jian Liea1b9662018-03-02 18:07:32 +0900603 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900604 private Long getVni(InstancePort instPort) {
605 Network osNet = osNetworkService.network(instPort.networkId());
606 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900607 final String error =
608 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900609 instPort, osNet == null ? STR_NONE : osNet.getName());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900610 throw new IllegalStateException(error);
611 }
612 return Long.valueOf(osNet.getProviderSegID());
613 }
614
Jian Li5c09e212018-10-24 18:23:58 +0900615 private String getArpMode() {
Jian Li34220ea2018-11-14 01:30:24 +0900616 Set<ConfigProperty> properties =
617 configService.getProperties(OpenstackSwitchingArpHandler.class.getName());
Jian Li5c09e212018-10-24 18:23:58 +0900618 return getPropertyValue(properties, ARP_MODE);
619 }
620
Jian Liea1b9662018-03-02 18:07:32 +0900621 /**
622 * An internal instance port listener which listens the port events generated
623 * from VM. The corresponding L2 forwarding rules will be generated and
624 * inserted to integration bridge only if a new VM port is detected. If the
625 * existing detected VM port is removed due to VM purge, we will remove the
626 * corresponding L2 forwarding to as well for the sake of resource saving.
627 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900628 private class InternalInstancePortListener implements InstancePortListener {
629
Jian Li34220ea2018-11-14 01:30:24 +0900630 private boolean isRelevantHelper(InstancePortEvent event) {
631 return mastershipService.isLocalMaster(event.subject().deviceId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900632 }
633
634 @Override
635 public void event(InstancePortEvent event) {
636 InstancePort instPort = event.subject();
Jian Li9a921b42018-06-18 02:44:50 +0900637
Hyunsun Moon44aac662017-02-18 02:07:01 +0900638 switch (event.type()) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900639 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +0900640 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li34220ea2018-11-14 01:30:24 +0900641 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li46b74002018-07-15 18:39:08 +0900642 case OPENSTACK_INSTANCE_RESTARTED:
Jian Li4d138702018-11-27 17:25:28 +0900643 eventExecutor.execute(() ->
644 processInstanceDetection(event, instPort));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900645 break;
Jian Li46b74002018-07-15 18:39:08 +0900646 case OPENSTACK_INSTANCE_TERMINATED:
Jian Li4d138702018-11-27 17:25:28 +0900647 eventExecutor.execute(() ->
648 processInstanceTermination(event, instPort));
Jian Li46b74002018-07-15 18:39:08 +0900649 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900650 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +0900651 eventExecutor.execute(() ->
652 processInstanceRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +0900653 break;
654 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +0900655 eventExecutor.execute(() ->
656 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +0900657 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900658 default:
659 break;
660 }
661 }
662
Jian Li4d138702018-11-27 17:25:28 +0900663 private void processInstanceDetection(InstancePortEvent event,
664 InstancePort instPort) {
665 if (!isRelevantHelper(event)) {
666 return;
667 }
668
669 if (event.type() == OPENSTACK_INSTANCE_MIGRATION_STARTED) {
670 log.info("SwitchingHandler: Migration started at MAC:{} IP:{}",
671 instPort.macAddress(),
672 instPort.ipAddress());
673 } else {
674 log.info("SwitchingHandler: Instance port detected MAC:{} IP:{}",
675 instPort.macAddress(),
676 instPort.ipAddress());
677 }
678
679 instPortDetected(instPort);
680
681 Port osPort = osNetworkService.port(instPort.portId());
682
683 if (osPort != null) {
684 setPortBlockRules(instPort, !osPort.isAdminStateUp());
685 }
686 }
687
688 private void processInstanceTermination(InstancePortEvent event,
689 InstancePort instPort) {
690 if (!isRelevantHelper(event)) {
691 return;
692 }
693
694 log.info("SwitchingHandler: Instance port terminated MAC:{} IP:{}",
695 instPort.macAddress(),
696 instPort.ipAddress());
697
698 removeVportRules(instPort);
699 }
700
701 private void processInstanceRemoval(InstancePortEvent event,
702 InstancePort instPort) {
703 if (!isRelevantHelper(event)) {
704 return;
705 }
706
707 log.info("SwitchingHandler: Instance port vanished MAC:{} IP:{}",
708 instPort.macAddress(),
709 instPort.ipAddress());
710
711 instPortRemoved(instPort);
712
713 Port osPort = osNetworkService.port(instPort.portId());
714
715 if (osPort != null) {
716 setPortBlockRules(instPort, false);
717 }
718 }
719
720 private void processInstanceMigrationEnd(InstancePortEvent event,
721 InstancePort instPort) {
722 if (!isRelevantHelper(event)) {
723 return;
724 }
725
726 log.info("SwitchingHandler: Migration finished for MAC:{} IP:{}",
727 instPort.macAddress(),
728 instPort.ipAddress());
729
730 InstancePort revisedInstPort = swapStaleLocation(instPort);
731
732 removeVportRules(revisedInstPort);
733 }
734
735 /**
736 * Configures L2 forwarding rules.
Jian Li2d68c192018-12-13 15:52:59 +0900737 * Currently, SONA supports Flat, VXLAN, GRE and VLAN modes.
Jian Li4d138702018-11-27 17:25:28 +0900738 *
739 * @param instPort instance port object
740 * @param install install flag, add the rule if true, remove it otherwise
741 */
742 private void setNetworkRules(InstancePort instPort, boolean install) {
743 Network network = osNetworkService.network(instPort.networkId());
744 NetworkType type = network.getNetworkType();
745
746 switch (type) {
747 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900748 case GRE:
749 setNetworkRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900750 break;
751 case VLAN:
752 setNetworkRulesForVlan(instPort, install);
753 break;
754 case FLAT:
755 setNetworkRulesForFlat(instPort, install);
756 break;
757 default:
758 log.warn("Unsupported network tunnel type {}", type.name());
759 break;
760 }
761 }
762
Jian Li2d68c192018-12-13 15:52:59 +0900763 private void setNetworkRulesForTunnel(InstancePort instPort, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900764 setTunnelTagIpFlowRules(instPort, install);
Jian Li2d68c192018-12-13 15:52:59 +0900765 setForwardingRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900766
767 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
768 setTunnelTagArpFlowRules(instPort, install);
769 }
770 }
771
772 private void setNetworkRulesForVlan(InstancePort instPort, boolean install) {
773 setVlanTagIpFlowRules(instPort, install);
774 setForwardingRulesForVlan(instPort, install);
775
776 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
777 setVlanTagArpFlowRules(instPort, install);
778 }
779 }
780
781 private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
782 setFlatJumpRules(instPort, install);
783 setDownstreamRulesForFlat(instPort, install);
784 setUpstreamRulesForFlat(instPort, install);
785 }
786
787 /**
788 * Removes virtual port related flow rules.
789 *
790 * @param instPort instance port
791 */
792 private void removeVportRules(InstancePort instPort) {
793 Network network = osNetworkService.network(instPort.networkId());
794 NetworkType type = network.getNetworkType();
795
796 switch (type) {
797 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900798 case GRE:
799 removeVportRulesForTunnel(instPort);
Jian Li4d138702018-11-27 17:25:28 +0900800 break;
801 case VLAN:
802 removeVportRulesForVlan(instPort);
803 break;
804 case FLAT:
805 removeVportRulesForFlat(instPort);
806 break;
807 default:
808 log.warn("Unsupported network type {}", type.name());
809 break;
810 }
811 }
812
Jian Li2d68c192018-12-13 15:52:59 +0900813 private void removeVportRulesForTunnel(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +0900814 setTunnelTagIpFlowRules(instPort, false);
815
816 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
817 setTunnelTagArpFlowRules(instPort, false);
818 }
819 }
820
821 private void removeVportRulesForVlan(InstancePort instPort) {
822 setVlanTagIpFlowRules(instPort, false);
823
824 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
825 setVlanTagArpFlowRules(instPort, false);
826 }
827 }
828
829 private void removeVportRulesForFlat(InstancePort instPort) {
830 setFlatJumpRules(instPort, false);
831 setUpstreamRulesForFlat(instPort, false);
832 setDownstreamRulesForFlat(instPort, false);
833 }
834
Hyunsun Moon44aac662017-02-18 02:07:01 +0900835 private void instPortDetected(InstancePort instPort) {
836 setNetworkRules(instPort, true);
837 // TODO add something else if needed
838 }
839
840 private void instPortRemoved(InstancePort instPort) {
841 setNetworkRules(instPort, false);
842 // TODO add something else if needed
843 }
844 }
Jian Li91be8cd2018-07-22 00:44:46 +0900845
846 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
847
848 @Override
849 public boolean isRelevant(OpenstackNetworkEvent event) {
Jian Li34220ea2018-11-14 01:30:24 +0900850 return event.subject() != null && event.port() != null;
851 }
Jian Li91be8cd2018-07-22 00:44:46 +0900852
Jian Li34220ea2018-11-14 01:30:24 +0900853 private boolean isRelevantHelper() {
854 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Jian Li91be8cd2018-07-22 00:44:46 +0900855 }
856
857 @Override
858 public void event(OpenstackNetworkEvent event) {
Jian Li91be8cd2018-07-22 00:44:46 +0900859 switch (event.type()) {
860 case OPENSTACK_NETWORK_CREATED:
861 case OPENSTACK_NETWORK_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900862 eventExecutor.execute(() -> processNetworkAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900863 break;
864 case OPENSTACK_NETWORK_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900865 eventExecutor.execute(() -> processNetworkRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900866 break;
867 case OPENSTACK_PORT_CREATED:
868 case OPENSTACK_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900869 eventExecutor.execute(() -> processPortAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900870 break;
871 case OPENSTACK_PORT_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900872 eventExecutor.execute(() -> processPortRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900873 break;
874 default:
875 break;
876 }
877 }
Jian Li4d138702018-11-27 17:25:28 +0900878
879 private void processNetworkAddition(OpenstackNetworkEvent event) {
880 if (!isRelevantHelper()) {
881 return;
882 }
883
884 boolean isNwAdminStateUp = event.subject().isAdminStateUp();
885 setNetworkBlockRules(event.subject(), !isNwAdminStateUp);
886 }
887
888 private void processNetworkRemoval(OpenstackNetworkEvent event) {
889 if (!isRelevantHelper()) {
890 return;
891 }
892
893 setNetworkBlockRules(event.subject(), false);
894 }
895
896 private void processPortAddition(OpenstackNetworkEvent event) {
897 if (!isRelevantHelper()) {
898 return;
899 }
900
901 boolean isPortAdminStateUp = event.port().isAdminStateUp();
902 String portId = event.port().getId();
903 InstancePort instPort = instancePortService.instancePort(portId);
904 if (instPort != null) {
905 setPortBlockRules(instPort, !isPortAdminStateUp);
906 }
907 }
908
909 private void processPortRemoval(OpenstackNetworkEvent event) {
910 if (!isRelevantHelper()) {
911 return;
912 }
913
914 String portId = event.port().getId();
915 InstancePort instPort = instancePortService.instancePort(portId);
916 if (instPort != null) {
917 setPortBlockRules(instPort, false);
918 }
919 }
Jian Li91be8cd2018-07-22 00:44:46 +0900920 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900921}