blob: d44dab1061a82d3e4c961a553bc4683a8bf7eb8a [file] [log] [blame]
sangho6a9ff0d2017-03-27 11:23:37 +09001/*
Jian Li26949762018-03-30 15:46:37 +09002 * Copyright 2017-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 */
sangho6a9ff0d2017-03-27 11:23:37 +090016
17package org.onosproject.openstacknetworking.impl;
18
19import com.google.common.base.Strings;
sangho2e97be02017-07-03 18:18:27 +090020import com.google.common.collect.Maps;
21import com.google.common.collect.Sets;
sangho6a9ff0d2017-03-27 11:23:37 +090022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
sangho0248ca22017-05-31 13:22:47 +090025import org.apache.felix.scr.annotations.Modified;
26import org.apache.felix.scr.annotations.Property;
sangho6a9ff0d2017-03-27 11:23:37 +090027import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.onlab.packet.Ethernet;
30import org.onlab.packet.IPv4;
31import org.onlab.packet.Ip4Address;
32import org.onlab.packet.Ip4Prefix;
33import org.onlab.packet.IpPrefix;
34import org.onlab.packet.TpPort;
Jian Lie8b28db2018-10-17 14:04:09 +090035import org.onlab.packet.VlanId;
sangho0248ca22017-05-31 13:22:47 +090036import org.onlab.util.Tools;
37import org.onosproject.cfg.ComponentConfigService;
sangho1aaa7882017-05-31 13:22:47 +090038import org.onosproject.cluster.ClusterService;
39import org.onosproject.cluster.LeadershipService;
40import org.onosproject.cluster.NodeId;
sangho6a9ff0d2017-03-27 11:23:37 +090041import org.onosproject.core.ApplicationId;
42import org.onosproject.core.CoreService;
43import org.onosproject.mastership.MastershipService;
sangho1aaa7882017-05-31 13:22:47 +090044import org.onosproject.net.DeviceId;
45import org.onosproject.net.driver.DriverService;
sangho6a9ff0d2017-03-27 11:23:37 +090046import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.TrafficSelector;
sangho1aaa7882017-05-31 13:22:47 +090049import org.onosproject.net.flow.TrafficTreatment;
50import org.onosproject.net.flow.criteria.ExtensionSelector;
sangho6a9ff0d2017-03-27 11:23:37 +090051import org.onosproject.openstacknetworking.api.InstancePort;
Jian Li9d35bd62018-10-13 01:43:24 +090052import org.onosproject.openstacknetworking.api.InstancePortAdminService;
sangho6a9ff0d2017-03-27 11:23:37 +090053import org.onosproject.openstacknetworking.api.InstancePortEvent;
54import org.onosproject.openstacknetworking.api.InstancePortListener;
sanghodc375372017-06-08 10:41:30 +090055import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
sangho6a9ff0d2017-03-27 11:23:37 +090056import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
57import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
58import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
59import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupEvent;
60import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupListener;
61import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
Jian Li9d35bd62018-10-13 01:43:24 +090062import org.onosproject.openstacknetworking.api.PreCommitPortService;
Jian Li26949762018-03-30 15:46:37 +090063import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
sangho3dd2a8b2017-07-19 15:54:31 +090064import org.onosproject.openstacknode.api.OpenstackNode;
sangho1aaa7882017-05-31 13:22:47 +090065import org.onosproject.openstacknode.api.OpenstackNodeEvent;
66import org.onosproject.openstacknode.api.OpenstackNodeListener;
sangho3dd2a8b2017-07-19 15:54:31 +090067import org.onosproject.openstacknode.api.OpenstackNodeService;
sangho6a9ff0d2017-03-27 11:23:37 +090068import org.openstack4j.model.network.Port;
69import org.openstack4j.model.network.SecurityGroup;
70import org.openstack4j.model.network.SecurityGroupRule;
71import org.openstack4j.openstack.networking.domain.NeutronSecurityGroupRule;
sangho0248ca22017-05-31 13:22:47 +090072import org.osgi.service.component.ComponentContext;
sangho6a9ff0d2017-03-27 11:23:37 +090073import org.slf4j.Logger;
74
sangho6a9ff0d2017-03-27 11:23:37 +090075import java.util.Collections;
sangho0248ca22017-05-31 13:22:47 +090076import java.util.Dictionary;
sangho2e97be02017-07-03 18:18:27 +090077import java.util.Map;
sangho6a9ff0d2017-03-27 11:23:37 +090078import java.util.Objects;
79import java.util.Set;
80import java.util.concurrent.ExecutorService;
81import java.util.stream.Collectors;
82
83import static java.util.concurrent.Executors.newSingleThreadExecutor;
84import static org.onlab.util.Tools.groupedThreads;
sanghodc375372017-06-08 10:41:30 +090085import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
sangho1aaa7882017-05-31 13:22:47 +090086import static org.onosproject.openstacknetworking.api.Constants.CT_TABLE;
87import static org.onosproject.openstacknetworking.api.Constants.ERROR_TABLE;
Jian Li9d35bd62018-10-13 01:43:24 +090088import static org.onosproject.openstacknetworking.api.Constants.JUMP_TABLE;
sangho6a9ff0d2017-03-27 11:23:37 +090089import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
90import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ACL_RULE;
sangho1aaa7882017-05-31 13:22:47 +090091import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_DROP_RULE;
92import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_HOOK_RULE;
93import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_RULE;
Jian Li9d35bd62018-10-13 01:43:24 +090094import static org.onosproject.openstacknetworking.api.InstancePort.State.REMOVE_PENDING;
95import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
Jian Libcc42282018-09-13 20:59:34 +090096import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtMaskFlag;
97import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtStateFlag;
98import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.niciraConnTrackTreatmentBuilder;
sangho1aaa7882017-05-31 13:22:47 +090099import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
sangho6a9ff0d2017-03-27 11:23:37 +0900100import static org.slf4j.LoggerFactory.getLogger;
101
102/**
103 * Populates flow rules to handle OpenStack SecurityGroups.
104 */
105@Component(immediate = true)
106public class OpenstackSecurityGroupHandler {
107
108 private final Logger log = getLogger(getClass());
109
sangho0248ca22017-05-31 13:22:47 +0900110 private static final boolean USE_SECURITY_GROUP = false;
111
112 @Property(name = "useSecurityGroup", boolValue = USE_SECURITY_GROUP,
113 label = "Apply OpenStack security group rule for VM traffic")
114 private boolean useSecurityGroup = USE_SECURITY_GROUP;
115
sangho6a9ff0d2017-03-27 11:23:37 +0900116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected CoreService coreService;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Li9d35bd62018-10-13 01:43:24 +0900120 protected InstancePortAdminService instancePortService;
sangho6a9ff0d2017-03-27 11:23:37 +0900121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected MastershipService mastershipService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonae51e732017-04-25 17:46:21 +0900126 protected OpenstackNetworkService osNetService;
sangho6a9ff0d2017-03-27 11:23:37 +0900127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 protected OpenstackSecurityGroupService securityGroupService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900132 protected OpenstackFlowRuleService osFlowRuleService;
sangho6a9ff0d2017-03-27 11:23:37 +0900133
sangho0248ca22017-05-31 13:22:47 +0900134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected ComponentConfigService configService;
136
sangho3dd2a8b2017-07-19 15:54:31 +0900137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 protected OpenstackNodeService osNodeService;
139
sanghoe6457a32017-08-24 14:31:19 +0900140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho1aaa7882017-05-31 13:22:47 +0900141 protected DriverService driverService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 protected LeadershipService leadershipService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected ClusterService clusterService;
148
Jian Li9d35bd62018-10-13 01:43:24 +0900149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected PreCommitPortService preCommitPortService;
151
Jian Libcc42282018-09-13 20:59:34 +0900152 private final InstancePortListener instancePortListener =
153 new InternalInstancePortListener();
154 private final OpenstackNetworkListener osNetworkListener =
155 new InternalOpenstackNetworkListener();
156 private final OpenstackNetworkListener osPortListener =
157 new InternalOpenstackPortListener();
158 private final OpenstackSecurityGroupListener securityGroupListener =
159 new InternalSecurityGroupListener();
sangho1aaa7882017-05-31 13:22:47 +0900160 private final OpenstackNodeListener osNodeListener = new InternalNodeListener();
sangho6a9ff0d2017-03-27 11:23:37 +0900161 private ApplicationId appId;
sangho1aaa7882017-05-31 13:22:47 +0900162 private NodeId localNodeId;
sangho6a9ff0d2017-03-27 11:23:37 +0900163
164 private final ExecutorService eventExecutor = newSingleThreadExecutor(
165 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
166
167 private static final String PROTO_ICMP = "ICMP";
168 private static final String PROTO_TCP = "TCP";
169 private static final String PROTO_UDP = "UDP";
170 private static final String ETHTYPE_IPV4 = "IPV4";
171 private static final String EGRESS = "EGRESS";
172 private static final String INGRESS = "INGRESS";
173 private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
174
Jian Lie8b28db2018-10-17 14:04:09 +0900175 private static final String VXLAN = "VXLAN";
176 private static final String VLAN = "VLAN";
177
sangho1aaa7882017-05-31 13:22:47 +0900178 // We expose pipeline structure to SONA application considering removing pipeline soon.
sanghoshinbbeb31a2018-09-11 17:01:01 +0800179 private static final int GOTO_CONNTRACK_TABLE = CT_TABLE;
180 private static final int GOTO_JUMP_TABLE = JUMP_TABLE;
sangho1aaa7882017-05-31 13:22:47 +0900181
182 private static final int CT_COMMIT = 0;
183 private static final int CT_NO_COMMIT = 1;
184 private static final short CT_NO_RECIRC = -1;
185
186 private static final int ACTION_NONE = 0;
187 private static final int ACTION_DROP = -1;
188
sangho6a9ff0d2017-03-27 11:23:37 +0900189 @Activate
190 protected void activate() {
191 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
sangho1aaa7882017-05-31 13:22:47 +0900192 localNodeId = clusterService.getLocalNode().id();
sangho6a9ff0d2017-03-27 11:23:37 +0900193 instancePortService.addListener(instancePortListener);
194 securityGroupService.addListener(securityGroupListener);
Jian Libcc42282018-09-13 20:59:34 +0900195 osNetService.addListener(osPortListener);
196 osNetService.addListener(osNetworkListener);
sangho0248ca22017-05-31 13:22:47 +0900197 configService.registerProperties(getClass());
sangho1aaa7882017-05-31 13:22:47 +0900198 osNodeService.addListener(osNodeListener);
sangho6a9ff0d2017-03-27 11:23:37 +0900199
200 log.info("Started");
201 }
202
203 @Deactivate
204 protected void deactivate() {
205 instancePortService.removeListener(instancePortListener);
206 securityGroupService.removeListener(securityGroupListener);
Jian Libcc42282018-09-13 20:59:34 +0900207 osNetService.removeListener(osNetworkListener);
208 osNetService.removeListener(osPortListener);
sangho0248ca22017-05-31 13:22:47 +0900209 configService.unregisterProperties(getClass(), false);
sangho1aaa7882017-05-31 13:22:47 +0900210 osNodeService.removeListener(osNodeListener);
sangho6a9ff0d2017-03-27 11:23:37 +0900211 eventExecutor.shutdown();
212
213 log.info("Stopped");
214 }
215
sangho0248ca22017-05-31 13:22:47 +0900216 @Modified
217 protected void modified(ComponentContext context) {
218 Dictionary<?, ?> properties = context.getProperties();
219 Boolean flag;
220
221 flag = Tools.isPropertyEnabled(properties, "useSecurityGroup");
222 if (flag == null) {
223 log.info("useSecurityGroup is not configured, " +
224 "using current value of {}", useSecurityGroup);
225 } else {
226 useSecurityGroup = flag;
227 log.info("Configured. useSecurityGroup is {}",
228 useSecurityGroup ? "enabled" : "disabled");
229 }
230
sanghoe6457a32017-08-24 14:31:19 +0900231 securityGroupService.setSecurityGroupEnabled(useSecurityGroup);
sangho0248ca22017-05-31 13:22:47 +0900232 resetSecurityGroupRules();
233 }
234
sangho1aaa7882017-05-31 13:22:47 +0900235 private void initializeConnTrackTable(DeviceId deviceId, boolean install) {
236
237 //table=1,ip,ct_state=-trk, actions=ct(table:2)
Jian Libcc42282018-09-13 20:59:34 +0900238 long ctState = computeCtStateFlag(false, false, false);
239 long ctMask = computeCtMaskFlag(true, false, false);
sangho1aaa7882017-05-31 13:22:47 +0900240 setConnTrackRule(deviceId, ctState, ctMask, CT_NO_COMMIT, (short) GOTO_CONNTRACK_TABLE,
241 ACTION_NONE, PRIORITY_CT_HOOK_RULE, install);
242
243 //table=2,ip,nw_dst=10.10.0.2,ct_state=+trk+est,action=goto_table:3
Jian Libcc42282018-09-13 20:59:34 +0900244 ctState = computeCtStateFlag(true, false, true);
245 ctMask = computeCtMaskFlag(true, false, true);
sangho1aaa7882017-05-31 13:22:47 +0900246 setConnTrackRule(deviceId, ctState, ctMask, CT_NO_COMMIT, CT_NO_RECIRC,
247 GOTO_JUMP_TABLE, PRIORITY_CT_RULE, install);
248
249 //table=2,ip,nw_dst=10.10.0.2,ct_state=+trk+new,action=drop
Jian Libcc42282018-09-13 20:59:34 +0900250 ctState = computeCtStateFlag(true, true, false);
251 ctMask = computeCtMaskFlag(true, true, false);
sangho1aaa7882017-05-31 13:22:47 +0900252 setConnTrackRule(deviceId, ctState, ctMask, CT_NO_COMMIT, CT_NO_RECIRC,
253 ACTION_DROP, PRIORITY_CT_DROP_RULE, install);
254 }
255
Jian Libcc42282018-09-13 20:59:34 +0900256 private void setSecurityGroupRules(InstancePort instPort,
257 Port port, boolean install) {
sangho6a9ff0d2017-03-27 11:23:37 +0900258 port.getSecurityGroups().forEach(sgId -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900259 SecurityGroup sg = securityGroupService.securityGroup(sgId);
260 if (sg == null) {
261 log.error("Security Group Not Found : {}", sgId);
262 return;
263 }
Jian Libcc42282018-09-13 20:59:34 +0900264 sg.getRules().forEach(sgRule ->
265 updateSecurityGroupRule(instPort, port, sgRule, install));
Hyunsun Moonae51e732017-04-25 17:46:21 +0900266 final String action = install ? "Installed " : "Removed ";
267 log.debug(action + "security group rule ID : " + sgId);
sangho6a9ff0d2017-03-27 11:23:37 +0900268 });
Jian Li9d35bd62018-10-13 01:43:24 +0900269
270 if (install) {
271 preCommitPortService.subscribePreCommit(instPort.portId(),
272 OPENSTACK_PORT_PRE_REMOVE, this.getClass().getName());
273 log.info("Subscribed the port {} on listening pre-remove event", instPort.portId());
274 } else {
275 preCommitPortService.unsubscribePreCommit(instPort.portId(),
276 OPENSTACK_PORT_PRE_REMOVE, instancePortService, this.getClass().getName());
277 log.info("Unsubscribed the port {} on listening pre-remove event", instPort.portId());
278 }
sangho6a9ff0d2017-03-27 11:23:37 +0900279 }
280
Jian Libcc42282018-09-13 20:59:34 +0900281 private void updateSecurityGroupRule(InstancePort instPort, Port port,
282 SecurityGroupRule sgRule, boolean install) {
sangho2e97be02017-07-03 18:18:27 +0900283
Daniel Park3a140592018-06-28 18:33:10 +0900284 if (instPort == null || port == null || sgRule == null) {
285 return;
286 }
287
sangho6a9ff0d2017-03-27 11:23:37 +0900288 if (sgRule.getRemoteGroupId() != null && !sgRule.getRemoteGroupId().isEmpty()) {
289 getRemoteInstPorts(port.getTenantId(), sgRule.getRemoteGroupId())
Jian Libcc42282018-09-13 20:59:34 +0900290 .forEach(rInstPort -> {
Jian Lie8b28db2018-10-17 14:04:09 +0900291 populateSecurityGroupRule(sgRule, instPort, port,
Jian Libcc42282018-09-13 20:59:34 +0900292 rInstPort.ipAddress().toIpPrefix(), install);
Jian Lie8b28db2018-10-17 14:04:09 +0900293 populateSecurityGroupRule(sgRule, rInstPort, port,
Jian Libcc42282018-09-13 20:59:34 +0900294 instPort.ipAddress().toIpPrefix(), install);
sangho6a9ff0d2017-03-27 11:23:37 +0900295
Jian Libcc42282018-09-13 20:59:34 +0900296 SecurityGroupRule rSgRule =
297 new NeutronSecurityGroupRule
298 .SecurityGroupRuleConcreteBuilder()
299 .from(sgRule)
300 .direction(sgRule.getDirection().toUpperCase()
301 .equals(EGRESS) ? INGRESS : EGRESS)
302 .build();
Jian Lie8b28db2018-10-17 14:04:09 +0900303 populateSecurityGroupRule(rSgRule, instPort, port,
Jian Libcc42282018-09-13 20:59:34 +0900304 rInstPort.ipAddress().toIpPrefix(), install);
Jian Lie8b28db2018-10-17 14:04:09 +0900305 populateSecurityGroupRule(rSgRule, rInstPort, port,
Jian Libcc42282018-09-13 20:59:34 +0900306 instPort.ipAddress().toIpPrefix(), install);
307 });
sangho6a9ff0d2017-03-27 11:23:37 +0900308 } else {
Jian Lie8b28db2018-10-17 14:04:09 +0900309 populateSecurityGroupRule(sgRule, instPort, port,
Jian Libcc42282018-09-13 20:59:34 +0900310 sgRule.getRemoteIpPrefix() == null ? IP_PREFIX_ANY :
sangho6a9ff0d2017-03-27 11:23:37 +0900311 IpPrefix.valueOf(sgRule.getRemoteIpPrefix()), install);
312 }
313 }
314
Jian Libcc42282018-09-13 20:59:34 +0900315 private void populateSecurityGroupRule(SecurityGroupRule sgRule,
316 InstancePort instPort,
Jian Lie8b28db2018-10-17 14:04:09 +0900317 Port port,
318 IpPrefix remoteIp,
319 boolean install) {
sangho2e97be02017-07-03 18:18:27 +0900320 Set<TrafficSelector> selectors = buildSelectors(sgRule,
Jian Lie8b28db2018-10-17 14:04:09 +0900321 Ip4Address.valueOf(instPort.ipAddress().toInetAddress()), remoteIp, port);
sangho2e97be02017-07-03 18:18:27 +0900322 if (selectors == null || selectors.isEmpty()) {
sangho6a9ff0d2017-03-27 11:23:37 +0900323 return;
324 }
325
sangho2e97be02017-07-03 18:18:27 +0900326 selectors.forEach(selector -> {
327 osFlowRuleService.setRule(appId,
328 instPort.deviceId(),
329 selector,
sangho3dd2a8b2017-07-19 15:54:31 +0900330 DefaultTrafficTreatment.builder().transition(JUMP_TABLE).build(),
sangho2e97be02017-07-03 18:18:27 +0900331 PRIORITY_ACL_RULE,
332 ACL_TABLE,
333 install);
334 });
sangho6a9ff0d2017-03-27 11:23:37 +0900335 }
336
337 /**
sangho1aaa7882017-05-31 13:22:47 +0900338 * Sets connection tracking rule using OVS extension commands.
339 * It is not so graceful, but I don't want to make it more general because it is going to be used
Ray Milkeyc108a6b2017-08-23 15:23:50 -0700340 * only here. The following is the usage of the function.
sangho1aaa7882017-05-31 13:22:47 +0900341 *
342 * @param deviceId Device ID
343 * @param ctState ctState: please use RulePopulatorUtil.computeCtStateFlag() to build the value
344 * @param ctMask crMask: please use RulePopulatorUtil.computeCtMaskFlag() to build the value
345 * @param commit CT_COMMIT for commit action, CT_NO_COMMIT otherwise
346 * @param recircTable table number for recirculation after CT actions. CT_NO_RECIRC with no recirculation
347 * @param action Additional actions. ACTION_DROP, ACTION_NONE, GOTO_XXX_TABLE are supported.
348 * @param priority priority value for the rule
349 * @param install true for insertion, false for removal
350 */
351 private void setConnTrackRule(DeviceId deviceId, long ctState, long ctMask,
352 int commit, short recircTable,
353 int action, int priority, boolean install) {
354
Jian Libcc42282018-09-13 20:59:34 +0900355 ExtensionSelector esCtSate = RulePopulatorUtil
356 .buildCtExtensionSelector(driverService, deviceId, ctState, ctMask);
sangho1aaa7882017-05-31 13:22:47 +0900357 TrafficSelector selector = DefaultTrafficSelector.builder()
358 .extension(esCtSate, deviceId)
359 .matchEthType(Ethernet.TYPE_IPV4)
360 .build();
361
362 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
363
364 if (commit == CT_COMMIT || recircTable > 0) {
365 RulePopulatorUtil.NiriraConnTrackTreatmentBuilder natTreatmentBuilder =
Jian Libcc42282018-09-13 20:59:34 +0900366 niciraConnTrackTreatmentBuilder(driverService, deviceId);
sangho1aaa7882017-05-31 13:22:47 +0900367 natTreatmentBuilder.natAction(false);
368 if (commit == CT_COMMIT) {
369 natTreatmentBuilder.commit(true);
370 } else {
371 natTreatmentBuilder.commit(false);
372 }
373 if (recircTable > 0) {
374 natTreatmentBuilder.table(recircTable);
375 }
376 tb.extension(natTreatmentBuilder.build(), deviceId);
377 } else if (action == ACTION_DROP) {
378 tb.drop();
379 }
380
sanghoshinbbeb31a2018-09-11 17:01:01 +0800381 if (action != ACTION_NONE && action != ACTION_DROP) {
sangho1aaa7882017-05-31 13:22:47 +0900382 tb.transition(action);
383 }
384
385 int tableType = ERROR_TABLE;
386 if (priority == PRIORITY_CT_RULE || priority == PRIORITY_CT_DROP_RULE) {
387 tableType = CT_TABLE;
388 } else if (priority == PRIORITY_CT_HOOK_RULE) {
389 tableType = ACL_TABLE;
390 } else {
391 log.error("Cannot an appropriate table for the conn track rule.");
392 }
393
394 osFlowRuleService.setRule(
395 appId,
396 deviceId,
397 selector,
398 tb.build(),
399 priority,
400 tableType,
401 install);
402 }
403
404 /**
sangho6a9ff0d2017-03-27 11:23:37 +0900405 * Returns a set of host IP addresses engaged with supplied security group ID.
406 * It only searches a VM in the same tenant boundary.
407 *
408 * @param tenantId tenant id
409 * @param sgId security group id
410 * @return set of ip addresses
411 */
412 private Set<InstancePort> getRemoteInstPorts(String tenantId, String sgId) {
413 Set<InstancePort> remoteInstPorts;
414
Hyunsun Moonae51e732017-04-25 17:46:21 +0900415 remoteInstPorts = osNetService.ports().stream()
sangho6a9ff0d2017-03-27 11:23:37 +0900416 .filter(port -> port.getTenantId().equals(tenantId))
417 .filter(port -> port.getSecurityGroups().contains(sgId))
418 .map(port -> instancePortService.instancePort(port.getId()))
419 .filter(instPort -> instPort != null && instPort.ipAddress() != null)
420 .collect(Collectors.toSet());
421
422 return Collections.unmodifiableSet(remoteInstPorts);
423 }
424
sangho2e97be02017-07-03 18:18:27 +0900425 private Set<TrafficSelector> buildSelectors(SecurityGroupRule sgRule,
426 Ip4Address vmIp,
Jian Lie8b28db2018-10-17 14:04:09 +0900427 IpPrefix remoteIp,
428 Port port) {
sangho2e97be02017-07-03 18:18:27 +0900429 if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
430 // do nothing if the remote IP is my IP
431 return null;
432 }
433
434 Set<TrafficSelector> selectorSet = Sets.newHashSet();
435
436 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
Jian Lie8b28db2018-10-17 14:04:09 +0900437 buildMatches(sBuilder, sgRule, vmIp, remoteIp, port);
sangho2e97be02017-07-03 18:18:27 +0900438
439 if (sgRule.getPortRangeMax() != null && sgRule.getPortRangeMin() != null &&
440 sgRule.getPortRangeMin() < sgRule.getPortRangeMax()) {
Jian Libcc42282018-09-13 20:59:34 +0900441 Map<TpPort, TpPort> portRangeMatchMap =
442 buildPortRangeMatches(sgRule.getPortRangeMin(),
sangho2e97be02017-07-03 18:18:27 +0900443 sgRule.getPortRangeMax());
444 portRangeMatchMap.entrySet().forEach(entry -> {
445
Jian Libcc42282018-09-13 20:59:34 +0900446 if (sgRule.getProtocol().toUpperCase().equals(PROTO_TCP)) {
447 if (sgRule.getDirection().toUpperCase().equals(EGRESS)) {
448 sBuilder.matchTcpSrcMasked(entry.getKey(), entry.getValue());
449 } else {
450 sBuilder.matchTcpDstMasked(entry.getKey(), entry.getValue());
451 }
452 } else if (sgRule.getProtocol().toUpperCase().equals(PROTO_UDP)) {
453 if (sgRule.getDirection().toUpperCase().equals(EGRESS)) {
454 sBuilder.matchUdpSrcMasked(entry.getKey(), entry.getValue());
455 } else {
456 sBuilder.matchUdpDstMasked(entry.getKey(), entry.getValue());
457 }
458 }
sangho2e97be02017-07-03 18:18:27 +0900459
Jian Libcc42282018-09-13 20:59:34 +0900460 selectorSet.add(sBuilder.build());
461 }
sangho2e97be02017-07-03 18:18:27 +0900462 );
463 } else {
464 selectorSet.add(sBuilder.build());
465 }
466
467 return selectorSet;
468 }
469
Jian Libcc42282018-09-13 20:59:34 +0900470 private void buildMatches(TrafficSelector.Builder sBuilder,
471 SecurityGroupRule sgRule,
Jian Lie8b28db2018-10-17 14:04:09 +0900472 Ip4Address vmIp, IpPrefix remoteIp, Port port) {
473 buildTunnelId(sBuilder, port);
sangho6a9ff0d2017-03-27 11:23:37 +0900474 buildMatchEthType(sBuilder, sgRule.getEtherType());
475 buildMatchDirection(sBuilder, sgRule.getDirection(), vmIp);
476 buildMatchProto(sBuilder, sgRule.getProtocol());
477 buildMatchPort(sBuilder, sgRule.getProtocol(), sgRule.getDirection(),
sangho2e97be02017-07-03 18:18:27 +0900478 sgRule.getPortRangeMin() == null ? 0 : sgRule.getPortRangeMin(),
479 sgRule.getPortRangeMax() == null ? 0 : sgRule.getPortRangeMax());
sangho6a9ff0d2017-03-27 11:23:37 +0900480 buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
481 if (sgRule.getRemoteGroupId() != null && sgRule.getRemoteGroupId().isEmpty()) {
482 buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
483 }
484 }
485
Jian Lie8b28db2018-10-17 14:04:09 +0900486 private void buildTunnelId(TrafficSelector.Builder sBuilder, Port port) {
487 String segId = osNetService.segmentId(port.getNetworkId());
488 String netType = osNetService.networkType(port.getNetworkId());
489
490 if (VLAN.equals(netType)) {
491 sBuilder.matchVlanId(VlanId.vlanId(segId));
492 } else if (VXLAN.equals(netType)) {
493 sBuilder.matchTunnelId(Long.valueOf(segId));
494 }
495 }
496
sangho6a9ff0d2017-03-27 11:23:37 +0900497 private void buildMatchDirection(TrafficSelector.Builder sBuilder,
498 String direction,
499 Ip4Address vmIp) {
500 if (direction.toUpperCase().equals(EGRESS)) {
501 sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
502 } else {
503 sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
504 }
505 }
506
507 private void buildMatchEthType(TrafficSelector.Builder sBuilder, String etherType) {
508 // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
509 sBuilder.matchEthType(Ethernet.TYPE_IPV4);
510 if (etherType != null && !Objects.equals(etherType, "null") &&
511 !etherType.toUpperCase().equals(ETHTYPE_IPV4)) {
512 log.debug("EthType {} is not supported yet in Security Group", etherType);
513 }
514 }
515
Jian Libcc42282018-09-13 20:59:34 +0900516 private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder,
517 IpPrefix remoteIpPrefix, String direction) {
518 if (remoteIpPrefix != null &&
519 !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
sangho6a9ff0d2017-03-27 11:23:37 +0900520 if (direction.toUpperCase().equals(EGRESS)) {
521 sBuilder.matchIPDst(remoteIpPrefix);
522 } else {
523 sBuilder.matchIPSrc(remoteIpPrefix);
524 }
525 }
526 }
527
528 private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
529 if (protocol != null) {
530 switch (protocol.toUpperCase()) {
531 case PROTO_ICMP:
532 sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
533 break;
534 case PROTO_TCP:
535 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
536 break;
537 case PROTO_UDP:
538 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
539 break;
540 default:
541 }
542 }
543 }
544
Jian Libcc42282018-09-13 20:59:34 +0900545 private void buildMatchPort(TrafficSelector.Builder sBuilder,
546 String protocol, String direction,
sangho6a9ff0d2017-03-27 11:23:37 +0900547 int portMin, int portMax) {
548 if (portMin > 0 && portMax > 0 && portMin == portMax) {
549 if (protocol.toUpperCase().equals(PROTO_TCP)) {
550 if (direction.toUpperCase().equals(EGRESS)) {
551 sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
552 } else {
553 sBuilder.matchTcpDst(TpPort.tpPort(portMax));
554 }
555 } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
556 if (direction.toUpperCase().equals(EGRESS)) {
557 sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
558 } else {
559 sBuilder.matchUdpDst(TpPort.tpPort(portMax));
560 }
561 }
562 }
563 }
564
sangho0248ca22017-05-31 13:22:47 +0900565 private void resetSecurityGroupRules() {
566
567 if (useSecurityGroup) {
sangho3dd2a8b2017-07-19 15:54:31 +0900568 osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
Jian Libcc42282018-09-13 20:59:34 +0900569 .forEach(node -> osFlowRuleService
570 .setUpTableMissEntry(node.intgBridge(), ACL_TABLE));
sangho0248ca22017-05-31 13:22:47 +0900571 securityGroupService.securityGroups().forEach(securityGroup ->
572 securityGroup.getRules().forEach(this::securityGroupRuleAdded));
sangho1aaa7882017-05-31 13:22:47 +0900573 osNodeService.nodes().stream()
574 .filter(node -> node.type().equals(OpenstackNode.NodeType.COMPUTE))
575 .forEach(node -> initializeConnTrackTable(node .intgBridge(), true));
sangho0248ca22017-05-31 13:22:47 +0900576 } else {
sangho3dd2a8b2017-07-19 15:54:31 +0900577 osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
Jian Libcc42282018-09-13 20:59:34 +0900578 .forEach(node -> osFlowRuleService
579 .connectTables(node.intgBridge(), ACL_TABLE, JUMP_TABLE));
sangho0248ca22017-05-31 13:22:47 +0900580 securityGroupService.securityGroups().forEach(securityGroup ->
581 securityGroup.getRules().forEach(this::securityGroupRuleRemoved));
sangho1aaa7882017-05-31 13:22:47 +0900582 osNodeService.nodes().stream()
583 .filter(node -> node.type().equals(OpenstackNode.NodeType.COMPUTE))
584 .forEach(node -> initializeConnTrackTable(node.intgBridge(), false));
sangho0248ca22017-05-31 13:22:47 +0900585 }
586
Jian Libcc42282018-09-13 20:59:34 +0900587 log.info("Reset security group info " +
588 (useSecurityGroup ? " with " : " without") + " Security Group");
sangho0248ca22017-05-31 13:22:47 +0900589 }
590
591 private void securityGroupRuleAdded(SecurityGroupRule sgRule) {
592 osNetService.ports().stream()
Jian Libcc42282018-09-13 20:59:34 +0900593 .filter(port -> port.getSecurityGroups()
594 .contains(sgRule.getSecurityGroupId()))
sangho0248ca22017-05-31 13:22:47 +0900595 .forEach(port -> {
596 updateSecurityGroupRule(
597 instancePortService.instancePort(port.getId()),
598 port, sgRule, true);
599 log.debug("Applied security group rule {} to port {}",
600 sgRule.getId(), port.getId());
601 });
602 }
603
604 private void securityGroupRuleRemoved(SecurityGroupRule sgRule) {
605 osNetService.ports().stream()
Jian Libcc42282018-09-13 20:59:34 +0900606 .filter(port -> port.getSecurityGroups()
607 .contains(sgRule.getSecurityGroupId()))
sangho0248ca22017-05-31 13:22:47 +0900608 .forEach(port -> {
609 updateSecurityGroupRule(
610 instancePortService.instancePort(port.getId()),
611 port, sgRule, false);
612 log.debug("Removed security group rule {} from port {}",
613 sgRule.getId(), port.getId());
614 });
615 }
616
sangho2e97be02017-07-03 18:18:27 +0900617 private int binLower(String binStr, int bits) {
618 String outBin = binStr.substring(0, 16 - bits);
619 for (int i = 0; i < bits; i++) {
620 outBin += "0";
621 }
622
623 return Integer.parseInt(outBin, 2);
624 }
625
626 private int binHigher(String binStr, int bits) {
627 String outBin = binStr.substring(0, 16 - bits);
628 for (int i = 0; i < bits; i++) {
629 outBin += "1";
630 }
631
632 return Integer.parseInt(outBin, 2);
633 }
634
635 private int testMasks(String binStr, int start, int end) {
636 int mask = 0;
637 for (; mask <= 16; mask++) {
638 int maskStart = binLower(binStr, mask);
639 int maskEnd = binHigher(binStr, mask);
640 if (maskStart < start || maskEnd > end) {
641 return mask - 1;
642 }
643 }
644
645 return mask;
646 }
647
648 private String getMask(int bits) {
649 switch (bits) {
650 case 0: return "ffff";
651 case 1: return "fffe";
652 case 2: return "fffc";
653 case 3: return "fff8";
654 case 4: return "fff0";
655 case 5: return "ffe0";
656 case 6: return "ffc0";
657 case 7: return "ff80";
658 case 8: return "ff00";
659 case 9: return "fe00";
660 case 10: return "fc00";
661 case 11: return "f800";
662 case 12: return "f000";
663 case 13: return "e000";
664 case 14: return "c000";
665 case 15: return "8000";
666 case 16: return "0000";
667 default: return null;
668 }
669 }
670
671 private Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {
672
673 boolean processing = true;
674 int start = portMin;
675 Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
676 while (processing) {
677 String minStr = Integer.toBinaryString(start);
678 String binStrMinPadded = "0000000000000000".substring(minStr.length()) + minStr;
679
680 int mask = testMasks(binStrMinPadded, start, portMax);
681 int maskStart = binLower(binStrMinPadded, mask);
682 int maskEnd = binHigher(binStrMinPadded, mask);
683
684 log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
Jian Libcc42282018-09-13 20:59:34 +0900685 portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(
686 Integer.parseInt(Objects.requireNonNull(getMask(mask)), 16)));
sangho2e97be02017-07-03 18:18:27 +0900687
688 start = maskEnd + 1;
689 if (start > portMax) {
690 processing = false;
691 }
692 }
693
694 return portMaskMap;
695 }
696
sangho6a9ff0d2017-03-27 11:23:37 +0900697 private class InternalInstancePortListener implements InstancePortListener {
698
699 @Override
700 public boolean isRelevant(InstancePortEvent event) {
701 InstancePort instPort = event.subject();
sangho0248ca22017-05-31 13:22:47 +0900702 if (!useSecurityGroup) {
703 return false;
704 }
sangho6a9ff0d2017-03-27 11:23:37 +0900705 return mastershipService.isLocalMaster(instPort.deviceId());
706 }
707
708 @Override
709 public void event(InstancePortEvent event) {
710 InstancePort instPort = event.subject();
711 switch (event.type()) {
Jian Liec5c32b2018-07-13 14:28:58 +0900712 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Lie8b28db2018-10-17 14:04:09 +0900713 if (instPort.state() == REMOVE_PENDING) {
714 break;
715 }
716 case OPENSTACK_INSTANCE_PORT_DETECTED:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900717 log.debug("Instance port detected MAC:{} IP:{}",
718 instPort.macAddress(),
719 instPort.ipAddress());
sangho6a9ff0d2017-03-27 11:23:37 +0900720 eventExecutor.execute(() -> {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900721 setSecurityGroupRules(instPort,
722 osNetService.port(event.subject().portId()),
723 true);
sangho6a9ff0d2017-03-27 11:23:37 +0900724 });
725 break;
sangho6a9ff0d2017-03-27 11:23:37 +0900726 default:
727 break;
728 }
729 }
sangho6a9ff0d2017-03-27 11:23:37 +0900730 }
731
732 private class InternalOpenstackPortListener implements OpenstackNetworkListener {
733
734 @Override
735 public boolean isRelevant(OpenstackNetworkEvent event) {
sanghoshinbbeb31a2018-09-11 17:01:01 +0800736 if (event.port() == null || Strings.isNullOrEmpty(event.port().getId())) {
sangho6a9ff0d2017-03-27 11:23:37 +0900737 return false;
738 }
Jian Libcc42282018-09-13 20:59:34 +0900739
740 InstancePort instPort = instancePortService.instancePort(event.port().getId());
741
742 if (instPort == null) {
743 return false;
744 }
745
746 return useSecurityGroup && mastershipService.isLocalMaster(instPort.deviceId());
747 }
748
749 @Override
750 public void event(OpenstackNetworkEvent event) {
751 log.debug("openstack port event received {}", event);
752 Port osPort = event.port();
753 InstancePort instPort = instancePortService.instancePort(osPort.getId());
754
755 switch (event.type()) {
756 case OPENSTACK_PORT_PRE_REMOVE:
Jian Li9d35bd62018-10-13 01:43:24 +0900757 instancePortService.updateInstancePort(
758 instPort.updateState(REMOVE_PENDING));
759 eventExecutor.execute(() ->
760 setSecurityGroupRules(instPort, osPort, false)
761 );
Jian Libcc42282018-09-13 20:59:34 +0900762 break;
763 default:
764 // do nothing for the other events
765 break;
766 }
767 }
768 }
769
770 private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
771
772 @Override
773 public boolean isRelevant(OpenstackNetworkEvent event) {
774 if (event.port() == null || Strings.isNullOrEmpty(event.port().getId())) {
775 return false;
776 }
Hyunsun Moonae51e732017-04-25 17:46:21 +0900777 if (event.securityGroupId() == null ||
778 securityGroupService.securityGroup(event.securityGroupId()) == null) {
779 return false;
780 }
781 if (instancePortService.instancePort(event.port().getId()) == null) {
782 return false;
783 }
Jian Libcc42282018-09-13 20:59:34 +0900784 return useSecurityGroup;
sangho6a9ff0d2017-03-27 11:23:37 +0900785 }
786
787 @Override
788 public void event(OpenstackNetworkEvent event) {
sanghoshinbbeb31a2018-09-11 17:01:01 +0800789 log.debug("security group event received {}", event);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900790 Port osPort = event.port();
791 InstancePort instPort = instancePortService.instancePort(osPort.getId());
792 SecurityGroup osSg = securityGroupService.securityGroup(event.securityGroupId());
793
sangho6a9ff0d2017-03-27 11:23:37 +0900794 switch (event.type()) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900795 case OPENSTACK_PORT_SECURITY_GROUP_ADDED:
796 eventExecutor.execute(() -> {
797 osSg.getRules().forEach(sgRule -> {
798 updateSecurityGroupRule(instPort, osPort, sgRule, true);
799 });
800 log.info("Added security group {} to port {}",
801 event.securityGroupId(), event.port().getId());
802 });
sangho6a9ff0d2017-03-27 11:23:37 +0900803 break;
Hyunsun Moonae51e732017-04-25 17:46:21 +0900804 case OPENSTACK_PORT_SECURITY_GROUP_REMOVED:
805 eventExecutor.execute(() -> {
806 osSg.getRules().forEach(sgRule -> {
807 updateSecurityGroupRule(instPort, osPort, sgRule, false);
808 });
809 log.info("Removed security group {} from port {}",
810 event.securityGroupId(), event.port().getId());
811 });
sangho6a9ff0d2017-03-27 11:23:37 +0900812 break;
813 default:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900814 // do nothing for the other events
sangho6a9ff0d2017-03-27 11:23:37 +0900815 break;
816 }
817 }
sangho6a9ff0d2017-03-27 11:23:37 +0900818 }
819
820 private class InternalSecurityGroupListener implements OpenstackSecurityGroupListener {
821
822 @Override
sangho0248ca22017-05-31 13:22:47 +0900823 public boolean isRelevant(OpenstackSecurityGroupEvent event) {
Jian Libcc42282018-09-13 20:59:34 +0900824 return useSecurityGroup;
sangho0248ca22017-05-31 13:22:47 +0900825 }
826
827 @Override
sangho6a9ff0d2017-03-27 11:23:37 +0900828 public void event(OpenstackSecurityGroupEvent event) {
829 switch (event.type()) {
sangho6a9ff0d2017-03-27 11:23:37 +0900830 case OPENSTACK_SECURITY_GROUP_RULE_CREATED:
831 SecurityGroupRule securityGroupRuleToAdd = event.securityGroupRule();
832 eventExecutor.execute(() -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900833 securityGroupRuleAdded(securityGroupRuleToAdd);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900834 log.info("Applied new security group rule {} to ports",
835 securityGroupRuleToAdd.getId());
sangho6a9ff0d2017-03-27 11:23:37 +0900836 });
837 break;
838
839 case OPENSTACK_SECURITY_GROUP_RULE_REMOVED:
840 SecurityGroupRule securityGroupRuleToRemove = event.securityGroupRule();
841 eventExecutor.execute(() -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900842 securityGroupRuleRemoved(securityGroupRuleToRemove);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900843 log.info("Removed security group rule {} from ports",
844 securityGroupRuleToRemove.getId());
sangho6a9ff0d2017-03-27 11:23:37 +0900845 });
846 break;
Hyunsun Moonae51e732017-04-25 17:46:21 +0900847 case OPENSTACK_SECURITY_GROUP_REMOVED:
Jian Li9d35bd62018-10-13 01:43:24 +0900848 case OPENSTACK_SECURITY_GROUP_CREATED:
sangho6a9ff0d2017-03-27 11:23:37 +0900849 default:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900850 // do nothing
851 break;
sangho6a9ff0d2017-03-27 11:23:37 +0900852 }
853 }
sangho6a9ff0d2017-03-27 11:23:37 +0900854 }
sangho1aaa7882017-05-31 13:22:47 +0900855
856 private class InternalNodeListener implements OpenstackNodeListener {
857
858 @Override
859 public boolean isRelevant(OpenstackNodeEvent event) {
860 // do not allow to proceed without leadership
861 NodeId leader = leadershipService.getLeader(appId.name());
862 if (!Objects.equals(localNodeId, leader)) {
863 return false;
864 }
865 return event.subject().type() == COMPUTE;
866 }
867
868 @Override
869 public void event(OpenstackNodeEvent event) {
870 OpenstackNode osNode = event.subject();
871
872 switch (event.type()) {
873 case OPENSTACK_NODE_COMPLETE:
874 eventExecutor.execute(() -> {
875 try {
876 if (useSecurityGroup) {
877 initializeConnTrackTable(osNode.intgBridge(), true);
Jian Li0488c732018-09-14 20:53:07 +0900878 log.info("SG table initialization : {} is done",
Jian Libcc42282018-09-13 20:59:34 +0900879 osNode.intgBridge());
sangho1aaa7882017-05-31 13:22:47 +0900880 }
881 } catch (IllegalArgumentException e) {
Jian Libcc42282018-09-13 20:59:34 +0900882 log.error("ACL table initialization error : {}",
883 e.getMessage());
sangho1aaa7882017-05-31 13:22:47 +0900884 }
885 });
886 break;
887 case OPENSTACK_NODE_CREATED:
888 case OPENSTACK_NODE_REMOVED:
889 case OPENSTACK_NODE_UPDATED:
890 case OPENSTACK_NODE_INCOMPLETE:
891 default:
892 break;
893 }
894 }
895 }
Jian Libcc42282018-09-13 20:59:34 +0900896}