blob: e4b22b590566101e4e0d00ca93a523122975b8b9 [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 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
SONA Project6bc5c4a2018-12-14 23:49:52 +0900495 Type type = osNetworkService.networkType(network.getId());
Jian Li91be8cd2018-07-22 00:44:46 +0900496
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) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900743 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900744
745 switch (type) {
746 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900747 case GRE:
748 setNetworkRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900749 break;
750 case VLAN:
751 setNetworkRulesForVlan(instPort, install);
752 break;
753 case FLAT:
754 setNetworkRulesForFlat(instPort, install);
755 break;
756 default:
757 log.warn("Unsupported network tunnel type {}", type.name());
758 break;
759 }
760 }
761
Jian Li2d68c192018-12-13 15:52:59 +0900762 private void setNetworkRulesForTunnel(InstancePort instPort, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900763 setTunnelTagIpFlowRules(instPort, install);
Jian Li2d68c192018-12-13 15:52:59 +0900764 setForwardingRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900765
766 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
767 setTunnelTagArpFlowRules(instPort, install);
768 }
769 }
770
771 private void setNetworkRulesForVlan(InstancePort instPort, boolean install) {
772 setVlanTagIpFlowRules(instPort, install);
773 setForwardingRulesForVlan(instPort, install);
774
775 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
776 setVlanTagArpFlowRules(instPort, install);
777 }
778 }
779
780 private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
781 setFlatJumpRules(instPort, install);
782 setDownstreamRulesForFlat(instPort, install);
783 setUpstreamRulesForFlat(instPort, install);
784 }
785
786 /**
787 * Removes virtual port related flow rules.
788 *
789 * @param instPort instance port
790 */
791 private void removeVportRules(InstancePort instPort) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900792 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900793
794 switch (type) {
795 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900796 case GRE:
797 removeVportRulesForTunnel(instPort);
Jian Li4d138702018-11-27 17:25:28 +0900798 break;
799 case VLAN:
800 removeVportRulesForVlan(instPort);
801 break;
802 case FLAT:
803 removeVportRulesForFlat(instPort);
804 break;
805 default:
806 log.warn("Unsupported network type {}", type.name());
807 break;
808 }
809 }
810
Jian Li2d68c192018-12-13 15:52:59 +0900811 private void removeVportRulesForTunnel(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +0900812 setTunnelTagIpFlowRules(instPort, false);
813
814 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
815 setTunnelTagArpFlowRules(instPort, false);
816 }
817 }
818
819 private void removeVportRulesForVlan(InstancePort instPort) {
820 setVlanTagIpFlowRules(instPort, false);
821
822 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
823 setVlanTagArpFlowRules(instPort, false);
824 }
825 }
826
827 private void removeVportRulesForFlat(InstancePort instPort) {
828 setFlatJumpRules(instPort, false);
829 setUpstreamRulesForFlat(instPort, false);
830 setDownstreamRulesForFlat(instPort, false);
831 }
832
Hyunsun Moon44aac662017-02-18 02:07:01 +0900833 private void instPortDetected(InstancePort instPort) {
834 setNetworkRules(instPort, true);
835 // TODO add something else if needed
836 }
837
838 private void instPortRemoved(InstancePort instPort) {
839 setNetworkRules(instPort, false);
840 // TODO add something else if needed
841 }
842 }
Jian Li91be8cd2018-07-22 00:44:46 +0900843
844 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
845
846 @Override
847 public boolean isRelevant(OpenstackNetworkEvent event) {
Jian Li34220ea2018-11-14 01:30:24 +0900848 return event.subject() != null && event.port() != null;
849 }
Jian Li91be8cd2018-07-22 00:44:46 +0900850
Jian Li34220ea2018-11-14 01:30:24 +0900851 private boolean isRelevantHelper() {
852 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Jian Li91be8cd2018-07-22 00:44:46 +0900853 }
854
855 @Override
856 public void event(OpenstackNetworkEvent event) {
Jian Li91be8cd2018-07-22 00:44:46 +0900857 switch (event.type()) {
858 case OPENSTACK_NETWORK_CREATED:
859 case OPENSTACK_NETWORK_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900860 eventExecutor.execute(() -> processNetworkAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900861 break;
862 case OPENSTACK_NETWORK_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900863 eventExecutor.execute(() -> processNetworkRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900864 break;
865 case OPENSTACK_PORT_CREATED:
866 case OPENSTACK_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900867 eventExecutor.execute(() -> processPortAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900868 break;
869 case OPENSTACK_PORT_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900870 eventExecutor.execute(() -> processPortRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900871 break;
872 default:
873 break;
874 }
875 }
Jian Li4d138702018-11-27 17:25:28 +0900876
877 private void processNetworkAddition(OpenstackNetworkEvent event) {
878 if (!isRelevantHelper()) {
879 return;
880 }
881
882 boolean isNwAdminStateUp = event.subject().isAdminStateUp();
883 setNetworkBlockRules(event.subject(), !isNwAdminStateUp);
884 }
885
886 private void processNetworkRemoval(OpenstackNetworkEvent event) {
887 if (!isRelevantHelper()) {
888 return;
889 }
890
891 setNetworkBlockRules(event.subject(), false);
892 }
893
894 private void processPortAddition(OpenstackNetworkEvent event) {
895 if (!isRelevantHelper()) {
896 return;
897 }
898
899 boolean isPortAdminStateUp = event.port().isAdminStateUp();
900 String portId = event.port().getId();
901 InstancePort instPort = instancePortService.instancePort(portId);
902 if (instPort != null) {
903 setPortBlockRules(instPort, !isPortAdminStateUp);
904 }
905 }
906
907 private void processPortRemoval(OpenstackNetworkEvent event) {
908 if (!isRelevantHelper()) {
909 return;
910 }
911
912 String portId = event.port().getId();
913 InstancePort instPort = instancePortService.instancePort(portId);
914 if (instPort != null) {
915 setPortBlockRules(instPort, false);
916 }
917 }
Jian Li91be8cd2018-07-22 00:44:46 +0900918 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900919}