blob: 690fc6c8cc1e73c3b76752625fb0f38226c3e708 [file] [log] [blame]
sangho6a9ff0d2017-03-27 11:23:37 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002* Copyright 2017-present Open Networking Foundation
sangho6a9ff0d2017-03-27 11:23:37 +09003*
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*/
16
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;
sangho0248ca22017-05-31 13:22:47 +090035import org.onlab.util.Tools;
36import org.onosproject.cfg.ComponentConfigService;
sangho6a9ff0d2017-03-27 11:23:37 +090037import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
39import org.onosproject.mastership.MastershipService;
40import org.onosproject.net.flow.DefaultTrafficSelector;
41import org.onosproject.net.flow.DefaultTrafficTreatment;
42import org.onosproject.net.flow.TrafficSelector;
sangho6a9ff0d2017-03-27 11:23:37 +090043import org.onosproject.openstacknetworking.api.InstancePort;
44import org.onosproject.openstacknetworking.api.InstancePortEvent;
45import org.onosproject.openstacknetworking.api.InstancePortListener;
46import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090047import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
sangho6a9ff0d2017-03-27 11:23:37 +090048import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
49import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
50import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
51import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupEvent;
52import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupListener;
53import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
sangho3dd2a8b2017-07-19 15:54:31 +090054import org.onosproject.openstacknode.api.OpenstackNode;
55import org.onosproject.openstacknode.api.OpenstackNodeService;
sangho6a9ff0d2017-03-27 11:23:37 +090056import org.openstack4j.model.network.Port;
57import org.openstack4j.model.network.SecurityGroup;
58import org.openstack4j.model.network.SecurityGroupRule;
59import org.openstack4j.openstack.networking.domain.NeutronSecurityGroupRule;
sangho0248ca22017-05-31 13:22:47 +090060import org.osgi.service.component.ComponentContext;
sangho6a9ff0d2017-03-27 11:23:37 +090061import org.slf4j.Logger;
62
sangho6a9ff0d2017-03-27 11:23:37 +090063import java.util.Collections;
sangho0248ca22017-05-31 13:22:47 +090064import java.util.Dictionary;
sangho2e97be02017-07-03 18:18:27 +090065import java.util.Map;
sangho6a9ff0d2017-03-27 11:23:37 +090066import java.util.Objects;
67import java.util.Set;
68import java.util.concurrent.ExecutorService;
69import java.util.stream.Collectors;
70
71import static java.util.concurrent.Executors.newSingleThreadExecutor;
72import static org.onlab.util.Tools.groupedThreads;
sanghodc375372017-06-08 10:41:30 +090073import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
sangho3dd2a8b2017-07-19 15:54:31 +090074import static org.onosproject.openstacknetworking.api.Constants.JUMP_TABLE;
sangho6a9ff0d2017-03-27 11:23:37 +090075import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
76import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ACL_RULE;
77import static org.slf4j.LoggerFactory.getLogger;
78
79/**
80 * Populates flow rules to handle OpenStack SecurityGroups.
81 */
82@Component(immediate = true)
83public class OpenstackSecurityGroupHandler {
84
85 private final Logger log = getLogger(getClass());
86
sangho0248ca22017-05-31 13:22:47 +090087 private static final boolean USE_SECURITY_GROUP = false;
88
89 @Property(name = "useSecurityGroup", boolValue = USE_SECURITY_GROUP,
90 label = "Apply OpenStack security group rule for VM traffic")
91 private boolean useSecurityGroup = USE_SECURITY_GROUP;
92
sangho6a9ff0d2017-03-27 11:23:37 +090093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected CoreService coreService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected InstancePortService instancePortService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected MastershipService mastershipService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonae51e732017-04-25 17:46:21 +0900103 protected OpenstackNetworkService osNetService;
sangho6a9ff0d2017-03-27 11:23:37 +0900104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected OpenstackSecurityGroupService securityGroupService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900109 protected OpenstackFlowRuleService osFlowRuleService;
sangho6a9ff0d2017-03-27 11:23:37 +0900110
sangho0248ca22017-05-31 13:22:47 +0900111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected ComponentConfigService configService;
113
sangho3dd2a8b2017-07-19 15:54:31 +0900114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected OpenstackNodeService osNodeService;
116
sangho6a9ff0d2017-03-27 11:23:37 +0900117 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
118 private final OpenstackNetworkListener portListener = new InternalOpenstackPortListener();
119 private final OpenstackSecurityGroupListener securityGroupListener = new InternalSecurityGroupListener();
120 private ApplicationId appId;
121
122 private final ExecutorService eventExecutor = newSingleThreadExecutor(
123 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
124
125 private static final String PROTO_ICMP = "ICMP";
126 private static final String PROTO_TCP = "TCP";
127 private static final String PROTO_UDP = "UDP";
128 private static final String ETHTYPE_IPV4 = "IPV4";
129 private static final String EGRESS = "EGRESS";
130 private static final String INGRESS = "INGRESS";
131 private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
132
133 @Activate
134 protected void activate() {
135 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
136 instancePortService.addListener(instancePortListener);
137 securityGroupService.addListener(securityGroupListener);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900138 osNetService.addListener(portListener);
sangho0248ca22017-05-31 13:22:47 +0900139 configService.registerProperties(getClass());
sangho6a9ff0d2017-03-27 11:23:37 +0900140
141 log.info("Started");
142 }
143
144 @Deactivate
145 protected void deactivate() {
146 instancePortService.removeListener(instancePortListener);
147 securityGroupService.removeListener(securityGroupListener);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900148 osNetService.removeListener(portListener);
sangho0248ca22017-05-31 13:22:47 +0900149 configService.unregisterProperties(getClass(), false);
sangho6a9ff0d2017-03-27 11:23:37 +0900150 eventExecutor.shutdown();
151
152 log.info("Stopped");
153 }
154
sangho0248ca22017-05-31 13:22:47 +0900155 @Modified
156 protected void modified(ComponentContext context) {
157 Dictionary<?, ?> properties = context.getProperties();
158 Boolean flag;
159
160 flag = Tools.isPropertyEnabled(properties, "useSecurityGroup");
161 if (flag == null) {
162 log.info("useSecurityGroup is not configured, " +
163 "using current value of {}", useSecurityGroup);
164 } else {
165 useSecurityGroup = flag;
166 log.info("Configured. useSecurityGroup is {}",
167 useSecurityGroup ? "enabled" : "disabled");
168 }
169
170 resetSecurityGroupRules();
171 }
172
sangho6a9ff0d2017-03-27 11:23:37 +0900173 private void setSecurityGroupRules(InstancePort instPort, Port port, boolean install) {
174 port.getSecurityGroups().forEach(sgId -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900175 SecurityGroup sg = securityGroupService.securityGroup(sgId);
176 if (sg == null) {
177 log.error("Security Group Not Found : {}", sgId);
178 return;
179 }
180 sg.getRules().forEach(sgRule -> updateSecurityGroupRule(instPort, port, sgRule, install));
Hyunsun Moonae51e732017-04-25 17:46:21 +0900181 final String action = install ? "Installed " : "Removed ";
182 log.debug(action + "security group rule ID : " + sgId);
sangho6a9ff0d2017-03-27 11:23:37 +0900183 });
184 }
185
186 private void updateSecurityGroupRule(InstancePort instPort, Port port, SecurityGroupRule sgRule, boolean install) {
sangho2e97be02017-07-03 18:18:27 +0900187
sangho6a9ff0d2017-03-27 11:23:37 +0900188 if (sgRule.getRemoteGroupId() != null && !sgRule.getRemoteGroupId().isEmpty()) {
189 getRemoteInstPorts(port.getTenantId(), sgRule.getRemoteGroupId())
190 .forEach(rInstPort -> {
191 populateSecurityGroupRule(sgRule, instPort, rInstPort.ipAddress().toIpPrefix(), install);
192 populateSecurityGroupRule(sgRule, rInstPort, instPort.ipAddress().toIpPrefix(), install);
193
194 SecurityGroupRule rSgRule = new NeutronSecurityGroupRule.SecurityGroupRuleConcreteBuilder()
195 .from(sgRule)
196 .direction(sgRule.getDirection().toUpperCase().equals(EGRESS) ? INGRESS : EGRESS).build();
197 populateSecurityGroupRule(rSgRule, instPort, rInstPort.ipAddress().toIpPrefix(), install);
198 populateSecurityGroupRule(rSgRule, rInstPort, instPort.ipAddress().toIpPrefix(), install);
199 });
200 } else {
201 populateSecurityGroupRule(sgRule, instPort, sgRule.getRemoteIpPrefix() == null ? IP_PREFIX_ANY :
202 IpPrefix.valueOf(sgRule.getRemoteIpPrefix()), install);
203 }
204 }
205
206 private void populateSecurityGroupRule(SecurityGroupRule sgRule, InstancePort instPort,
207 IpPrefix remoteIp, boolean install) {
sangho2e97be02017-07-03 18:18:27 +0900208 Set<TrafficSelector> selectors = buildSelectors(sgRule,
209 Ip4Address.valueOf(instPort.ipAddress().toInetAddress()), remoteIp);
210 if (selectors == null || selectors.isEmpty()) {
sangho6a9ff0d2017-03-27 11:23:37 +0900211 return;
212 }
213
sangho2e97be02017-07-03 18:18:27 +0900214 selectors.forEach(selector -> {
215 osFlowRuleService.setRule(appId,
216 instPort.deviceId(),
217 selector,
sangho3dd2a8b2017-07-19 15:54:31 +0900218 DefaultTrafficTreatment.builder().transition(JUMP_TABLE).build(),
sangho2e97be02017-07-03 18:18:27 +0900219 PRIORITY_ACL_RULE,
220 ACL_TABLE,
221 install);
222 });
sangho6a9ff0d2017-03-27 11:23:37 +0900223 }
224
225 /**
226 * Returns a set of host IP addresses engaged with supplied security group ID.
227 * It only searches a VM in the same tenant boundary.
228 *
229 * @param tenantId tenant id
230 * @param sgId security group id
231 * @return set of ip addresses
232 */
233 private Set<InstancePort> getRemoteInstPorts(String tenantId, String sgId) {
234 Set<InstancePort> remoteInstPorts;
235
Hyunsun Moonae51e732017-04-25 17:46:21 +0900236 remoteInstPorts = osNetService.ports().stream()
sangho6a9ff0d2017-03-27 11:23:37 +0900237 .filter(port -> port.getTenantId().equals(tenantId))
238 .filter(port -> port.getSecurityGroups().contains(sgId))
239 .map(port -> instancePortService.instancePort(port.getId()))
240 .filter(instPort -> instPort != null && instPort.ipAddress() != null)
241 .collect(Collectors.toSet());
242
243 return Collections.unmodifiableSet(remoteInstPorts);
244 }
245
sangho2e97be02017-07-03 18:18:27 +0900246 private Set<TrafficSelector> buildSelectors(SecurityGroupRule sgRule,
247 Ip4Address vmIp,
248 IpPrefix remoteIp) {
249 if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
250 // do nothing if the remote IP is my IP
251 return null;
252 }
253
254 Set<TrafficSelector> selectorSet = Sets.newHashSet();
255
256 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
257 buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
258
259 if (sgRule.getPortRangeMax() != null && sgRule.getPortRangeMin() != null &&
260 sgRule.getPortRangeMin() < sgRule.getPortRangeMax()) {
261 Map<TpPort, TpPort> portRangeMatchMap = buildPortRangeMatches(sgRule.getPortRangeMin(),
262 sgRule.getPortRangeMax());
263 portRangeMatchMap.entrySet().forEach(entry -> {
264
265 if (sgRule.getProtocol().toUpperCase().equals(PROTO_TCP)) {
266 if (sgRule.getDirection().toUpperCase().equals(EGRESS)) {
267 sBuilder.matchTcpSrcMasked(entry.getKey(), entry.getValue());
268 } else {
269 sBuilder.matchTcpDstMasked(entry.getKey(), entry.getValue());
270 }
271 } else if (sgRule.getProtocol().toUpperCase().equals(PROTO_UDP)) {
272 if (sgRule.getDirection().toUpperCase().equals(EGRESS)) {
273 sBuilder.matchUdpSrcMasked(entry.getKey(), entry.getValue());
274 } else {
275 sBuilder.matchUdpDstMasked(entry.getKey(), entry.getValue());
276 }
277 }
278
279 selectorSet.add(sBuilder.build());
280 }
281 );
282 } else {
283 selectorSet.add(sBuilder.build());
284 }
285
286 return selectorSet;
287 }
288
sangho6a9ff0d2017-03-27 11:23:37 +0900289 private void buildMatchs(TrafficSelector.Builder sBuilder, SecurityGroupRule sgRule,
290 Ip4Address vmIp, IpPrefix remoteIp) {
291 buildMatchEthType(sBuilder, sgRule.getEtherType());
292 buildMatchDirection(sBuilder, sgRule.getDirection(), vmIp);
293 buildMatchProto(sBuilder, sgRule.getProtocol());
294 buildMatchPort(sBuilder, sgRule.getProtocol(), sgRule.getDirection(),
sangho2e97be02017-07-03 18:18:27 +0900295 sgRule.getPortRangeMin() == null ? 0 : sgRule.getPortRangeMin(),
296 sgRule.getPortRangeMax() == null ? 0 : sgRule.getPortRangeMax());
sangho6a9ff0d2017-03-27 11:23:37 +0900297 buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
298 if (sgRule.getRemoteGroupId() != null && sgRule.getRemoteGroupId().isEmpty()) {
299 buildMatchRemoteIp(sBuilder, remoteIp, sgRule.getDirection());
300 }
301 }
302
303 private void buildMatchDirection(TrafficSelector.Builder sBuilder,
304 String direction,
305 Ip4Address vmIp) {
306 if (direction.toUpperCase().equals(EGRESS)) {
307 sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
308 } else {
309 sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
310 }
311 }
312
313 private void buildMatchEthType(TrafficSelector.Builder sBuilder, String etherType) {
314 // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
315 sBuilder.matchEthType(Ethernet.TYPE_IPV4);
316 if (etherType != null && !Objects.equals(etherType, "null") &&
317 !etherType.toUpperCase().equals(ETHTYPE_IPV4)) {
318 log.debug("EthType {} is not supported yet in Security Group", etherType);
319 }
320 }
321
322 private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix, String direction) {
323 if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
324 if (direction.toUpperCase().equals(EGRESS)) {
325 sBuilder.matchIPDst(remoteIpPrefix);
326 } else {
327 sBuilder.matchIPSrc(remoteIpPrefix);
328 }
329 }
330 }
331
332 private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
333 if (protocol != null) {
334 switch (protocol.toUpperCase()) {
335 case PROTO_ICMP:
336 sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
337 break;
338 case PROTO_TCP:
339 sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
340 break;
341 case PROTO_UDP:
342 sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
343 break;
344 default:
345 }
346 }
347 }
348
349 private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol, String direction,
350 int portMin, int portMax) {
351 if (portMin > 0 && portMax > 0 && portMin == portMax) {
352 if (protocol.toUpperCase().equals(PROTO_TCP)) {
353 if (direction.toUpperCase().equals(EGRESS)) {
354 sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
355 } else {
356 sBuilder.matchTcpDst(TpPort.tpPort(portMax));
357 }
358 } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
359 if (direction.toUpperCase().equals(EGRESS)) {
360 sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
361 } else {
362 sBuilder.matchUdpDst(TpPort.tpPort(portMax));
363 }
364 }
365 }
366 }
367
sangho0248ca22017-05-31 13:22:47 +0900368 private void resetSecurityGroupRules() {
369
370 if (useSecurityGroup) {
sangho3dd2a8b2017-07-19 15:54:31 +0900371 osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
372 .forEach(node -> osFlowRuleService.setUpTableMissEntry(node.intgBridge(), ACL_TABLE));
sangho0248ca22017-05-31 13:22:47 +0900373 securityGroupService.securityGroups().forEach(securityGroup ->
374 securityGroup.getRules().forEach(this::securityGroupRuleAdded));
375 } else {
sangho3dd2a8b2017-07-19 15:54:31 +0900376 osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
377 .forEach(node -> osFlowRuleService.connectTables(node.intgBridge(), ACL_TABLE, JUMP_TABLE));
sangho0248ca22017-05-31 13:22:47 +0900378 securityGroupService.securityGroups().forEach(securityGroup ->
379 securityGroup.getRules().forEach(this::securityGroupRuleRemoved));
380 }
381
382 log.info("Reset security group info " + (useSecurityGroup ? " with " : " without") + " Security Group");
383 }
384
385 private void securityGroupRuleAdded(SecurityGroupRule sgRule) {
386 osNetService.ports().stream()
387 .filter(port -> port.getSecurityGroups().contains(sgRule.getSecurityGroupId()))
388 .forEach(port -> {
389 updateSecurityGroupRule(
390 instancePortService.instancePort(port.getId()),
391 port, sgRule, true);
392 log.debug("Applied security group rule {} to port {}",
393 sgRule.getId(), port.getId());
394 });
395 }
396
397 private void securityGroupRuleRemoved(SecurityGroupRule sgRule) {
398 osNetService.ports().stream()
399 .filter(port -> port.getSecurityGroups().contains(sgRule.getSecurityGroupId()))
400 .forEach(port -> {
401 updateSecurityGroupRule(
402 instancePortService.instancePort(port.getId()),
403 port, sgRule, false);
404 log.debug("Removed security group rule {} from port {}",
405 sgRule.getId(), port.getId());
406 });
407 }
408
sangho2e97be02017-07-03 18:18:27 +0900409 private int binLower(String binStr, int bits) {
410 String outBin = binStr.substring(0, 16 - bits);
411 for (int i = 0; i < bits; i++) {
412 outBin += "0";
413 }
414
415 return Integer.parseInt(outBin, 2);
416 }
417
418 private int binHigher(String binStr, int bits) {
419 String outBin = binStr.substring(0, 16 - bits);
420 for (int i = 0; i < bits; i++) {
421 outBin += "1";
422 }
423
424 return Integer.parseInt(outBin, 2);
425 }
426
427 private int testMasks(String binStr, int start, int end) {
428 int mask = 0;
429 for (; mask <= 16; mask++) {
430 int maskStart = binLower(binStr, mask);
431 int maskEnd = binHigher(binStr, mask);
432 if (maskStart < start || maskEnd > end) {
433 return mask - 1;
434 }
435 }
436
437 return mask;
438 }
439
440 private String getMask(int bits) {
441 switch (bits) {
442 case 0: return "ffff";
443 case 1: return "fffe";
444 case 2: return "fffc";
445 case 3: return "fff8";
446 case 4: return "fff0";
447 case 5: return "ffe0";
448 case 6: return "ffc0";
449 case 7: return "ff80";
450 case 8: return "ff00";
451 case 9: return "fe00";
452 case 10: return "fc00";
453 case 11: return "f800";
454 case 12: return "f000";
455 case 13: return "e000";
456 case 14: return "c000";
457 case 15: return "8000";
458 case 16: return "0000";
459 default: return null;
460 }
461 }
462
463 private Map<TpPort, TpPort> buildPortRangeMatches(int portMin, int portMax) {
464
465 boolean processing = true;
466 int start = portMin;
467 Map<TpPort, TpPort> portMaskMap = Maps.newHashMap();
468 while (processing) {
469 String minStr = Integer.toBinaryString(start);
470 String binStrMinPadded = "0000000000000000".substring(minStr.length()) + minStr;
471
472 int mask = testMasks(binStrMinPadded, start, portMax);
473 int maskStart = binLower(binStrMinPadded, mask);
474 int maskEnd = binHigher(binStrMinPadded, mask);
475
476 log.debug("start : {} port/mask = {} / {} ", start, getMask(mask), maskStart);
477 portMaskMap.put(TpPort.tpPort(maskStart), TpPort.tpPort(Integer.parseInt(getMask(mask), 16)));
478
479 start = maskEnd + 1;
480 if (start > portMax) {
481 processing = false;
482 }
483 }
484
485 return portMaskMap;
486 }
487
sangho6a9ff0d2017-03-27 11:23:37 +0900488 private class InternalInstancePortListener implements InstancePortListener {
489
490 @Override
491 public boolean isRelevant(InstancePortEvent event) {
492 InstancePort instPort = event.subject();
sangho0248ca22017-05-31 13:22:47 +0900493 if (!useSecurityGroup) {
494 return false;
495 }
sangho6a9ff0d2017-03-27 11:23:37 +0900496 return mastershipService.isLocalMaster(instPort.deviceId());
497 }
498
499 @Override
500 public void event(InstancePortEvent event) {
501 InstancePort instPort = event.subject();
502 switch (event.type()) {
503 case OPENSTACK_INSTANCE_PORT_UPDATED:
504 case OPENSTACK_INSTANCE_PORT_DETECTED:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900505 log.debug("Instance port detected MAC:{} IP:{}",
506 instPort.macAddress(),
507 instPort.ipAddress());
sangho6a9ff0d2017-03-27 11:23:37 +0900508 eventExecutor.execute(() -> {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900509 setSecurityGroupRules(instPort,
510 osNetService.port(event.subject().portId()),
511 true);
sangho6a9ff0d2017-03-27 11:23:37 +0900512 });
513 break;
514 case OPENSTACK_INSTANCE_PORT_VANISHED:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900515 log.debug("Instance port vanished MAC:{} IP:{}",
516 instPort.macAddress(),
517 instPort.ipAddress());
sangho6a9ff0d2017-03-27 11:23:37 +0900518 eventExecutor.execute(() -> {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900519 setSecurityGroupRules(instPort,
520 osNetService.port(event.subject().portId()),
521 false);
sangho6a9ff0d2017-03-27 11:23:37 +0900522 });
523 break;
524 default:
525 break;
526 }
527 }
sangho6a9ff0d2017-03-27 11:23:37 +0900528 }
529
530 private class InternalOpenstackPortListener implements OpenstackNetworkListener {
531
532 @Override
533 public boolean isRelevant(OpenstackNetworkEvent event) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900534 if (event.port() == null || !Strings.isNullOrEmpty(event.port().getId())) {
sangho6a9ff0d2017-03-27 11:23:37 +0900535 return false;
536 }
Hyunsun Moonae51e732017-04-25 17:46:21 +0900537 if (event.securityGroupId() == null ||
538 securityGroupService.securityGroup(event.securityGroupId()) == null) {
539 return false;
540 }
541 if (instancePortService.instancePort(event.port().getId()) == null) {
542 return false;
543 }
sangho0248ca22017-05-31 13:22:47 +0900544 if (!useSecurityGroup) {
545 return false;
546 }
Hyunsun Moonae51e732017-04-25 17:46:21 +0900547 return true;
sangho6a9ff0d2017-03-27 11:23:37 +0900548 }
549
550 @Override
551 public void event(OpenstackNetworkEvent event) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900552 Port osPort = event.port();
553 InstancePort instPort = instancePortService.instancePort(osPort.getId());
554 SecurityGroup osSg = securityGroupService.securityGroup(event.securityGroupId());
555
sangho6a9ff0d2017-03-27 11:23:37 +0900556 switch (event.type()) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900557 case OPENSTACK_PORT_SECURITY_GROUP_ADDED:
558 eventExecutor.execute(() -> {
559 osSg.getRules().forEach(sgRule -> {
560 updateSecurityGroupRule(instPort, osPort, sgRule, true);
561 });
562 log.info("Added security group {} to port {}",
563 event.securityGroupId(), event.port().getId());
564 });
sangho6a9ff0d2017-03-27 11:23:37 +0900565 break;
Hyunsun Moonae51e732017-04-25 17:46:21 +0900566 case OPENSTACK_PORT_SECURITY_GROUP_REMOVED:
567 eventExecutor.execute(() -> {
568 osSg.getRules().forEach(sgRule -> {
569 updateSecurityGroupRule(instPort, osPort, sgRule, false);
570 });
571 log.info("Removed security group {} from port {}",
572 event.securityGroupId(), event.port().getId());
573 });
sangho6a9ff0d2017-03-27 11:23:37 +0900574 break;
575 default:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900576 // do nothing for the other events
sangho6a9ff0d2017-03-27 11:23:37 +0900577 break;
578 }
579 }
sangho6a9ff0d2017-03-27 11:23:37 +0900580 }
581
582 private class InternalSecurityGroupListener implements OpenstackSecurityGroupListener {
583
584 @Override
sangho0248ca22017-05-31 13:22:47 +0900585 public boolean isRelevant(OpenstackSecurityGroupEvent event) {
586 if (!useSecurityGroup) {
587 return false;
588 }
589 return true;
590 }
591
592 @Override
sangho6a9ff0d2017-03-27 11:23:37 +0900593 public void event(OpenstackSecurityGroupEvent event) {
594 switch (event.type()) {
sangho6a9ff0d2017-03-27 11:23:37 +0900595 case OPENSTACK_SECURITY_GROUP_RULE_CREATED:
596 SecurityGroupRule securityGroupRuleToAdd = event.securityGroupRule();
597 eventExecutor.execute(() -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900598 securityGroupRuleAdded(securityGroupRuleToAdd);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900599 log.info("Applied new security group rule {} to ports",
600 securityGroupRuleToAdd.getId());
sangho6a9ff0d2017-03-27 11:23:37 +0900601 });
602 break;
603
604 case OPENSTACK_SECURITY_GROUP_RULE_REMOVED:
605 SecurityGroupRule securityGroupRuleToRemove = event.securityGroupRule();
606 eventExecutor.execute(() -> {
sangho6a9ff0d2017-03-27 11:23:37 +0900607 securityGroupRuleRemoved(securityGroupRuleToRemove);
Hyunsun Moonae51e732017-04-25 17:46:21 +0900608 log.info("Removed security group rule {} from ports",
609 securityGroupRuleToRemove.getId());
sangho6a9ff0d2017-03-27 11:23:37 +0900610 });
611 break;
Hyunsun Moonae51e732017-04-25 17:46:21 +0900612 case OPENSTACK_SECURITY_GROUP_CREATED:
613 case OPENSTACK_SECURITY_GROUP_REMOVED:
sangho6a9ff0d2017-03-27 11:23:37 +0900614 default:
Hyunsun Moonae51e732017-04-25 17:46:21 +0900615 // do nothing
616 break;
sangho6a9ff0d2017-03-27 11:23:37 +0900617 }
618 }
sangho6a9ff0d2017-03-27 11:23:37 +0900619 }
620}