[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
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
index 24d5f58..564ae99 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
@@ -17,6 +17,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -25,13 +26,11 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.dhcp.DhcpService;
import org.onosproject.event.AbstractEvent;
import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Port;
import org.onosproject.net.config.ConfigFactory;
@@ -42,12 +41,6 @@
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
@@ -60,6 +53,7 @@
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Collection;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -104,9 +98,6 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected FlowRuleService flowRuleService;
-
private ApplicationId appId;
private boolean doNotPushFlows;
private Ip4Address neutronServer;
@@ -136,6 +127,9 @@
}
);
+
+ private Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
+
@Activate
protected void activate() {
appId = coreService
@@ -258,13 +252,39 @@
log.debug("device {} is added", device.id());
}
- private void processPortAdded(Device device, Port port) {
- if (!port.annotations().value("portName").equals("vxlan")
- && port.isEnabled() && !doNotPushFlows) {
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, restHandler, driverService);
- rulePopulator.populateSwitchingRules(device, port);
+ private void processPortUpdated(Device device, Port port) {
+ if (!port.annotations().value("portName").equals("vxlan") && !doNotPushFlows) {
+ if (port.isEnabled()) {
+ OpenstackSwitchingRulePopulator rulePopulator =
+ new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
+ deviceService, restHandler, driverService);
+ rulePopulator.populateSwitchingRules(device, port);
+
+ OpenstackPort openstackPort = port(port);
+
+ long vni = Long.parseLong(restHandler.getNetworks().stream()
+ .filter(n -> n.id().equals(openstackPort.networkId()))
+ .findAny().orElse(null).segmentId());
+
+ OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
+ .setDeviceId(device.id())
+ .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
+ .setVNI(vni);
+
+ openstackPortInfoMap.putIfAbsent(port.annotations().value("portName"),
+ portBuilder.build());
+ }
+
+ //In case portupdate event is driven by vm shutoff from openstack
+ if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value("portName"))) {
+ log.debug("Flowrules according to the port {} were removed", port.number().toString());
+ OpenstackSwitchingRulePopulator rulePopulator =
+ new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
+ deviceService, restHandler, driverService);
+ openstackPortInfoMap.get(port.annotations().value("portName"));
+ rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
+ openstackPortInfoMap.remove(port.annotations().value("portName"));
+ }
}
}
@@ -300,46 +320,6 @@
private void processHostRemoved(Host host) {
log.debug("host {} was removed", host.toString());
-
- try {
- if (!doNotPushFlows) {
- IpAddress hostIp = host.ipAddresses().stream().
- filter(ip -> ip.isIp4()).findAny().orElse(null);
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, restHandler, driverService);
- rulePopulator.removeSwitchingRules(host.location().deviceId(),
- hostIp.getIp4Address());
- }
-
- dhcpService.removeStaticMapping(host.mac());
- } catch (NoSuchElementException e) {
- log.error("No IP address is assigned.");
- }
- }
-
- private long getVniFromFlowRules(DeviceId deviceId, Ip4Address hostIp) {
-
- for (FlowEntry flowEntry: flowRuleService.getFlowEntries(deviceId)) {
- Criterion c = flowEntry.selector().getCriterion(Criterion.Type.IPV4_DST);
- if (c != null) {
- IPCriterion destIpCriterion = (IPCriterion) c;
- if (destIpCriterion.ip().getIp4Prefix().address().equals(hostIp)) {
- for (Instruction i : flowEntry.treatment().immediate()) {
- if (i.type().equals(Instruction.Type.L2MODIFICATION)) {
- L2ModificationInstruction l2m = (L2ModificationInstruction) i;
- if (l2m.subtype().equals(L2ModificationInstruction.L2SubType.TUNNEL_ID)) {
- L2ModificationInstruction.ModTunnelIdInstruction setTunnelInstr =
- (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
- return setTunnelInstr.tunnelId();
- }
- }
- }
- }
- }
- }
-
- return 0;
}
private void registerDhcpInfo(OpenstackPort openstackPort) {
@@ -350,7 +330,7 @@
Ip4Address domainServer;
OpenstackSubnet openstackSubnet;
- ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
+ ip4Address = (Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null);
openstackSubnet = restHandler.getSubnets().stream()
.filter(n -> n.networkId().equals(openstackPort.networkId()))
@@ -442,7 +422,7 @@
case DEVICE_UPDATED:
Port port = (Port) deviceEvent.subject();
if (port.isEnabled()) {
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
}
break;
case DEVICE_AVAILABILITY_CHANGED:
@@ -452,10 +432,10 @@
}
break;
case PORT_ADDED:
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
break;
case PORT_UPDATED:
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ processPortUpdated((Device) deviceEvent.subject(), deviceEvent.port());
break;
case PORT_REMOVED:
processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
@@ -502,19 +482,4 @@
}
}
-
- private final class PortInfo {
- DeviceId deviceId;
- String portName;
- Ip4Address fixedIp;
- Ip4Address hostIp;
-
- private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
- Ip4Address hostIp) {
- this.deviceId = deviceId;
- this.portName = portName;
- this.fixedIp = fixedIp;
- this.hostIp = hostIp;
- }
- }
}
\ No newline at end of file