Daniel Park
Committed by Gerrit Code Review

[ONOS-3696] Remove flow rules when a VM is terminated

- ProcessPortAdded method name is changed to ProcessPortUpdated
- PortNumber is removed in OpenstackPortInfo class
- Checks doNotPushFlows in OpenstackSwitchingRulePopulator
- etc
- rebased

Change-Id: I215892102669799af0fd8c8ac8ea377ab7be2aad
1 +/*
2 + * Copyright 2014-2015 Open Networking Laboratory
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 + */
16 +package org.onosproject.openstackswitching;
17 +
18 +import org.onlab.packet.Ip4Address;
19 +import org.onosproject.net.DeviceId;
20 +
21 +import static com.google.common.base.Preconditions.checkNotNull;
22 +
23 +/**
24 + * Contains OpenstackPort Information.
25 + */
26 +public final class OpenstackPortInfo {
27 +
28 + private final Ip4Address hostIp;
29 + private final DeviceId deviceId;
30 + private final long vni;
31 +
32 + public OpenstackPortInfo(Ip4Address hostIp, DeviceId deviceId,
33 + long vni) {
34 + this.hostIp = hostIp;
35 + this.deviceId = deviceId;
36 + this.vni = vni;
37 + }
38 +
39 + public Ip4Address ip() {
40 + return hostIp;
41 + }
42 +
43 + public DeviceId deviceId() {
44 + return deviceId;
45 + }
46 +
47 + public long vni() {
48 + return vni;
49 + }
50 +
51 + public static OpenstackPortInfo.Builder builder() {
52 + return new Builder();
53 + }
54 +
55 + public static final class Builder {
56 + private Ip4Address hostIp;
57 + private DeviceId deviceId;
58 + private long vni;
59 +
60 + public Builder setHostIp(Ip4Address hostIp) {
61 + this.hostIp = checkNotNull(hostIp, "hostIp cannot be null");
62 + return this;
63 + }
64 +
65 + public Builder setDeviceId(DeviceId deviceId) {
66 + this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
67 + return this;
68 + }
69 +
70 + public Builder setVNI(long vni) {
71 + this.vni = checkNotNull(vni, "vni cannot be null");
72 + return this;
73 + }
74 + public OpenstackPortInfo build() {
75 + return new OpenstackPortInfo(this);
76 + }
77 + }
78 +
79 + private OpenstackPortInfo(Builder builder) {
80 + hostIp = builder.hostIp;
81 + deviceId = builder.deviceId;
82 + vni = builder.vni;
83 + }
84 +}
...@@ -17,6 +17,7 @@ package org.onosproject.openstackswitching; ...@@ -17,6 +17,7 @@ package org.onosproject.openstackswitching;
17 17
18 import com.google.common.collect.ImmutableSet; 18 import com.google.common.collect.ImmutableSet;
19 import com.google.common.collect.Lists; 19 import com.google.common.collect.Lists;
20 +import com.google.common.collect.Maps;
20 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -25,13 +26,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -25,13 +26,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
25 import org.apache.felix.scr.annotations.Service; 26 import org.apache.felix.scr.annotations.Service;
26 import org.onlab.packet.Ethernet; 27 import org.onlab.packet.Ethernet;
27 import org.onlab.packet.Ip4Address; 28 import org.onlab.packet.Ip4Address;
28 -import org.onlab.packet.IpAddress;
29 import org.onosproject.core.ApplicationId; 29 import org.onosproject.core.ApplicationId;
30 import org.onosproject.core.CoreService; 30 import org.onosproject.core.CoreService;
31 import org.onosproject.dhcp.DhcpService; 31 import org.onosproject.dhcp.DhcpService;
32 import org.onosproject.event.AbstractEvent; 32 import org.onosproject.event.AbstractEvent;
33 import org.onosproject.net.Device; 33 import org.onosproject.net.Device;
34 -import org.onosproject.net.DeviceId;
35 import org.onosproject.net.Host; 34 import org.onosproject.net.Host;
36 import org.onosproject.net.Port; 35 import org.onosproject.net.Port;
37 import org.onosproject.net.config.ConfigFactory; 36 import org.onosproject.net.config.ConfigFactory;
...@@ -42,12 +41,6 @@ import org.onosproject.net.device.DeviceEvent; ...@@ -42,12 +41,6 @@ import org.onosproject.net.device.DeviceEvent;
42 import org.onosproject.net.device.DeviceListener; 41 import org.onosproject.net.device.DeviceListener;
43 import org.onosproject.net.device.DeviceService; 42 import org.onosproject.net.device.DeviceService;
44 import org.onosproject.net.driver.DriverService; 43 import org.onosproject.net.driver.DriverService;
45 -import org.onosproject.net.flow.FlowEntry;
46 -import org.onosproject.net.flow.FlowRuleService;
47 -import org.onosproject.net.flow.criteria.Criterion;
48 -import org.onosproject.net.flow.criteria.IPCriterion;
49 -import org.onosproject.net.flow.instructions.Instruction;
50 -import org.onosproject.net.flow.instructions.L2ModificationInstruction;
51 import org.onosproject.net.flowobjective.FlowObjectiveService; 44 import org.onosproject.net.flowobjective.FlowObjectiveService;
52 import org.onosproject.net.host.HostEvent; 45 import org.onosproject.net.host.HostEvent;
53 import org.onosproject.net.host.HostListener; 46 import org.onosproject.net.host.HostListener;
...@@ -60,6 +53,7 @@ import org.slf4j.Logger; ...@@ -60,6 +53,7 @@ import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory; 53 import org.slf4j.LoggerFactory;
61 import java.util.List; 54 import java.util.List;
62 import java.util.Collection; 55 import java.util.Collection;
56 +import java.util.Map;
63 import java.util.NoSuchElementException; 57 import java.util.NoSuchElementException;
64 import java.util.Set; 58 import java.util.Set;
65 import java.util.concurrent.ExecutorService; 59 import java.util.concurrent.ExecutorService;
...@@ -104,9 +98,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -104,9 +98,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected DriverService driverService; 99 protected DriverService driverService;
106 100
107 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 - protected FlowRuleService flowRuleService;
109 -
110 private ApplicationId appId; 101 private ApplicationId appId;
111 private boolean doNotPushFlows; 102 private boolean doNotPushFlows;
112 private Ip4Address neutronServer; 103 private Ip4Address neutronServer;
...@@ -136,6 +127,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -136,6 +127,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
136 } 127 }
137 ); 128 );
138 129
130 +
131 + private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
132 +
139 @Activate 133 @Activate
140 protected void activate() { 134 protected void activate() {
141 appId = coreService 135 appId = coreService
...@@ -258,13 +252,39 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -258,13 +252,39 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
258 log.debug("device {} is added", device.id()); 252 log.debug("device {} is added", device.id());
259 } 253 }
260 254
261 - private void processPortAdded(Device device, Port port) { 255 + private void processPortUpdated(Device device, Port port) {
262 - if (!port.annotations().value("portName").equals("vxlan") 256 + if (!port.annotations().value("portName").equals("vxlan") && !doNotPushFlows) {
263 - && port.isEnabled() && !doNotPushFlows) { 257 + if (port.isEnabled()) {
264 - OpenstackSwitchingRulePopulator rulePopulator = 258 + OpenstackSwitchingRulePopulator rulePopulator =
265 - new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, 259 + new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
266 - deviceService, restHandler, driverService); 260 + deviceService, restHandler, driverService);
267 - rulePopulator.populateSwitchingRules(device, port); 261 + rulePopulator.populateSwitchingRules(device, port);
262 +
263 + OpenstackPort openstackPort = port(port);
264 +
265 + long vni = Long.parseLong(restHandler.getNetworks().stream()
266 + .filter(n -> n.id().equals(openstackPort.networkId()))
267 + .findAny().orElse(null).segmentId());
268 +
269 + OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
270 + .setDeviceId(device.id())
271 + .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
272 + .setVNI(vni);
273 +
274 + openstackPortInfoMap.putIfAbsent(port.annotations().value("portName"),
275 + portBuilder.build());
276 + }
277 +
278 + //In case portupdate event is driven by vm shutoff from openstack
279 + if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value("portName"))) {
280 + log.debug("Flowrules according to the port {} were removed", port.number().toString());
281 + OpenstackSwitchingRulePopulator rulePopulator =
282 + new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
283 + deviceService, restHandler, driverService);
284 + openstackPortInfoMap.get(port.annotations().value("portName"));
285 + rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
286 + openstackPortInfoMap.remove(port.annotations().value("portName"));
287 + }
268 } 288 }
269 } 289 }
270 290
...@@ -300,46 +320,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -300,46 +320,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
300 320
301 private void processHostRemoved(Host host) { 321 private void processHostRemoved(Host host) {
302 log.debug("host {} was removed", host.toString()); 322 log.debug("host {} was removed", host.toString());
303 -
304 - try {
305 - if (!doNotPushFlows) {
306 - IpAddress hostIp = host.ipAddresses().stream().
307 - filter(ip -> ip.isIp4()).findAny().orElse(null);
308 - OpenstackSwitchingRulePopulator rulePopulator =
309 - new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
310 - deviceService, restHandler, driverService);
311 - rulePopulator.removeSwitchingRules(host.location().deviceId(),
312 - hostIp.getIp4Address());
313 - }
314 -
315 - dhcpService.removeStaticMapping(host.mac());
316 - } catch (NoSuchElementException e) {
317 - log.error("No IP address is assigned.");
318 - }
319 - }
320 -
321 - private long getVniFromFlowRules(DeviceId deviceId, Ip4Address hostIp) {
322 -
323 - for (FlowEntry flowEntry: flowRuleService.getFlowEntries(deviceId)) {
324 - Criterion c = flowEntry.selector().getCriterion(Criterion.Type.IPV4_DST);
325 - if (c != null) {
326 - IPCriterion destIpCriterion = (IPCriterion) c;
327 - if (destIpCriterion.ip().getIp4Prefix().address().equals(hostIp)) {
328 - for (Instruction i : flowEntry.treatment().immediate()) {
329 - if (i.type().equals(Instruction.Type.L2MODIFICATION)) {
330 - L2ModificationInstruction l2m = (L2ModificationInstruction) i;
331 - if (l2m.subtype().equals(L2ModificationInstruction.L2SubType.TUNNEL_ID)) {
332 - L2ModificationInstruction.ModTunnelIdInstruction setTunnelInstr =
333 - (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
334 - return setTunnelInstr.tunnelId();
335 - }
336 - }
337 - }
338 - }
339 - }
340 - }
341 -
342 - return 0;
343 } 323 }
344 324
345 private void registerDhcpInfo(OpenstackPort openstackPort) { 325 private void registerDhcpInfo(OpenstackPort openstackPort) {
...@@ -350,7 +330,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -350,7 +330,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
350 Ip4Address domainServer; 330 Ip4Address domainServer;
351 OpenstackSubnet openstackSubnet; 331 OpenstackSubnet openstackSubnet;
352 332
353 - ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0]; 333 + ip4Address = (Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null);
354 334
355 openstackSubnet = restHandler.getSubnets().stream() 335 openstackSubnet = restHandler.getSubnets().stream()
356 .filter(n -> n.networkId().equals(openstackPort.networkId())) 336 .filter(n -> n.networkId().equals(openstackPort.networkId()))
...@@ -442,7 +422,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -442,7 +422,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
442 case DEVICE_UPDATED: 422 case DEVICE_UPDATED:
443 Port port = (Port) deviceEvent.subject(); 423 Port port = (Port) deviceEvent.subject();
444 if (port.isEnabled()) { 424 if (port.isEnabled()) {
445 - processPortAdded((Device) deviceEvent.subject(), deviceEvent.port()); 425 + processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
446 } 426 }
447 break; 427 break;
448 case DEVICE_AVAILABILITY_CHANGED: 428 case DEVICE_AVAILABILITY_CHANGED:
...@@ -452,10 +432,10 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -452,10 +432,10 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
452 } 432 }
453 break; 433 break;
454 case PORT_ADDED: 434 case PORT_ADDED:
455 - processPortAdded((Device) deviceEvent.subject(), deviceEvent.port()); 435 + processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
456 break; 436 break;
457 case PORT_UPDATED: 437 case PORT_UPDATED:
458 - processPortAdded((Device) deviceEvent.subject(), deviceEvent.port()); 438 + processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
459 break; 439 break;
460 case PORT_REMOVED: 440 case PORT_REMOVED:
461 processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port()); 441 processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
...@@ -502,19 +482,4 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -502,19 +482,4 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
502 } 482 }
503 483
504 } 484 }
505 -
506 - private final class PortInfo {
507 - DeviceId deviceId;
508 - String portName;
509 - Ip4Address fixedIp;
510 - Ip4Address hostIp;
511 -
512 - private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
513 - Ip4Address hostIp) {
514 - this.deviceId = deviceId;
515 - this.portName = portName;
516 - this.fixedIp = fixedIp;
517 - this.hostIp = hostIp;
518 - }
519 - }
520 } 485 }
...\ No newline at end of file ...\ No newline at end of file
......