sangho
Committed by Ray Milkey

[ONOS-3697] Remove flow rules and dhcp mapping for router when it is removed.

Change-Id: I24e7c6d3fa0731822250c84ac5807f6192d371bf
......@@ -16,6 +16,7 @@
package org.onosproject.openstackswitching.impl;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -27,11 +28,13 @@ public final class OpenstackPortInfo {
private final Ip4Address hostIp;
private final DeviceId deviceId;
private final MacAddress hostMac;
private final long vni;
public OpenstackPortInfo(Ip4Address hostIp, DeviceId deviceId,
public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId,
long vni) {
this.hostIp = hostIp;
this.hostMac = hostMac;
this.deviceId = deviceId;
this.vni = vni;
}
......@@ -40,6 +43,10 @@ public final class OpenstackPortInfo {
return hostIp;
}
public MacAddress mac() {
return hostMac;
}
public DeviceId deviceId() {
return deviceId;
}
......@@ -54,6 +61,7 @@ public final class OpenstackPortInfo {
public static final class Builder {
private Ip4Address hostIp;
private MacAddress hostMac;
private DeviceId deviceId;
private long vni;
......@@ -62,6 +70,11 @@ public final class OpenstackPortInfo {
return this;
}
public Builder setHostMac(MacAddress hostMac) {
this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull");
return this;
}
public Builder setDeviceId(DeviceId deviceId) {
this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
return this;
......@@ -78,6 +91,7 @@ public final class OpenstackPortInfo {
private OpenstackPortInfo(Builder builder) {
hostIp = builder.hostIp;
hostMac = builder.hostMac;
deviceId = builder.deviceId;
vni = builder.vni;
}
......
......@@ -104,10 +104,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
protected DriverService driverService;
public static final String PORTNAME_PREFIX_VM = "tap";
public static final String PORTNAME_PREFIX_ROUTER = "qr";
public static final String PORTNAME_PREFIX_ROUTER = "qr-";
public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
public static final String PORTNAME = "portName";
public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
private ApplicationId appId;
private boolean doNotPushFlows;
private Ip4Address neutronServer;
......@@ -170,14 +172,38 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
@Override
public void createPorts(OpenstackPort openstackPort) {
if (!openstackPort.fixedIps().isEmpty()) {
if (!openstackPort.fixedIps().isEmpty()
&& !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
registerDhcpInfo(openstackPort);
}
}
@Override
public void deletePort(String uuid) {
// When VMs are remvoed, the flow rules for the VMs are removed using ONOS port update event.
// But, when router is removed, no ONOS port event occurs and we need to use Neutron port event.
// Here we should not touch any rules for VMs.
log.debug("port {} was removed", uuid);
String routerPortName = PORTNAME_PREFIX_ROUTER + uuid.substring(0, 11);
OpenstackPortInfo routerPortInfo = openstackPortInfoMap.get(routerPortName);
if (routerPortInfo != null) {
dhcpService.removeStaticMapping(routerPortInfo.mac());
if (!doNotPushFlows) {
deviceService.getPorts(routerPortInfo.deviceId()).forEach(port -> {
String pName = port.annotations().value("portName");
if (pName.equals(routerPortName)) {
OpenstackSwitchingRulePopulator rulePopulator =
new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
deviceService, restHandler, driverService);
rulePopulator.removeSwitchingRules(doNotPushFlows, port, openstackPortInfoMap);
openstackPortInfoMap.remove(routerPortName);
return;
}
});
}
}
}
@Override
......@@ -268,17 +294,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
OpenstackSwitchingRulePopulator rulePopulator =
new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
deviceService, restHandler, driverService);
rulePopulator.populateSwitchingRules(device, port);
rulePopulator.populateSwitchingRules(doNotPushFlows, device, port);
updatePortMap(device.id(), port, restHandler.getNetworks(), rulePopulator.openstackPort(port));
//In case portupdate event is driven by vm shutoff from openstack
} else 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);
rulePopulator.removeSwitchingRules(doNotPushFlows, port, openstackPortInfoMap);
dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
}
}
......@@ -303,9 +329,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
.forEach(vmPort -> {
OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
if (osPort != null) {
if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
if (!doNotPushFlows) {
rulePopulator.populateSwitchingRules(device, vmPort);
rulePopulator.populateSwitchingRules(doNotPushFlows, device, vmPort);
updatePortMap(device.id(), vmPort, networks, osPort);
}
registerDhcpInfo(osPort);
......@@ -327,6 +353,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
.setDeviceId(deviceId)
.setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
.setHostMac(openstackPort.macAddress())
.setVni(vni);
openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
......
......@@ -99,7 +99,10 @@ public class OpenstackSwitchingRulePopulator {
* @param device device to populate rules to
* @param port port for the VM created
*/
public void populateSwitchingRules(Device device, Port port) {
public void populateSwitchingRules(boolean doNotPushFlow, Device device, Port port) {
if (doNotPushFlow) {
return;
}
populateFlowRulesForTunnelTag(device, port);
populateFlowRulesForTrafficToSameCnode(device, port);
populateFlowRulesForTrafficToDifferentCnode(device, port);
......@@ -271,8 +274,11 @@ public class OpenstackSwitchingRulePopulator {
* @param removedPort removedport info
* @param openstackPortInfoMap openstackPortInfoMap
*/
public void removeSwitchingRules(Port removedPort, Map<String, OpenstackPortInfo> openstackPortInfoMap) {
public void removeSwitchingRules(boolean doNotPushFlows, Port removedPort, Map<String,
OpenstackPortInfo> openstackPortInfoMap) {
if (doNotPushFlows) {
return;
}
OpenstackPortInfo openstackPortInfo = openstackPortInfoMap
.get(removedPort.annotations().value("portName"));
......
......@@ -72,6 +72,9 @@ public class OpenstackPortWebResource extends AbstractWebResource {
@Path("{portUUID}")
@DELETE
public Response deletePorts(@PathParam("portUUID") String id) {
OpenstackSwitchingService switchingService =
getService(OpenstackSwitchingService.class);
switchingService.deletePort(id);
return Response.status(Response.Status.OK).build();
}
......