blob: 0fab37efbc9c11457eaa8500e2d0b84881376903 [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:
Jian Li621f73c2018-12-15 01:49:22 +0900503 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900504 setNetworkBlockRulesForTunnel(network.getProviderSegID(), install);
Jian Li91be8cd2018-07-22 00:44:46 +0900505 break;
506 case VLAN:
507 setNetworkBlockRulesForVlan(network.getProviderSegID(), install);
508 break;
509 case FLAT:
510 // TODO: need to find a way to block flat typed network
511 break;
512 default:
513 break;
Frank Wangf9571662017-06-06 18:01:29 +0800514 }
Jian Li91be8cd2018-07-22 00:44:46 +0900515 }
516
Jian Li2d68c192018-12-13 15:52:59 +0900517 private void setNetworkBlockRulesForTunnel(String segmentId, boolean install) {
Jian Li91be8cd2018-07-22 00:44:46 +0900518 TrafficSelector selector = DefaultTrafficSelector.builder()
519 .matchTunnelId(Long.valueOf(segmentId))
520 .build();
Frank Wangf9571662017-06-06 18:01:29 +0800521
522 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
523 .drop()
524 .build();
525
Jian Li91be8cd2018-07-22 00:44:46 +0900526 osNodeService.completeNodes(COMPUTE)
Jian Liea1b9662018-03-02 18:07:32 +0900527 .forEach(osNode ->
Frank Wangf9571662017-06-06 18:01:29 +0800528 osFlowRuleService.setRule(
Jian Li91be8cd2018-07-22 00:44:46 +0900529 appId,
530 osNode.intgBridge(),
531 selector,
532 treatment,
533 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900534 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900535 install)
Jian Liea1b9662018-03-02 18:07:32 +0900536 );
Frank Wangf9571662017-06-06 18:01:29 +0800537 }
538
Jian Li91be8cd2018-07-22 00:44:46 +0900539 private void setNetworkBlockRulesForVlan(String segmentId, boolean install) {
Frank Wangf9571662017-06-06 18:01:29 +0800540 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Li91be8cd2018-07-22 00:44:46 +0900541 .matchTunnelId(Long.valueOf(segmentId))
542 .build();
543
544 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
545 .drop()
546 .build();
547
548 osNodeService.completeNodes(COMPUTE)
549 .forEach(osNode ->
550 osFlowRuleService.setRule(
551 appId,
552 osNode.intgBridge(),
553 selector,
554 treatment,
555 PRIORITY_ADMIN_RULE,
Jian Li1e9cb732018-11-25 23:17:21 +0900556 ACL_EGRESS_TABLE,
Jian Li91be8cd2018-07-22 00:44:46 +0900557 install)
558 );
559 }
560
561 private void setPortBlockRules(InstancePort instPort, boolean install) {
562 TrafficSelector selector = DefaultTrafficSelector.builder()
563 .matchInPort(instPort.portNumber())
Frank Wangf9571662017-06-06 18:01:29 +0800564 .build();
565
566 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
567 .drop()
568 .build();
569
570 osFlowRuleService.setRule(
571 appId,
Jian Li91be8cd2018-07-22 00:44:46 +0900572 instPort.deviceId(),
Frank Wangf9571662017-06-06 18:01:29 +0800573 selector,
574 treatment,
575 PRIORITY_ADMIN_RULE,
Jian Li70a2c3f2018-04-13 17:26:31 +0900576 VTAG_TABLE,
Frank Wangf9571662017-06-06 18:01:29 +0800577 install);
578 }
579
Jian Liea1b9662018-03-02 18:07:32 +0900580 /**
581 * Obtains the VLAN ID from the given instance port.
582 *
583 * @param instPort instance port object
584 * @return VLAN ID
585 */
daniel parka792cf72017-04-14 16:25:35 +0900586 private VlanId getVlanId(InstancePort instPort) {
587 Network osNet = osNetworkService.network(instPort.networkId());
588
589 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900590 final String error =
591 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900592 instPort, osNet == null ? STR_NONE : osNet.getName());
daniel parka792cf72017-04-14 16:25:35 +0900593 throw new IllegalStateException(error);
594 }
595
596 return VlanId.vlanId(osNet.getProviderSegID());
597 }
598
Jian Liea1b9662018-03-02 18:07:32 +0900599 /**
600 * Obtains the VNI from the given instance port.
601 *
602 * @param instPort instance port object
Jian Li2d68c192018-12-13 15:52:59 +0900603 * @return Virtual Network Identifier (VNI)
Jian Liea1b9662018-03-02 18:07:32 +0900604 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900605 private Long getVni(InstancePort instPort) {
606 Network osNet = osNetworkService.network(instPort.networkId());
607 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900608 final String error =
609 String.format(ERR_SET_FLOWS_VNI,
Jian Li4d138702018-11-27 17:25:28 +0900610 instPort, osNet == null ? STR_NONE : osNet.getName());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900611 throw new IllegalStateException(error);
612 }
613 return Long.valueOf(osNet.getProviderSegID());
614 }
615
Jian Li5c09e212018-10-24 18:23:58 +0900616 private String getArpMode() {
Jian Li34220ea2018-11-14 01:30:24 +0900617 Set<ConfigProperty> properties =
618 configService.getProperties(OpenstackSwitchingArpHandler.class.getName());
Jian Li5c09e212018-10-24 18:23:58 +0900619 return getPropertyValue(properties, ARP_MODE);
620 }
621
Jian Liea1b9662018-03-02 18:07:32 +0900622 /**
623 * An internal instance port listener which listens the port events generated
624 * from VM. The corresponding L2 forwarding rules will be generated and
625 * inserted to integration bridge only if a new VM port is detected. If the
626 * existing detected VM port is removed due to VM purge, we will remove the
627 * corresponding L2 forwarding to as well for the sake of resource saving.
628 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900629 private class InternalInstancePortListener implements InstancePortListener {
630
Jian Li34220ea2018-11-14 01:30:24 +0900631 private boolean isRelevantHelper(InstancePortEvent event) {
632 return mastershipService.isLocalMaster(event.subject().deviceId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900633 }
634
635 @Override
636 public void event(InstancePortEvent event) {
637 InstancePort instPort = event.subject();
Jian Li9a921b42018-06-18 02:44:50 +0900638
Hyunsun Moon44aac662017-02-18 02:07:01 +0900639 switch (event.type()) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900640 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +0900641 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li34220ea2018-11-14 01:30:24 +0900642 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li46b74002018-07-15 18:39:08 +0900643 case OPENSTACK_INSTANCE_RESTARTED:
Jian Li4d138702018-11-27 17:25:28 +0900644 eventExecutor.execute(() ->
645 processInstanceDetection(event, instPort));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900646 break;
Jian Li46b74002018-07-15 18:39:08 +0900647 case OPENSTACK_INSTANCE_TERMINATED:
Jian Li4d138702018-11-27 17:25:28 +0900648 eventExecutor.execute(() ->
649 processInstanceTermination(event, instPort));
Jian Li46b74002018-07-15 18:39:08 +0900650 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900651 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +0900652 eventExecutor.execute(() ->
653 processInstanceRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +0900654 break;
655 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +0900656 eventExecutor.execute(() ->
657 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +0900658 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900659 default:
660 break;
661 }
662 }
663
Jian Li4d138702018-11-27 17:25:28 +0900664 private void processInstanceDetection(InstancePortEvent event,
665 InstancePort instPort) {
666 if (!isRelevantHelper(event)) {
667 return;
668 }
669
670 if (event.type() == OPENSTACK_INSTANCE_MIGRATION_STARTED) {
671 log.info("SwitchingHandler: Migration started at MAC:{} IP:{}",
672 instPort.macAddress(),
673 instPort.ipAddress());
674 } else {
675 log.info("SwitchingHandler: Instance port detected MAC:{} IP:{}",
676 instPort.macAddress(),
677 instPort.ipAddress());
678 }
679
680 instPortDetected(instPort);
681
682 Port osPort = osNetworkService.port(instPort.portId());
683
684 if (osPort != null) {
685 setPortBlockRules(instPort, !osPort.isAdminStateUp());
686 }
687 }
688
689 private void processInstanceTermination(InstancePortEvent event,
690 InstancePort instPort) {
691 if (!isRelevantHelper(event)) {
692 return;
693 }
694
695 log.info("SwitchingHandler: Instance port terminated MAC:{} IP:{}",
696 instPort.macAddress(),
697 instPort.ipAddress());
698
699 removeVportRules(instPort);
700 }
701
702 private void processInstanceRemoval(InstancePortEvent event,
703 InstancePort instPort) {
704 if (!isRelevantHelper(event)) {
705 return;
706 }
707
708 log.info("SwitchingHandler: Instance port vanished MAC:{} IP:{}",
709 instPort.macAddress(),
710 instPort.ipAddress());
711
712 instPortRemoved(instPort);
713
714 Port osPort = osNetworkService.port(instPort.portId());
715
716 if (osPort != null) {
717 setPortBlockRules(instPort, false);
718 }
719 }
720
721 private void processInstanceMigrationEnd(InstancePortEvent event,
722 InstancePort instPort) {
723 if (!isRelevantHelper(event)) {
724 return;
725 }
726
727 log.info("SwitchingHandler: Migration finished for MAC:{} IP:{}",
728 instPort.macAddress(),
729 instPort.ipAddress());
730
731 InstancePort revisedInstPort = swapStaleLocation(instPort);
732
733 removeVportRules(revisedInstPort);
734 }
735
736 /**
737 * Configures L2 forwarding rules.
Jian Li621f73c2018-12-15 01:49:22 +0900738 * Currently, SONA supports Flat, VXLAN, GRE, GENEVE and VLAN modes.
Jian Li4d138702018-11-27 17:25:28 +0900739 *
740 * @param instPort instance port object
741 * @param install install flag, add the rule if true, remove it otherwise
742 */
743 private void setNetworkRules(InstancePort instPort, boolean install) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900744 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900745
746 switch (type) {
747 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900748 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900749 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900750 setNetworkRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900751 break;
752 case VLAN:
753 setNetworkRulesForVlan(instPort, install);
754 break;
755 case FLAT:
756 setNetworkRulesForFlat(instPort, install);
757 break;
758 default:
759 log.warn("Unsupported network tunnel type {}", type.name());
760 break;
761 }
762 }
763
Jian Li2d68c192018-12-13 15:52:59 +0900764 private void setNetworkRulesForTunnel(InstancePort instPort, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900765 setTunnelTagIpFlowRules(instPort, install);
Jian Li2d68c192018-12-13 15:52:59 +0900766 setForwardingRulesForTunnel(instPort, install);
Jian Li4d138702018-11-27 17:25:28 +0900767
768 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
769 setTunnelTagArpFlowRules(instPort, install);
770 }
771 }
772
773 private void setNetworkRulesForVlan(InstancePort instPort, boolean install) {
774 setVlanTagIpFlowRules(instPort, install);
775 setForwardingRulesForVlan(instPort, install);
776
777 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
778 setVlanTagArpFlowRules(instPort, install);
779 }
780 }
781
782 private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
783 setFlatJumpRules(instPort, install);
784 setDownstreamRulesForFlat(instPort, install);
785 setUpstreamRulesForFlat(instPort, install);
786 }
787
788 /**
789 * Removes virtual port related flow rules.
790 *
791 * @param instPort instance port
792 */
793 private void removeVportRules(InstancePort instPort) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900794 Type type = osNetworkService.networkType(instPort.networkId());
Jian Li4d138702018-11-27 17:25:28 +0900795
796 switch (type) {
797 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900798 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900799 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900800 removeVportRulesForTunnel(instPort);
Jian Li4d138702018-11-27 17:25:28 +0900801 break;
802 case VLAN:
803 removeVportRulesForVlan(instPort);
804 break;
805 case FLAT:
806 removeVportRulesForFlat(instPort);
807 break;
808 default:
809 log.warn("Unsupported network type {}", type.name());
810 break;
811 }
812 }
813
Jian Li2d68c192018-12-13 15:52:59 +0900814 private void removeVportRulesForTunnel(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +0900815 setTunnelTagIpFlowRules(instPort, false);
816
817 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
818 setTunnelTagArpFlowRules(instPort, false);
819 }
820 }
821
822 private void removeVportRulesForVlan(InstancePort instPort) {
823 setVlanTagIpFlowRules(instPort, false);
824
825 if (ARP_BROADCAST_MODE.equals(getArpMode())) {
826 setVlanTagArpFlowRules(instPort, false);
827 }
828 }
829
830 private void removeVportRulesForFlat(InstancePort instPort) {
831 setFlatJumpRules(instPort, false);
832 setUpstreamRulesForFlat(instPort, false);
833 setDownstreamRulesForFlat(instPort, false);
834 }
835
Hyunsun Moon44aac662017-02-18 02:07:01 +0900836 private void instPortDetected(InstancePort instPort) {
837 setNetworkRules(instPort, true);
838 // TODO add something else if needed
839 }
840
841 private void instPortRemoved(InstancePort instPort) {
842 setNetworkRules(instPort, false);
843 // TODO add something else if needed
844 }
845 }
Jian Li91be8cd2018-07-22 00:44:46 +0900846
847 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
848
849 @Override
850 public boolean isRelevant(OpenstackNetworkEvent event) {
Jian Li34220ea2018-11-14 01:30:24 +0900851 return event.subject() != null && event.port() != null;
852 }
Jian Li91be8cd2018-07-22 00:44:46 +0900853
Jian Li34220ea2018-11-14 01:30:24 +0900854 private boolean isRelevantHelper() {
855 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Jian Li91be8cd2018-07-22 00:44:46 +0900856 }
857
858 @Override
859 public void event(OpenstackNetworkEvent event) {
Jian Li91be8cd2018-07-22 00:44:46 +0900860 switch (event.type()) {
861 case OPENSTACK_NETWORK_CREATED:
862 case OPENSTACK_NETWORK_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900863 eventExecutor.execute(() -> processNetworkAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900864 break;
865 case OPENSTACK_NETWORK_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900866 eventExecutor.execute(() -> processNetworkRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900867 break;
868 case OPENSTACK_PORT_CREATED:
869 case OPENSTACK_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +0900870 eventExecutor.execute(() -> processPortAddition(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900871 break;
872 case OPENSTACK_PORT_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +0900873 eventExecutor.execute(() -> processPortRemoval(event));
Jian Li91be8cd2018-07-22 00:44:46 +0900874 break;
875 default:
876 break;
877 }
878 }
Jian Li4d138702018-11-27 17:25:28 +0900879
880 private void processNetworkAddition(OpenstackNetworkEvent event) {
881 if (!isRelevantHelper()) {
882 return;
883 }
884
885 boolean isNwAdminStateUp = event.subject().isAdminStateUp();
886 setNetworkBlockRules(event.subject(), !isNwAdminStateUp);
887 }
888
889 private void processNetworkRemoval(OpenstackNetworkEvent event) {
890 if (!isRelevantHelper()) {
891 return;
892 }
893
894 setNetworkBlockRules(event.subject(), false);
895 }
896
897 private void processPortAddition(OpenstackNetworkEvent event) {
898 if (!isRelevantHelper()) {
899 return;
900 }
901
902 boolean isPortAdminStateUp = event.port().isAdminStateUp();
903 String portId = event.port().getId();
904 InstancePort instPort = instancePortService.instancePort(portId);
905 if (instPort != null) {
906 setPortBlockRules(instPort, !isPortAdminStateUp);
907 }
908 }
909
910 private void processPortRemoval(OpenstackNetworkEvent event) {
911 if (!isRelevantHelper()) {
912 return;
913 }
914
915 String portId = event.port().getId();
916 InstancePort instPort = instancePortService.instancePort(portId);
917 if (instPort != null) {
918 setPortBlockRules(instPort, false);
919 }
920 }
Jian Li91be8cd2018-07-22 00:44:46 +0900921 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900922}