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 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.openstackswitching.impl; 16 package org.onosproject.openstackswitching.impl;
17 17
18 import org.onlab.packet.Ip4Address; 18 import org.onlab.packet.Ip4Address;
19 +import org.onlab.packet.MacAddress;
19 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
20 21
21 import static com.google.common.base.Preconditions.checkNotNull; 22 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -27,11 +28,13 @@ public final class OpenstackPortInfo { ...@@ -27,11 +28,13 @@ public final class OpenstackPortInfo {
27 28
28 private final Ip4Address hostIp; 29 private final Ip4Address hostIp;
29 private final DeviceId deviceId; 30 private final DeviceId deviceId;
31 + private final MacAddress hostMac;
30 private final long vni; 32 private final long vni;
31 33
32 - public OpenstackPortInfo(Ip4Address hostIp, DeviceId deviceId, 34 + public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId,
33 long vni) { 35 long vni) {
34 this.hostIp = hostIp; 36 this.hostIp = hostIp;
37 + this.hostMac = hostMac;
35 this.deviceId = deviceId; 38 this.deviceId = deviceId;
36 this.vni = vni; 39 this.vni = vni;
37 } 40 }
...@@ -40,6 +43,10 @@ public final class OpenstackPortInfo { ...@@ -40,6 +43,10 @@ public final class OpenstackPortInfo {
40 return hostIp; 43 return hostIp;
41 } 44 }
42 45
46 + public MacAddress mac() {
47 + return hostMac;
48 + }
49 +
43 public DeviceId deviceId() { 50 public DeviceId deviceId() {
44 return deviceId; 51 return deviceId;
45 } 52 }
...@@ -54,6 +61,7 @@ public final class OpenstackPortInfo { ...@@ -54,6 +61,7 @@ public final class OpenstackPortInfo {
54 61
55 public static final class Builder { 62 public static final class Builder {
56 private Ip4Address hostIp; 63 private Ip4Address hostIp;
64 + private MacAddress hostMac;
57 private DeviceId deviceId; 65 private DeviceId deviceId;
58 private long vni; 66 private long vni;
59 67
...@@ -62,6 +70,11 @@ public final class OpenstackPortInfo { ...@@ -62,6 +70,11 @@ public final class OpenstackPortInfo {
62 return this; 70 return this;
63 } 71 }
64 72
73 + public Builder setHostMac(MacAddress hostMac) {
74 + this.hostMac = checkNotNull(hostMac, "hostMac cannot be bull");
75 + return this;
76 + }
77 +
65 public Builder setDeviceId(DeviceId deviceId) { 78 public Builder setDeviceId(DeviceId deviceId) {
66 this.deviceId = checkNotNull(deviceId, "deviceId cannot be null"); 79 this.deviceId = checkNotNull(deviceId, "deviceId cannot be null");
67 return this; 80 return this;
...@@ -78,6 +91,7 @@ public final class OpenstackPortInfo { ...@@ -78,6 +91,7 @@ public final class OpenstackPortInfo {
78 91
79 private OpenstackPortInfo(Builder builder) { 92 private OpenstackPortInfo(Builder builder) {
80 hostIp = builder.hostIp; 93 hostIp = builder.hostIp;
94 + hostMac = builder.hostMac;
81 deviceId = builder.deviceId; 95 deviceId = builder.deviceId;
82 vni = builder.vni; 96 vni = builder.vni;
83 } 97 }
......
...@@ -104,10 +104,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -104,10 +104,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
104 protected DriverService driverService; 104 protected DriverService driverService;
105 105
106 public static final String PORTNAME_PREFIX_VM = "tap"; 106 public static final String PORTNAME_PREFIX_VM = "tap";
107 - public static final String PORTNAME_PREFIX_ROUTER = "qr"; 107 + public static final String PORTNAME_PREFIX_ROUTER = "qr-";
108 public static final String PORTNAME_PREFIX_TUNNEL = "vxlan"; 108 public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
109 public static final String PORTNAME = "portName"; 109 public static final String PORTNAME = "portName";
110 110
111 + public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
112 +
111 private ApplicationId appId; 113 private ApplicationId appId;
112 private boolean doNotPushFlows; 114 private boolean doNotPushFlows;
113 private Ip4Address neutronServer; 115 private Ip4Address neutronServer;
...@@ -170,14 +172,38 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -170,14 +172,38 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
170 172
171 @Override 173 @Override
172 public void createPorts(OpenstackPort openstackPort) { 174 public void createPorts(OpenstackPort openstackPort) {
173 - if (!openstackPort.fixedIps().isEmpty()) { 175 + if (!openstackPort.fixedIps().isEmpty()
176 + && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
174 registerDhcpInfo(openstackPort); 177 registerDhcpInfo(openstackPort);
175 } 178 }
176 } 179 }
177 180
178 @Override 181 @Override
179 public void deletePort(String uuid) { 182 public void deletePort(String uuid) {
183 + // When VMs are remvoed, the flow rules for the VMs are removed using ONOS port update event.
184 + // But, when router is removed, no ONOS port event occurs and we need to use Neutron port event.
185 + // Here we should not touch any rules for VMs.
186 + log.debug("port {} was removed", uuid);
187 +
188 + String routerPortName = PORTNAME_PREFIX_ROUTER + uuid.substring(0, 11);
189 + OpenstackPortInfo routerPortInfo = openstackPortInfoMap.get(routerPortName);
190 + if (routerPortInfo != null) {
191 + dhcpService.removeStaticMapping(routerPortInfo.mac());
192 + if (!doNotPushFlows) {
193 + deviceService.getPorts(routerPortInfo.deviceId()).forEach(port -> {
194 + String pName = port.annotations().value("portName");
195 + if (pName.equals(routerPortName)) {
196 + OpenstackSwitchingRulePopulator rulePopulator =
197 + new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
198 + deviceService, restHandler, driverService);
180 199
200 + rulePopulator.removeSwitchingRules(doNotPushFlows, port, openstackPortInfoMap);
201 + openstackPortInfoMap.remove(routerPortName);
202 + return;
203 + }
204 + });
205 + }
206 + }
181 } 207 }
182 208
183 @Override 209 @Override
...@@ -268,17 +294,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -268,17 +294,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
268 OpenstackSwitchingRulePopulator rulePopulator = 294 OpenstackSwitchingRulePopulator rulePopulator =
269 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, 295 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
270 deviceService, restHandler, driverService); 296 deviceService, restHandler, driverService);
271 - rulePopulator.populateSwitchingRules(device, port); 297 + rulePopulator.populateSwitchingRules(doNotPushFlows, device, port);
272 updatePortMap(device.id(), port, restHandler.getNetworks(), rulePopulator.openstackPort(port)); 298 updatePortMap(device.id(), port, restHandler.getNetworks(), rulePopulator.openstackPort(port));
273 -
274 //In case portupdate event is driven by vm shutoff from openstack 299 //In case portupdate event is driven by vm shutoff from openstack
275 } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value(PORTNAME))) { 300 } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value(PORTNAME))) {
276 log.debug("Flowrules according to the port {} were removed", port.number().toString()); 301 log.debug("Flowrules according to the port {} were removed", port.number().toString());
277 OpenstackSwitchingRulePopulator rulePopulator = 302 OpenstackSwitchingRulePopulator rulePopulator =
278 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, 303 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
279 deviceService, restHandler, driverService); 304 deviceService, restHandler, driverService);
280 - openstackPortInfoMap.get(port.annotations().value(PORTNAME)); 305 +
281 - rulePopulator.removeSwitchingRules(port, openstackPortInfoMap); 306 + rulePopulator.removeSwitchingRules(doNotPushFlows, port, openstackPortInfoMap);
307 + dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
282 openstackPortInfoMap.remove(port.annotations().value(PORTNAME)); 308 openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
283 } 309 }
284 } 310 }
...@@ -303,9 +329,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -303,9 +329,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
303 port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER)) 329 port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
304 .forEach(vmPort -> { 330 .forEach(vmPort -> {
305 OpenstackPort osPort = rulePopulator.openstackPort(vmPort); 331 OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
306 - if (osPort != null) { 332 + if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
307 if (!doNotPushFlows) { 333 if (!doNotPushFlows) {
308 - rulePopulator.populateSwitchingRules(device, vmPort); 334 + rulePopulator.populateSwitchingRules(doNotPushFlows, device, vmPort);
309 updatePortMap(device.id(), vmPort, networks, osPort); 335 updatePortMap(device.id(), vmPort, networks, osPort);
310 } 336 }
311 registerDhcpInfo(osPort); 337 registerDhcpInfo(osPort);
...@@ -327,6 +353,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -327,6 +353,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
327 OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder() 353 OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
328 .setDeviceId(deviceId) 354 .setDeviceId(deviceId)
329 .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null)) 355 .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
356 + .setHostMac(openstackPort.macAddress())
330 .setVni(vni); 357 .setVni(vni);
331 358
332 openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME), 359 openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
......
...@@ -99,7 +99,10 @@ public class OpenstackSwitchingRulePopulator { ...@@ -99,7 +99,10 @@ public class OpenstackSwitchingRulePopulator {
99 * @param device device to populate rules to 99 * @param device device to populate rules to
100 * @param port port for the VM created 100 * @param port port for the VM created
101 */ 101 */
102 - public void populateSwitchingRules(Device device, Port port) { 102 + public void populateSwitchingRules(boolean doNotPushFlow, Device device, Port port) {
103 + if (doNotPushFlow) {
104 + return;
105 + }
103 populateFlowRulesForTunnelTag(device, port); 106 populateFlowRulesForTunnelTag(device, port);
104 populateFlowRulesForTrafficToSameCnode(device, port); 107 populateFlowRulesForTrafficToSameCnode(device, port);
105 populateFlowRulesForTrafficToDifferentCnode(device, port); 108 populateFlowRulesForTrafficToDifferentCnode(device, port);
...@@ -271,8 +274,11 @@ public class OpenstackSwitchingRulePopulator { ...@@ -271,8 +274,11 @@ public class OpenstackSwitchingRulePopulator {
271 * @param removedPort removedport info 274 * @param removedPort removedport info
272 * @param openstackPortInfoMap openstackPortInfoMap 275 * @param openstackPortInfoMap openstackPortInfoMap
273 */ 276 */
274 - public void removeSwitchingRules(Port removedPort, Map<String, OpenstackPortInfo> openstackPortInfoMap) { 277 + public void removeSwitchingRules(boolean doNotPushFlows, Port removedPort, Map<String,
275 - 278 + OpenstackPortInfo> openstackPortInfoMap) {
279 + if (doNotPushFlows) {
280 + return;
281 + }
276 OpenstackPortInfo openstackPortInfo = openstackPortInfoMap 282 OpenstackPortInfo openstackPortInfo = openstackPortInfoMap
277 .get(removedPort.annotations().value("portName")); 283 .get(removedPort.annotations().value("portName"));
278 284
......
...@@ -72,6 +72,9 @@ public class OpenstackPortWebResource extends AbstractWebResource { ...@@ -72,6 +72,9 @@ public class OpenstackPortWebResource extends AbstractWebResource {
72 @Path("{portUUID}") 72 @Path("{portUUID}")
73 @DELETE 73 @DELETE
74 public Response deletePorts(@PathParam("portUUID") String id) { 74 public Response deletePorts(@PathParam("portUUID") String id) {
75 + OpenstackSwitchingService switchingService =
76 + getService(OpenstackSwitchingService.class);
77 + switchingService.deletePort(id);
75 return Response.status(Response.Status.OK).build(); 78 return Response.status(Response.Status.OK).build();
76 } 79 }
77 80
......