Refactored OpenstackSwitching app
[DONE]
- Restructured to activate or deactivate switching and routing app separately
- Fixed to add or remove host when port is detected or vanished
- Use openstack node service to get integration bridges and data IP
[TODO]
- Remove use of OpenstackPortInfo
- Support installing flow rules for exising VMs
- Call security group update method when port update triggered from OpenStack
Change-Id: Ic0b2ac3f7ab07f0e20c97c6edfdd1928b9767baf
diff --git a/apps/openstacknetworking/BUCK b/apps/openstacknetworking/BUCK
index 03639d1..3176898 100644
--- a/apps/openstacknetworking/BUCK
+++ b/apps/openstacknetworking/BUCK
@@ -8,5 +8,5 @@
category = 'Utility',
url = 'http://onosproject.org',
included_bundles = BUNDLES,
- required_apps = [ 'org.onosproject.openstackinterface' ],
+ required_apps = [ 'org.onosproject.openstackrouting', 'org.onosproject.openstackswitching' ]
)
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
index 6217bf3..b40b865 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackPortInfo.java
@@ -19,14 +19,12 @@
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
-import java.util.Collection;
-import java.util.Collections;
-
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Contains OpenstackPort Information.
*/
+// TODO remove this
public final class OpenstackPortInfo {
private final Ip4Address hostIp;
private final MacAddress hostMac;
@@ -34,7 +32,6 @@
private final long vni;
private final Ip4Address gatewayIP;
private final String networkId;
- private final Collection<String> securityGroups;
/**
* Returns OpenstackPortInfo reference.
@@ -45,17 +42,15 @@
* @param vni tunnel ID
* @param gatewayIP gateway IP address
* @param networkId network identifier
- * @param securityGroups security group list
*/
public OpenstackPortInfo(Ip4Address hostIp, MacAddress hostMac, DeviceId deviceId, long vni,
- Ip4Address gatewayIP, String networkId, Collection<String> securityGroups) {
+ Ip4Address gatewayIP, String networkId) {
this.hostIp = hostIp;
this.hostMac = hostMac;
this.deviceId = deviceId;
this.vni = vni;
this.gatewayIP = gatewayIP;
this.networkId = networkId;
- this.securityGroups = securityGroups;
}
/**
@@ -113,15 +108,6 @@
}
/**
- * Returns Security Group ID list.
- *
- * @return list of Security Group ID
- */
- public Collection<String> securityGroups() {
- return Collections.unmodifiableCollection(securityGroups);
- }
-
- /**
* Returns the builder of the OpenstackPortInfo.
*
* @return OpenstackPortInfo builder reference
@@ -140,7 +126,6 @@
private DeviceId deviceId;
private long vni;
private Ip4Address gatewayIP;
- private Collection<String> securityGroups;
private String networkId;
/**
@@ -210,23 +195,12 @@
}
/**
- * Sets the security group ID list.
- *
- * @param securityGroups security group ID list
- * @return Builder reference
- */
- public Builder setSecurityGroups(Collection<String> securityGroups) {
- this.securityGroups = securityGroups;
- return this;
- }
-
- /**
* Builds the OpenstackPortInfo reference.
*
* @return OpenstackPortInfo reference
*/
public OpenstackPortInfo build() {
- return new OpenstackPortInfo(hostIp, hostMac, deviceId, vni, gatewayIP, networkId, securityGroups);
+ return new OpenstackPortInfo(hostIp, hostMac, deviceId, vni, gatewayIP, networkId);
}
}
}
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackSwitchingService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackSwitchingService.java
index 31dd9aa..c9f32ab 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackSwitchingService.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackSwitchingService.java
@@ -15,57 +15,19 @@
*/
package org.onosproject.openstacknetworking;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstackinterface.OpenstackSubnet;
-
import java.util.Map;
/**
* Handles port management REST API from Openstack for VMs.
*/
+// TODO remove this
public interface OpenstackSwitchingService {
/**
- * Store the port information created by Openstack.
- *
- * @param openstackPort port information
- */
- void createPorts(OpenstackPort openstackPort);
-
- /**
- * Removes flow rules corresponding to the port removed by Openstack.
- *
- * @param uuid UUID
- */
- void removePort(String uuid);
-
- /**
- * Updates flow rules corresponding to the port information updated by Openstack.
- *
- * @param openstackPort OpenStack port
- */
- void updatePort(OpenstackPort openstackPort);
-
- /**
- * Stores the network information created by openstack.
- *
- * @param openstackNetwork network information
- */
- void createNetwork(OpenstackNetwork openstackNetwork);
-
- /**
- * Stores the subnet information created by openstack.
- *
- * @param openstackSubnet subnet information
- */
- void createSubnet(OpenstackSubnet openstackSubnet);
-
- /**
* Retruns OpenstackPortInfo map.
*
* @return OpenstackPortInfo map
*/
+ // TODO remove this
Map<String, OpenstackPortInfo> openstackPortInfo();
-
}
diff --git a/apps/openstacknetworking/app/app.xml b/apps/openstacknetworking/app/app.xml
deleted file mode 100644
index 181c6af..0000000
--- a/apps/openstacknetworking/app/app.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<app name="org.onosproject.openstacknetworking" origin="ON.Lab" version="${project.version}"
- category="Utility" url="http://onosproject.org" title="OpenStack Networking App"
- featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
- features="${project.artifactId}"
- apps="org.onosproject.openstackswitching,org.onosproject.openstackrouting">
- <description>${project.description}</description>
- <artifact>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</artifact>
- <artifact>mvn:${project.groupId}/onos-app-openstacknetworking-web/${project.version}</artifact>
-</app>
diff --git a/apps/openstacknetworking/app/pom.xml b/apps/openstacknetworking/app/pom.xml
deleted file mode 100644
index 21a622d..0000000
--- a/apps/openstacknetworking/app/pom.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-openstacknetworking</artifactId>
- <version>1.7.0-SNAPSHOT</version>
- </parent>
-
- <artifactId>onos-app-openstacknetworking-app</artifactId>
- <packaging>pom</packaging>
-
- <properties>
- <onos.app.readme>Openstack Networking Application.</onos.app.readme>
- </properties>
-
- <description>SONA Openstack Networking main Application</description>
-
- <dependencies>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-openstackswitching</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-openstackrouting</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-openstacknetworking-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-openstacknetworking-web</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
-</project>
diff --git a/apps/openstacknetworking/openstackrouting/app.xml b/apps/openstacknetworking/openstackrouting/app.xml
deleted file mode 100644
index a2a373c..0000000
--- a/apps/openstacknetworking/openstackrouting/app.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<app name="org.onosproject.openstackrouting" origin="ON.Lab" version="${project.version}"
- category="default" url="http://onosproject.org"
- featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
- features="${project.artifactId}" >
- <description>${project.description}</description>
- <artifact>mvn:${project.groupId}/onos-app-openstackrouting/${project.version}</artifact>
- <artifact>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</artifact>
-</app>
diff --git a/apps/openstacknetworking/openstackrouting/features.xml b/apps/openstacknetworking/openstackrouting/features.xml
deleted file mode 100644
index 4c9eca4..0000000
--- a/apps/openstacknetworking/openstackrouting/features.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <feature name="${project.artifactId}" version="${project.version}"
- description="${project.description}">
- <feature>onos-api</feature>
- <bundle>mvn:${project.groupId}/onos-app-openstackrouting/${project.version}</bundle>
- <bundle>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</bundle>
- </feature>
-</features>
diff --git a/apps/openstacknetworking/openstackswitching/app.xml b/apps/openstacknetworking/openstackswitching/app.xml
deleted file mode 100644
index 657b70a..0000000
--- a/apps/openstacknetworking/openstackswitching/app.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<app name="org.onosproject.openstackswitching" origin="ON.Lab" version="${project.version}"
- category="default" url="http://onosproject.org"
- featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
- features="${project.artifactId}"
- apps="org.onosproject.dhcp">
- <description>${project.description}</description>
- <artifact>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</artifact>
- <artifact>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</artifact>
-</app>
diff --git a/apps/openstacknetworking/openstackswitching/features.xml b/apps/openstacknetworking/openstackswitching/features.xml
deleted file mode 100644
index ddbe726..0000000
--- a/apps/openstacknetworking/openstackswitching/features.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!--
- ~ Copyright 2016-present Open Networking Laboratory
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <feature name="${project.artifactId}" version="${project.version}"
- description="${project.description}">
- <feature>onos-api</feature>
- <bundle>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</bundle>
- <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</bundle>
- </feature>
-</features>
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java
deleted file mode 100644
index 48398fd..0000000
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-* Copyright 2016-present Open Networking Laboratory
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-package org.onosproject.openstacknetworking.switching;
-
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.openstackinterface.OpenstackInterfaceService;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstacknetworking.OpenstackPortInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.nio.ByteBuffer;
-import java.util.Collection;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Handles ARP packet from VMs.
- */
-public class OpenstackArpHandler {
-
- private static Logger log = LoggerFactory
- .getLogger(OpenstackArpHandler.class);
- private static final MacAddress GATEWAY_MAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
- private PacketService packetService;
- private OpenstackInterfaceService openstackService;
- private HostService hostService;
-
- /**
- * Returns OpenstackArpHandler reference.
- *
- * @param openstackService OpenstackNetworkingService reference
- * @param packetService PacketService reference
- * @param hostService host service
- */
- public OpenstackArpHandler(OpenstackInterfaceService openstackService, PacketService packetService,
- HostService hostService) {
- this.openstackService = openstackService;
- this.packetService = packetService;
- this.hostService = hostService;
- }
-
- /**
- * Processes ARP request packets.
- * It checks if the target IP is owned by a known host first and then ask to
- * OpenStack if it's not. This ARP proxy does not support overlapping IP.
- *
- * @param pkt ARP request packet
- * @param openstackPortInfoCollection collection of port information
- */
- public void processPacketIn(InboundPacket pkt, Collection<OpenstackPortInfo> openstackPortInfoCollection) {
- Ethernet ethRequest = pkt.parsed();
- ARP arp = (ARP) ethRequest.getPayload();
-
- if (arp.getOpCode() != ARP.OP_REQUEST) {
- return;
- }
-
- IpAddress sourceIp = Ip4Address.valueOf(arp.getSenderProtocolAddress());
- MacAddress srcMac = MacAddress.valueOf(arp.getSenderHardwareAddress());
- OpenstackPortInfo portInfo = openstackPortInfoCollection.stream()
- .filter(p -> p.ip().equals(sourceIp) && p.mac().equals(srcMac)).findFirst().orElse(null);
- IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
-
- MacAddress dstMac;
-
- if (targetIp.equals(portInfo == null ? null : portInfo.gatewayIP())) {
- dstMac = GATEWAY_MAC;
- } else {
- dstMac = getMacFromHostService(targetIp);
- if (dstMac == null) {
- dstMac = getMacFromOpenstack(targetIp);
- }
- }
-
- if (dstMac == null) {
- log.debug("Failed to find MAC address for {}", targetIp.toString());
- return;
- }
-
- Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
- dstMac,
- ethRequest);
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(pkt.receivedFrom().port())
- .build();
-
- packetService.emit(new DefaultOutboundPacket(
- pkt.receivedFrom().deviceId(),
- treatment,
- ByteBuffer.wrap(ethReply.serialize())));
- }
-
- /**
- * Returns MAC address of a host with a given target IP address by asking to
- * OpenStack. It does not support overlapping IP.
- *
- * @param targetIp target ip address
- * @return mac address, or null if it fails to fetch the mac
- */
- private MacAddress getMacFromOpenstack(IpAddress targetIp) {
- checkNotNull(targetIp);
-
- OpenstackPort openstackPort = openstackService.ports()
- .stream()
- .filter(port -> port.fixedIps().containsValue(targetIp))
- .findFirst()
- .orElse(null);
-
- if (openstackPort != null) {
- log.debug("Found MAC from OpenStack for {}", targetIp.toString());
- return openstackPort.macAddress();
- } else {
- return null;
- }
- }
-
- /**
- * Returns MAC address of a host with a given target IP address by asking to
- * host service. It does not support overlapping IP.
- *
- * @param targetIp target ip
- * @return mac address, or null if it fails to find the mac
- */
- private MacAddress getMacFromHostService(IpAddress targetIp) {
- checkNotNull(targetIp);
-
- Host host = hostService.getHostsByIp(targetIp)
- .stream()
- .findFirst()
- .orElse(null);
-
- if (host != null) {
- log.debug("Found MAC from host service for {}", targetIp.toString());
- return host.mac();
- } else {
- return null;
- }
- }
-}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
deleted file mode 100644
index dcc1c52..0000000
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
-* Copyright 2016-present Open Networking Laboratory
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package org.onosproject.openstacknetworking.switching;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.TpPort;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.openstackinterface.OpenstackInterfaceService;
-import org.onosproject.openstackinterface.OpenstackSecurityGroup;
-import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
-import org.onosproject.openstacknetworking.OpenstackPortInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Map;
-
-/**
- * Populates flows rules for Security Groups of VMs.
- *
- */
-public class OpenstackSecurityGroupRulePopulator {
-
- private static Logger log = LoggerFactory
- .getLogger(OpenstackSecurityGroupRulePopulator.class);
-
- private OpenstackInterfaceService openstackService;
- private FlowObjectiveService flowObjectiveService;
-
- private ApplicationId appId;
-
- private static final String PROTO_ICMP = "ICMP";
- private static final String PROTO_TCP = "TCP";
- private static final String PROTO_UDP = "UDP";
-
- private static final String ETHTYPE_IPV4 = "IPV4";
-
- private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
-
- private static final int ACL_RULE_PRIORITY = 30000;
-
- /**
- * Constructor.
- *
- * @param appId application ID
- * @param openstackService OpenStack interface service
- * @param flowObjectiveService flow objective service
- */
- public OpenstackSecurityGroupRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
- FlowObjectiveService flowObjectiveService) {
- this.appId = appId;
- this.openstackService = openstackService;
- this.flowObjectiveService = flowObjectiveService;
- }
-
- /**
- * Populates flow rules for security groups.
- *
- * @param id Device ID
- * @param sgId Security Group ID
- * @param vmIp VM IP address
- * @param portInfoMap Port Info map
- */
- public void populateSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
- Map<String, OpenstackPortInfo> portInfoMap) {
- OpenstackSecurityGroup securityGroup = openstackService.securityGroup(sgId);
- if (securityGroup != null) {
- securityGroup.rules().stream().forEach(sgRule -> {
- if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
- openstackService.ports().stream()
- .filter(port -> port.securityGroups().contains(sgRule.remoteGroupId()))
- .flatMap(port -> port.fixedIps().values().stream())
- .forEach(remoteIp -> setSecurityGroupRule(id, sgRule,
- vmIp, IpPrefix.valueOf((IpAddress) remoteIp, 32)));
- } else {
- setSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
- }
- });
-
- openstackService.ports().stream().forEach(osPort ->
- osPort.securityGroups().stream().forEach(remoteVmSgId -> {
- OpenstackSecurityGroup remoteVmSg = openstackService.securityGroup(remoteVmSgId);
- remoteVmSg.rules().stream()
- .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
- .forEach(remoteVmSgRule -> {
- Ip4Address remoteVmIp =
- (Ip4Address) osPort.fixedIps().values().stream().findAny().orElse(null);
- OpenstackPortInfo osPortInfo = portInfoMap.get(OpenstackSwitchingManager.PORTNAME_PREFIX_VM
- + osPort.id().substring(0, 11));
- if (osPortInfo != null && remoteVmIp != null) {
- setSecurityGroupRule(osPortInfo.deviceId(), remoteVmSgRule, remoteVmIp,
- IpPrefix.valueOf(vmIp, 32));
- }
- });
- }));
- }
- }
-
- /**
- * Removes flow rules for security groups.
- *
- * @param id Device ID
- * @param sgId Security Group ID to remove
- * @param vmIp VM IP address
- * @param portInfoMap port info map
- * @param securityGroupMap security group info map
- */
- public void removeSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
- Map<String, OpenstackPortInfo> portInfoMap,
- Map<String, OpenstackSecurityGroup> securityGroupMap) {
- OpenstackSecurityGroup securityGroup = securityGroupMap.get(sgId);
- if (securityGroup != null) {
- securityGroup.rules().stream().forEach(sgRule -> {
- if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
- portInfoMap.values().stream()
- .filter(portInfo -> portInfo.securityGroups().contains(sgRule.remoteGroupId()))
- .map(OpenstackPortInfo::ip)
- .forEach(remoteIp -> {
- removeSecurityGroupRule(id, sgRule, vmIp, IpPrefix.valueOf(remoteIp, 32));
- });
- } else {
- removeSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
- }
- });
-
- portInfoMap.values().stream()
- .forEach(portInfo -> portInfo.securityGroups()
- .forEach(remoteVmSgId -> {
- OpenstackSecurityGroup remoteVmSg = securityGroupMap.get(remoteVmSgId);
- remoteVmSg.rules().stream()
- .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
- .forEach(remoteVmSgRule -> removeSecurityGroupRule(portInfo.deviceId(),
- remoteVmSgRule, portInfo.ip(), IpPrefix.valueOf(vmIp, 32)));
- }));
- }
- }
-
- private void setSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
- Ip4Address vmIp, IpPrefix remoteIp) {
- ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
- if (foBuilder != null) {
- flowObjectiveService.forward(id, foBuilder.add());
- }
- }
-
- private void removeSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
- Ip4Address vmIp, IpPrefix remoteIp) {
- ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
- if (foBuilder != null) {
- flowObjectiveService.forward(id, foBuilder.remove());
- }
- }
-
- ForwardingObjective.Builder buildFlowObjective(DeviceId id, OpenstackSecurityGroupRule sgRule,
- Ip4Address vmIp, IpPrefix remoteIp) {
- if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
- return null;
- }
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
-
- ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(ACL_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId);
-
- return foBuilder;
- }
-
- private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
- Ip4Address vmIp, IpPrefix remoteIp) {
- buildMatchEthType(sBuilder, sgRule.ethertype());
- buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
- buildMatchProto(sBuilder, sgRule.protocol());
- buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(), sgRule.portRangeMax(), sgRule.portRangeMin());
- buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
- }
-
- private void buildMatchDirection(TrafficSelector.Builder sBuilder,
- OpenstackSecurityGroupRule.Direction direction, Ip4Address vmIp) {
- if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
- sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
- } else {
- sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
- }
- }
-
- private void buildMatchEthType(TrafficSelector.Builder sBuilder, String ethertype) {
- // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
- sBuilder.matchEthType(Ethernet.TYPE_IPV4);
- if (ethertype != null && ethertype != "null" &&
- !ethertype.toUpperCase().equals(ETHTYPE_IPV4)) {
- log.error("EthType {} is not supported yet in Security Group", ethertype);
- }
- }
-
- private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
- OpenstackSecurityGroupRule.Direction direction) {
- if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
- if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
- sBuilder.matchIPDst(remoteIpPrefix);
- } else {
- sBuilder.matchIPSrc(remoteIpPrefix);
- }
- }
- }
-
- private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
- if (protocol != null) {
- switch (protocol.toUpperCase()) {
- case PROTO_ICMP:
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
- break;
- case PROTO_TCP:
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
- break;
- case PROTO_UDP:
- sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
- break;
- default:
- }
- }
- }
-
- private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
- OpenstackSecurityGroupRule.Direction direction,
- int portMin, int portMax) {
- if (portMin > 0 && portMax > 0 && portMin == portMax) {
- if (protocol.toUpperCase().equals(PROTO_TCP)) {
- if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
- sBuilder.matchTcpDst(TpPort.tpPort(portMax));
- } else {
- sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
- }
- } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
- if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
- sBuilder.matchUdpDst(TpPort.tpPort(portMax));
- } else {
- sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
- }
- }
- }
- }
-}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
deleted file mode 100644
index 7f543a0..0000000
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.openstacknetworking.switching;
-
-import com.google.common.collect.ImmutableMap;
-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;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.dhcp.DhcpService;
-import org.onosproject.dhcp.IpAssignment;
-import org.onosproject.event.AbstractEvent;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.openstackinterface.OpenstackInterfaceService;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstackinterface.OpenstackSecurityGroup;
-import org.onosproject.openstackinterface.OpenstackSubnet;
-import org.onosproject.openstacknetworking.OpenstackPortInfo;
-import org.onosproject.openstacknetworking.OpenstackSubjectFactories;
-import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
-import org.onosproject.openstacknetworking.OpenstackSwitchingService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Date;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-@Service
-@Component(immediate = true)
-/**
- * Populates forwarding rules for VMs created by Openstack.
- */
-public class OpenstackSwitchingManager implements OpenstackSwitchingService {
-
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PacketService packetService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected FlowObjectiveService flowObjectiveService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DhcpService dhcpService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DriverService driverService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigRegistry networkConfig;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected OpenstackInterfaceService openstackService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigService configService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigRegistry configRegistry;
-
- public static final String PORTNAME_PREFIX_VM = "tap";
- public static final String PORTNAME_PREFIX_ROUTER = "qr-";
- public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
- public static final String PORTNAME = "portName";
- private static final String ROUTER_INTERFACE = "network:router_interface";
- public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
- public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8");
- private static final String FORWARD_SLASH = "/";
- private static final int DHCP_INFINITE_LEASE = -1;
- public static final String SONA_DRIVER_NAME = "sona";
-
-
- private ApplicationId appId;
-
- private OpenstackArpHandler arpHandler;
- private OpenstackSecurityGroupRulePopulator sgRulePopulator;
-
- private ExecutorService deviceEventExecutorService =
- Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event"));
-
- private ExecutorService configEventExecutorService =
- Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "config-event"));
-
- private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
- private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
- private InternalHostListener internalHostListener = new InternalHostListener();
-
- private final Map<String, OpenstackPortInfo> openstackPortInfoMap = Maps.newHashMap();
- private Map<String, OpenstackSecurityGroup> securityGroupMap = Maps.newConcurrentMap();
-
- private final ConfigFactory configFactory =
- new ConfigFactory(OpenstackSubjectFactories.USER_DEFINED_SUBJECT_FACTORY, OpenstackNetworkingConfig.class,
- "config") {
- @Override
- public OpenstackNetworkingConfig createConfig() {
- return new OpenstackNetworkingConfig();
- }
- };
- private final NetworkConfigListener configListener = new InternalConfigListener();
-
- private OpenstackNetworkingConfig config;
-
- @Activate
- protected void activate() {
- appId = coreService
- .registerApplication("org.onosproject.openstackswitching");
-
- packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
- deviceService.addListener(internalDeviceListener);
- hostService.addListener(internalHostListener);
- configRegistry.registerConfigFactory(configFactory);
- configService.addListener(configListener);
-
- arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
- sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);
-
- networkConfig.registerConfigFactory(configFactory);
- networkConfig.addListener(configListener);
-
- readConfiguration();
-
- log.info("Started");
- }
-
- @Deactivate
- protected void deactivate() {
- packetService.removeProcessor(internalPacketProcessor);
- deviceService.removeListener(internalDeviceListener);
-
- deviceEventExecutorService.shutdown();
- configEventExecutorService.shutdown();
- hostService.removeListener(internalHostListener);
- configService.removeListener(configListener);
- configRegistry.unregisterConfigFactory(configFactory);
-
- log.info("Stopped");
- }
-
- @Override
- public void createPorts(OpenstackPort openstackPort) {
-
- if (!openstackPort.deviceOwner().equals(ROUTER_INTERFACE)
- && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)
- && !openstackPort.fixedIps().isEmpty()) {
- registerDhcpInfo(openstackPort);
- }
- }
-
- @Override
- public void removePort(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());
- deviceService.getPorts(routerPortInfo.deviceId()).forEach(port -> {
- String pName = port.annotations().value(PORTNAME);
- if (pName.equals(routerPortName)) {
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService, config);
-
- rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
- openstackPortInfoMap.remove(routerPortName);
- return;
- }
- });
- }
- }
-
- @Override
- public void updatePort(OpenstackPort openstackPort) {
- if (openstackPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
- String portName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
- OpenstackPortInfo osPortInfo = openstackPortInfoMap.get(portName);
- if (osPortInfo != null) {
- // Remove all security group rules based on the ones stored in security group map.
- osPortInfo.securityGroups().stream().forEach(
- sgId -> sgRulePopulator.removeSecurityGroupRules(osPortInfo.deviceId(), sgId,
- osPortInfo.ip(), openstackPortInfoMap, securityGroupMap));
- // Add all security group rules based on the updated security group.
- openstackPort.securityGroups().stream().forEach(
- sgId -> sgRulePopulator.populateSecurityGroupRules(osPortInfo.deviceId(), sgId,
- osPortInfo.ip(), openstackPortInfoMap));
- updatePortMap(osPortInfo.deviceId(), portName, openstackService.networks(),
- openstackService.subnets(), openstackPort);
- }
- }
- }
-
- @Override
- public void createNetwork(OpenstackNetwork openstackNetwork) {
- //TODO
- }
-
- @Override
- public void createSubnet(OpenstackSubnet openstackSubnet) {
- //TODO
- }
-
- @Override
- public Map<String, OpenstackPortInfo> openstackPortInfo() {
- return ImmutableMap.copyOf(this.openstackPortInfoMap);
- }
-
- private void processPortUpdated(Device device, Port port) {
- String portName = port.annotations().value(PORTNAME);
- synchronized (openstackPortInfoMap) {
- if (portName.startsWith(PORTNAME_PREFIX_VM)) {
- if (port.isEnabled()) {
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService, config);
-
- rulePopulator.populateSwitchingRules(device, port);
- OpenstackPort openstackPort = rulePopulator.openstackPort(port);
- Ip4Address vmIp = (Ip4Address) openstackPort.fixedIps().values().stream()
- .findAny().orElseGet(null);
- openstackPort.securityGroups().stream().forEach(
- sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(), sgId, vmIp,
- openstackPortInfoMap));
- updatePortMap(device.id(), port.annotations().value(PORTNAME),
- openstackService.networks(), openstackService.subnets(), openstackPort);
-
- //In case portupdate event is driven by vm shutoff from openstack
- } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(portName)) {
- log.debug("Flowrules according to the port {} were removed", port.number());
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService, config);
- rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
- openstackPortInfoMap.get(portName).securityGroups().stream().forEach(
- sgId -> sgRulePopulator.removeSecurityGroupRules(device.id(), sgId,
- openstackPortInfoMap.get(portName).ip(), openstackPortInfoMap, securityGroupMap));
- dhcpService.removeStaticMapping(openstackPortInfoMap.get(port.annotations().value(PORTNAME)).mac());
- openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
- }
- }
- }
- }
-
- private void processPortRemoved(Port port) {
- log.debug("port {} is removed", port.toString());
- }
-
- private void initializeFlowRules() {
- OpenstackSwitchingRulePopulator rulePopulator =
- new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
- deviceService, openstackService, driverService, config);
-
- Collection<OpenstackNetwork> networks = openstackService.networks();
- Collection<OpenstackSubnet> subnets = openstackService.subnets();
-
- deviceService.getDevices().forEach(device -> {
- log.debug("device {} num of ports {} ", device.id(),
- deviceService.getPorts(device.id()).size());
- deviceService.getPorts(device.id()).stream()
- .filter(port -> port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM) ||
- port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
- .forEach(vmPort -> {
- OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
- if (osPort != null && !osPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
- rulePopulator.populateSwitchingRules(device, vmPort);
- Ip4Address vmIp = (Ip4Address) osPort.fixedIps().values().stream()
- .findAny().orElseGet(null);
- osPort.securityGroups().stream().forEach(
- sgId -> sgRulePopulator.populateSecurityGroupRules(device.id(),
- sgId, vmIp, openstackPortInfoMap));
- updatePortMap(device.id(), vmPort.annotations().value(PORTNAME), networks,
- subnets, osPort);
- registerDhcpInfo(osPort);
- } else {
- log.warn("No openstackPort information for port {}", vmPort);
- }
- }
- );
- }
- );
- }
-
- private void updatePortMap(DeviceId deviceId, String portName, Collection<OpenstackNetwork> networks,
- Collection<OpenstackSubnet> subnets, OpenstackPort openstackPort) {
- long vni;
- OpenstackNetwork openstackNetwork = networks.stream()
- .filter(n -> n.id().equals(openstackPort.networkId()))
- .findAny().orElse(null);
- if (openstackNetwork != null) {
- vni = Long.parseLong(openstackNetwork.segmentId());
- } else {
- log.debug("updatePortMap failed because there's no OpenstackNetwork matches {}", openstackPort.networkId());
- return;
- }
-
-
- OpenstackSubnet openstackSubnet = subnets.stream()
- .filter(n -> n.networkId().equals(openstackPort.networkId()))
- .findFirst().get();
-
- Ip4Address gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
-
- OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
- .setDeviceId(deviceId)
- .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
- .setHostMac(openstackPort.macAddress())
- .setVni(vni)
- .setGatewayIP(gatewayIPAddress)
- .setNetworkId(openstackPort.networkId())
- .setSecurityGroups(openstackPort.securityGroups());
-
- openstackPortInfoMap.put(portName, portBuilder.build());
-
- openstackPort.securityGroups().stream().forEach(sgId -> {
- if (!securityGroupMap.containsKey(sgId)) {
- securityGroupMap.put(sgId, openstackService.securityGroup(sgId));
- }
- });
- }
-
- private void registerDhcpInfo(OpenstackPort openstackPort) {
- checkNotNull(openstackPort);
- checkArgument(!openstackPort.fixedIps().isEmpty());
-
- OpenstackSubnet openstackSubnet = openstackService.subnets().stream()
- .filter(n -> n.networkId().equals(openstackPort.networkId()))
- .findFirst().orElse(null);
- if (openstackSubnet == null) {
- log.warn("Failed to find subnet for {}", openstackPort);
- return;
- }
-
- Ip4Address ipAddress = openstackPort.fixedIps().values().stream().findFirst().get();
- IpPrefix subnetPrefix = IpPrefix.valueOf(openstackSubnet.cidr());
- Ip4Address broadcast = Ip4Address.makeMaskedAddress(
- ipAddress,
- subnetPrefix.prefixLength());
-
- // TODO: supports multiple DNS servers
- Ip4Address domainServer = openstackSubnet.dnsNameservers().isEmpty() ?
- DNS_SERVER_IP : openstackSubnet.dnsNameservers().get(0);
-
- IpAssignment ipAssignment = IpAssignment.builder()
- .ipAddress(ipAddress)
- .leasePeriod(DHCP_INFINITE_LEASE)
- .timestamp(new Date())
- .subnetMask(Ip4Address.makeMaskPrefix(subnetPrefix.prefixLength()))
- .broadcast(broadcast)
- .domainServer(domainServer)
- .assignmentStatus(Option_RangeNotEnforced)
- .routerAddress(Ip4Address.valueOf(openstackSubnet.gatewayIp()))
- .build();
-
- dhcpService.setStaticMapping(openstackPort.macAddress(), ipAssignment);
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
-
- @Override
- public void process(PacketContext context) {
- // FIXME: use GatewayNode list to check if the ARP packet is from GatewayNode's
- if (context.isHandled()) {
- return;
- } else if (!SONA_DRIVER_NAME.equals(driverService
- .getDriver(context.inPacket().receivedFrom().deviceId()).name())) {
- return;
- }
-
- InboundPacket pkt = context.inPacket();
- Ethernet ethernet = pkt.parsed();
-
- if (ethernet != null && ethernet.getEtherType() == Ethernet.TYPE_ARP) {
- arpHandler.processPacketIn(pkt, openstackPortInfoMap.values());
- }
- }
- }
-
- private class InternalHostListener implements HostListener {
-
- @Override
- public void event(HostEvent hostEvent) {
- deviceEventExecutorService.execute(new InternalEventHandler(hostEvent));
- }
- }
-
- private class InternalDeviceListener implements DeviceListener {
-
- @Override
- public void event(DeviceEvent deviceEvent) {
- deviceEventExecutorService.execute(new InternalEventHandler(deviceEvent));
- }
- }
-
- private class InternalEventHandler implements Runnable {
-
- volatile AbstractEvent event;
-
- InternalEventHandler(AbstractEvent event) {
- this.event = event;
- }
-
- @Override
- public void run() {
-
- if (event instanceof DeviceEvent) {
- DeviceEvent deviceEvent = (DeviceEvent) event;
-
- switch (deviceEvent.type()) {
- case DEVICE_ADDED:
- log.debug("device {} is added", deviceEvent.subject().id());
- break;
- case DEVICE_AVAILABILITY_CHANGED:
- Device device = deviceEvent.subject();
- if (deviceService.isAvailable(device.id())) {
- log.debug("device {} is added", device.id());
- }
- break;
- case PORT_ADDED:
- processPortUpdated(deviceEvent.subject(), deviceEvent.port());
- break;
- case PORT_UPDATED:
- processPortUpdated(deviceEvent.subject(), deviceEvent.port());
- break;
- case PORT_REMOVED:
- processPortRemoved(deviceEvent.port());
- break;
- default:
- log.debug("Unsupported deviceEvent type {}", deviceEvent.type().toString());
- break;
- }
- } else if (event instanceof HostEvent) {
- HostEvent hostEvent = (HostEvent) event;
-
- switch (hostEvent.type()) {
- case HOST_REMOVED:
- log.debug("host {} was removed", hostEvent.subject().toString());
- break;
- default:
- log.debug("Unsupported hostEvent type {}", hostEvent.type().toString());
- break;
- }
- }
- }
- }
-
- private void readConfiguration() {
- config = configService.getConfig("openstacknetworking", OpenstackNetworkingConfig.class);
- if (config == null) {
- log.error("No configuration found");
- return;
- }
-
- arpHandler = new OpenstackArpHandler(openstackService, packetService, hostService);
- sgRulePopulator = new OpenstackSecurityGroupRulePopulator(appId, openstackService, flowObjectiveService);
-
- initializeFlowRules();
- }
-
- private class InternalConfigListener implements NetworkConfigListener {
-
- @Override
- public void event(NetworkConfigEvent event) {
- if (!event.configClass().equals(OpenstackNetworkingConfig.class)) {
- return;
- }
-
- if (event.type().equals(NetworkConfigEvent.Type.CONFIG_ADDED) ||
- event.type().equals(NetworkConfigEvent.Type.CONFIG_UPDATED)) {
- configEventExecutorService.execute(OpenstackSwitchingManager.this::readConfiguration);
-
- }
- }
- }
-}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
deleted file mode 100644
index 5f072bd..0000000
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
-* Copyright 2016-present Open Networking Laboratory
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package org.onosproject.openstacknetworking.switching;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DefaultDriverData;
-import org.onosproject.net.driver.DefaultDriverHandler;
-import org.onosproject.net.driver.Driver;
-import org.onosproject.net.driver.DriverHandler;
-import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.ExtensionTreatment;
-import org.onosproject.net.flow.instructions.ExtensionPropertyException;
-import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.openstackinterface.OpenstackInterfaceService;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
-import org.onosproject.openstacknetworking.OpenstackPortInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Populates switching flow rules.
- */
-public class OpenstackSwitchingRulePopulator {
-
- private static Logger log = LoggerFactory
- .getLogger(OpenstackSwitchingRulePopulator.class);
- private static final int SWITCHING_RULE_PRIORITY = 30000;
- private static final int TUNNELTAG_RULE_PRIORITY = 30000;
- private static final String PORT_NAME = "portName";
- private static final String TUNNEL_DST = "tunnelDst";
- private FlowObjectiveService flowObjectiveService;
- private DriverService driverService;
- private DeviceService deviceService;
- private ApplicationId appId;
- private OpenstackNetworkingConfig config;
-
- private Collection<OpenstackNetwork> openstackNetworkList;
- private Collection<OpenstackPort> openstackPortList;
-
- /**
- * Creates OpenstackSwitchingRulPopulator.
- *
- * @param appId application id
- * @param flowObjectiveService FlowObjectiveService reference
- * @param deviceService DeviceService reference
- * @param openstackService openstack interface service
- * @param driverService DriverService reference
- * @param config OpenstackRoutingConfig
- */
- public OpenstackSwitchingRulePopulator(ApplicationId appId,
- FlowObjectiveService flowObjectiveService,
- DeviceService deviceService,
- OpenstackInterfaceService openstackService,
- DriverService driverService,
- OpenstackNetworkingConfig config) {
- this.flowObjectiveService = flowObjectiveService;
- this.deviceService = deviceService;
- this.driverService = driverService;
- this.appId = appId;
- this.config = config;
-
- openstackNetworkList = openstackService.networks();
- openstackPortList = openstackService.ports();
- }
-
-
- /**
- * Populates flow rules for the VM created.
- *
- * @param device device to populate rules to
- * @param port port for the VM created
- */
- public void populateSwitchingRules(Device device, Port port) {
- populateFlowRulesForTunnelTag(device, port);
- populateFlowRulesForTrafficToSameCnode(device, port);
- populateFlowRulesForTrafficToDifferentCnode(device, port);
- }
-
- /**
- * Populate the flow rules for tagging tunnelId according to which inport is came from.
- *
- * @param device device to put the rules
- * @param port port info of the VM
- */
- private void populateFlowRulesForTunnelTag(Device device, Port port) {
- Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value(PORT_NAME));
- String portName = port.annotations().value(PORT_NAME);
- String vni = getVniForPort(portName);
-
- if (vmIp != null) {
- setFlowRuleForTunnelTag(device.id(), port, vni);
- }
- }
-
- private void setFlowRuleForTunnelTag(DeviceId deviceId, Port port, String vni) {
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchInPort(port.number());
-
- tBuilder.setTunnelId(Long.parseLong(vni));
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(TUNNELTAG_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- /**
- * Populates the flow rules for traffic to VMs in the same Cnode as the sender.
- *
- * @param device device to put the rules
- * @param port port info of the VM
- */
- private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) {
- Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value(PORT_NAME));
- String portName = port.annotations().value(PORT_NAME);
- String vni = getVniForPort(portName);
-
- if (vmIp != null) {
- setFlowRuleForVMsInSameCnode(vmIp, device.id(), port, vni);
- }
- }
-
- /**
- * Sets the flow rules for traffic between VMs in the same Cnode.
- *
- * @param ip4Address VM IP address
- * @param id device ID to put rules
- * @param port VM port
- * @param vni VM VNI
- */
- private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id,
- Port port, String vni) {
-
- //For L2 Switching Case
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(ip4Address.toIpPrefix())
- .matchTunnelId(Long.parseLong(vni));
-
- tBuilder.setOutput(port.number());
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(SWITCHING_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(id, fo);
- }
-
- /**
- * Populates the flow rules for traffic to VMs in different Cnode using
- * Nicira extention.
- *
- * @param device device to put rules
- * @param port port information of the VM
- */
- private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) {
- String portName = port.annotations().value(PORT_NAME);
- Ip4Address fixedIp = getFixedIpAddressForPort(portName);
- String vni = getVniForPort(portName);
- Ip4Address hostDpIpAddress = config.nodes().get(device.id());
-
- if (hostDpIpAddress == null) {
- log.debug("There's no openstack node information for device id {}", device.id().toString());
- return;
- }
-
- deviceService.getAvailableDevices().forEach(d -> {
- if (!d.equals(device)) {
- deviceService.getPorts(d.id()).forEach(p -> {
- String pName = p.annotations().value(PORT_NAME);
- if (!p.equals(port) && vni.equals(getVniForPort(pName))) {
- Ip4Address hostxDpIpAddress = config.nodes().get(d.id());
-
- Ip4Address fixedIpx = getFixedIpAddressForPort(pName);
- if (port.isEnabled()) {
- setVxLanFlowRule(vni, device.id(), hostxDpIpAddress, fixedIpx);
- setVxLanFlowRule(vni, d.id(), hostDpIpAddress, fixedIp);
- }
- }
- });
- }
- });
- }
-
- /**
- * Sets the flow rules between traffic from VMs in different Cnode.
- *
- * @param vni VNI
- * @param deviceId device ID
- * @param hostIp host IP of the VM
- * @param vmIp fixed IP of the VM
- */
- private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address hostIp,
- Ip4Address vmIp) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchTunnelId(Long.parseLong(vni))
- .matchIPDst(vmIp.toIpPrefix());
- tBuilder.extension(buildNiciraExtenstion(deviceId, hostIp), deviceId)
- .setOutput(getTunnelPort(deviceId));
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(SWITCHING_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- /**
- * Returns OpenstackPort object for the Port reference given.
- *
- * @param port Port object
- * @return OpenstackPort reference, or null when not found
- */
- public OpenstackPort openstackPort(Port port) {
- String uuid = port.annotations().value(PORT_NAME).substring(3);
- return openstackPortList.stream().filter(p -> p.id().startsWith(uuid))
- .findAny().orElse(null);
- }
-
- /**
- * Remove flows rules for the removed VM.
- *
- * @param removedPort removedport info
- * @param openstackPortInfoMap openstackPortInfoMap
- */
- public void removeSwitchingRules(Port removedPort, Map<String,
- OpenstackPortInfo> openstackPortInfoMap) {
- OpenstackPortInfo openstackPortInfo = openstackPortInfoMap
- .get(removedPort.annotations().value(PORT_NAME));
-
- DeviceId deviceId = openstackPortInfo.deviceId();
- Ip4Address vmIp = openstackPortInfo.ip();
- PortNumber portNumber = removedPort.number();
- long vni = openstackPortInfo.vni();
-
- removeFlowRuleForTunnelTag(deviceId, portNumber);
- removeFlowRuleForVMsInSameCnode(deviceId, vmIp, vni);
- removeFlowRuleForVMsInDiffrentCnode(removedPort, deviceId, vmIp, vni, openstackPortInfoMap);
- }
-
- /**
- * Removes flow rules for tagging tunnelId.
- *
- * @param deviceId device id
- * @param portNumber port number
- */
- private void removeFlowRuleForTunnelTag(DeviceId deviceId, PortNumber portNumber) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchInPort(portNumber);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(TUNNELTAG_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .remove();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- /**
- * Removes the flow rules for traffic between VMs in the same Cnode.
- *
- * @param deviceId device id on which removed VM was run
- * @param vmIp ip of the removed VM
- * @param vni vni which removed VM was belonged
- */
- private void removeFlowRuleForVMsInSameCnode(DeviceId deviceId, Ip4Address vmIp, long vni) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(vmIp.toIpPrefix())
- .matchTunnelId(vni);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(DefaultTrafficTreatment.builder().build())
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withPriority(SWITCHING_RULE_PRIORITY)
- .fromApp(appId)
- .remove();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- /**
- * Removes the flow rules for traffic between VMs in the different Cnode.
- *
- * @param removedPort removedport info
- * @param deviceId device id on which removed VM was run
- * @param vmIp ip of the removed VM
- * @param vni vni which removed VM was belonged
- * @param openstackPortInfoMap openstackPortInfoMap
- */
- private void removeFlowRuleForVMsInDiffrentCnode(Port removedPort, DeviceId deviceId, Ip4Address vmIp,
- long vni, Map<String, OpenstackPortInfo> openstackPortInfoMap) {
-
- final boolean anyPortRemainedInSameCnode
- = checkIfAnyPortRemainedInSameCnode(removedPort, deviceId, vni, openstackPortInfoMap);
-
- openstackPortInfoMap.forEach((port, portInfo) -> {
- if (portInfo.vni() == vni && !portInfo.deviceId().equals(deviceId)) {
- removeVxLanFlowRule(portInfo.deviceId(), vmIp, vni);
- if (!anyPortRemainedInSameCnode) {
- removeVxLanFlowRule(deviceId, portInfo.ip(), vni);
- }
- }
- });
- }
-
- /**
- * Removes the flow rules between traffic from VMs in different Cnode.
- *
- * @param deviceId device id
- * @param vmIp ip
- * @param vni vni which removed VM was belonged
- */
- private void removeVxLanFlowRule(DeviceId deviceId, Ip4Address vmIp, long vni) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchTunnelId(vni)
- .matchIPDst(vmIp.toIpPrefix());
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(DefaultTrafficTreatment.builder().build())
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withPriority(SWITCHING_RULE_PRIORITY)
- .fromApp(appId)
- .remove();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- /**
- * Checks if there is any port remained with same vni at the device, on which the removed VM was run.
- *
- * @param removedPort removedport info
- * @param deviceId device id on which removed VM was run
- * @param vni vni which removed VM was belonged
- * @param openstackPortInfoMap openstackPortInfoMap
- * @return true if there is, false otherwise
- */
- private boolean checkIfAnyPortRemainedInSameCnode(Port removedPort, DeviceId deviceId, long vni,
- Map<String, OpenstackPortInfo> openstackPortInfoMap) {
-
- for (Map.Entry<String, OpenstackPortInfo> entry : openstackPortInfoMap.entrySet()) {
- if (!removedPort.annotations().value(PORT_NAME).equals(entry.getKey())) {
- if (entry.getValue().vni() == vni && entry.getValue().deviceId().equals(deviceId)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns the VNI of the VM of the port.
- *
- * @param portName VM port
- * @return VNI
- */
- private String getVniForPort(String portName) {
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortList.stream()
- .filter(p -> p.id().startsWith(uuid))
- .findAny().orElse(null);
- if (port == null) {
- log.debug("No port information for port {}", portName);
- return null;
- }
-
- OpenstackNetwork network = openstackNetworkList.stream()
- .filter(n -> n.id().equals(port.networkId()))
- .findAny().orElse(null);
- if (network == null) {
- log.warn("No VNI information for network {}", port.networkId());
- return null;
- }
-
- return network.segmentId();
- }
-
- /**
- * Returns the Fixed IP address of the VM.
- *
- * @param portName VM port info
- * @return IP address of the VM
- */
- private Ip4Address getFixedIpAddressForPort(String portName) {
-
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortList.stream()
- .filter(p -> p.id().startsWith(uuid))
- .findFirst().orElse(null);
-
- if (port == null) {
- log.error("There is no port information for port name {}", portName);
- return null;
- }
-
- if (port.fixedIps().isEmpty()) {
- log.error("There is no fixed IP info in the port information");
- return null;
- }
-
- return (Ip4Address) port.fixedIps().values().toArray()[0];
- }
-
- private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
- Driver driver = driverService.getDriver(id);
- DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
- ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
-
- ExtensionTreatment extensionInstruction =
- resolver.getExtensionInstruction(
- ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
-
- try {
- extensionInstruction.setPropertyValue(TUNNEL_DST, hostIp);
- } catch (ExtensionPropertyException e) {
- log.error("Error setting Nicira extension setting {}", e);
- }
-
- return extensionInstruction;
- }
-
- private PortNumber getTunnelPort(DeviceId deviceId) {
- Port port = deviceService.getPorts(deviceId).stream()
- .filter(p -> p.annotations().value(PORT_NAME).equals(
- OpenstackSwitchingManager.PORTNAME_PREFIX_TUNNEL))
- .findAny().orElse(null);
-
- if (port == null) {
- log.error("No TunnelPort was created.");
- return null;
- }
- return port.number();
- }
-
-}
diff --git a/apps/openstacknetworking/pom.xml b/apps/openstacknetworking/pom.xml
index f0a6530..d232273 100644
--- a/apps/openstacknetworking/pom.xml
+++ b/apps/openstacknetworking/pom.xml
@@ -29,11 +29,10 @@
<packaging>pom</packaging>
<modules>
- <module>app</module>
- <module>web</module>
<module>api</module>
- <module>openstackswitching</module>
- <module>openstackrouting</module>
+ <module>web</module>
+ <module>switching</module>
+ <module>routing</module>
</modules>
<description>SONA Openstack Networking Application</description>
diff --git a/apps/openstacknetworking/openstackrouting/BUCK b/apps/openstacknetworking/routing/BUCK
similarity index 62%
rename from apps/openstacknetworking/openstackrouting/BUCK
rename to apps/openstacknetworking/routing/BUCK
index da4f812..fe48a99 100644
--- a/apps/openstacknetworking/openstackrouting/BUCK
+++ b/apps/openstacknetworking/routing/BUCK
@@ -4,12 +4,13 @@
'//apps/openstackinterface/api:onos-apps-openstackinterface-api',
'//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
'//apps/scalablegateway:onos-apps-scalablegateway',
+ '//apps/openstacknode:onos-apps-openstacknode',
]
BUNDLES = [
- '//apps/openstackinterface/api:onos-apps-openstackinterface-api',
'//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
- '//apps/openstacknetworking/openstackrouting:onos-apps-openstacknetworking-openstackrouting',
+ '//apps/openstacknetworking/web:onos-apps-openstacknetworking-web',
+ '//apps/openstacknetworking/routing:onos-apps-openstacknetworking-routing',
]
osgi_jar_with_tests (
@@ -17,9 +18,11 @@
)
onos_app (
+ app_name = 'org.onosproject.openstackrouting',
title = 'OpenStack Routing App',
category = 'Utility',
url = 'http://onosproject.org',
description = 'OpenStack routing application.',
included_bundles = BUNDLES,
+ required_apps = [ 'org.onosproject.openstackinterface', 'org.onosproject.openstacknode', 'org.onosproject.scalablegateway' ]
)
diff --git a/apps/openstacknetworking/app/features.xml b/apps/openstacknetworking/routing/features.xml
similarity index 92%
copy from apps/openstacknetworking/app/features.xml
copy to apps/openstacknetworking/routing/features.xml
index 2043fc6..f9be32e 100644
--- a/apps/openstacknetworking/app/features.xml
+++ b/apps/openstacknetworking/routing/features.xml
@@ -20,5 +20,6 @@
<feature>onos-api</feature>
<bundle>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-app-openstacknetworking-web/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-openstackrouting/${project.version}</bundle>
</feature>
</features>
diff --git a/apps/openstacknetworking/openstackrouting/pom.xml b/apps/openstacknetworking/routing/pom.xml
similarity index 83%
rename from apps/openstacknetworking/openstackrouting/pom.xml
rename to apps/openstacknetworking/routing/pom.xml
index 3b74025..cc4f7d0 100644
--- a/apps/openstacknetworking/openstackrouting/pom.xml
+++ b/apps/openstacknetworking/routing/pom.xml
@@ -28,6 +28,17 @@
<artifactId>onos-app-openstackrouting</artifactId>
<packaging>bundle</packaging>
+ <properties>
+ <onos.app.name>org.onosproject.openstackrouting</onos.app.name>
+ <onos.app.title>Openstack Switching App</onos.app.title>
+ <onos.app.category>Traffic Steering</onos.app.category>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.requires>
+ org.onosproject.openstackinterface,
+ org.onosproject.openstacknode
+ </onos.app.requires>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIPHandler.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIPHandler.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIPHandler.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIPHandler.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackPnatHandler.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackPnatHandler.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackPnatHandler.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackPnatHandler.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/package-info.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/package-info.java
similarity index 100%
rename from apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/package-info.java
rename to apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/package-info.java
diff --git a/apps/openstacknetworking/openstackswitching/BUCK b/apps/openstacknetworking/switching/BUCK
similarity index 62%
rename from apps/openstacknetworking/openstackswitching/BUCK
rename to apps/openstacknetworking/switching/BUCK
index 42d7c07..5e991af 100644
--- a/apps/openstacknetworking/openstackswitching/BUCK
+++ b/apps/openstacknetworking/switching/BUCK
@@ -3,14 +3,14 @@
'//core/store/serializers:onos-core-serializers',
'//apps/openstackinterface/api:onos-apps-openstackinterface-api',
'//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
+ '//apps/openstacknode:onos-apps-openstacknode',
'//apps/dhcp/api:onos-apps-dhcp-api',
]
BUNDLES = [
- '//apps/openstackinterface/api:onos-apps-openstackinterface-api',
'//apps/openstacknetworking/api:onos-apps-openstacknetworking-api',
- '//apps/openstacknetworking/openstackswitching:onos-apps-openstacknetworking-openstackswitching',
- '//apps/dhcp/api:onos-apps-dhcp-api',
+ '//apps/openstacknetworking/web:onos-apps-openstacknetworking-web',
+ '//apps/openstacknetworking/switching:onos-apps-openstacknetworking-switching',
]
osgi_jar_with_tests (
@@ -18,9 +18,11 @@
)
onos_app (
+ app_name = 'org.onosproject.openstackswitching',
title = 'OpenStack Switching App',
category = 'Utility',
url = 'http://onosproject.org',
description = 'OpenStack Switching application.',
included_bundles = BUNDLES,
+ required_apps = [ 'org.onosproject.openstackinterface', 'org.onosproject.openstacknode', 'org.onosproject.dhcp' ]
)
diff --git a/apps/openstacknetworking/app/features.xml b/apps/openstacknetworking/switching/features.xml
similarity index 92%
rename from apps/openstacknetworking/app/features.xml
rename to apps/openstacknetworking/switching/features.xml
index 2043fc6..1792b61 100644
--- a/apps/openstacknetworking/app/features.xml
+++ b/apps/openstacknetworking/switching/features.xml
@@ -20,5 +20,6 @@
<feature>onos-api</feature>
<bundle>mvn:${project.groupId}/onos-app-openstacknetworking-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-app-openstacknetworking-web/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</bundle>
</feature>
</features>
diff --git a/apps/openstacknetworking/openstackswitching/pom.xml b/apps/openstacknetworking/switching/pom.xml
similarity index 76%
rename from apps/openstacknetworking/openstackswitching/pom.xml
rename to apps/openstacknetworking/switching/pom.xml
index af2d55b..4135e19 100644
--- a/apps/openstacknetworking/openstackswitching/pom.xml
+++ b/apps/openstacknetworking/switching/pom.xml
@@ -28,8 +28,24 @@
<artifactId>onos-app-openstackswitching</artifactId>
<packaging>bundle</packaging>
+ <properties>
+ <onos.app.name>org.onosproject.openstackswitching</onos.app.name>
+ <onos.app.title>Openstack Switching App</onos.app.title>
+ <onos.app.category>Traffic Steering</onos.app.category>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.requires>
+ org.onosproject.dhcp,
+ org.onosproject.openstackinterface,
+ org.onosproject.openstacknode
+ </onos.app.requires>
+ </properties>
+
<dependencies>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-openstacknetworking-api</artifactId>
<version>${project.version}</version>
@@ -41,6 +57,11 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-app-openstacknode</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onos-app-dhcp</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/AbstractVmHandler.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/AbstractVmHandler.java
new file mode 100644
index 0000000..9bf2baa
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/AbstractVmHandler.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.switching;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ip4Address;
+import org.onlab.util.Tools;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.slf4j.Logger;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.openstacknetworking.switching.Constants.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provides abstract virtual machine handler.
+ */
+public abstract class AbstractVmHandler {
+ protected final Logger log = getLogger(getClass());
+
+ protected final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
+ groupedThreads(this.getClass().getSimpleName(), "event-handler"));
+
+ protected CoreService coreService;
+ protected MastershipService mastershipService;
+ protected HostService hostService;
+
+ protected ApplicationId appId;
+ protected HostListener hostListener = new InternalHostListener();
+
+ protected void activate() {
+ ServiceDirectory services = new DefaultServiceDirectory();
+ coreService = services.get(CoreService.class);
+ mastershipService = services.get(MastershipService.class);
+ hostService = services.get(HostService.class);
+
+ appId = coreService.registerApplication(Constants.APP_ID);
+ hostService.addListener(hostListener);
+
+ log.info("Started");
+ }
+
+ protected void deactivate() {
+ hostService.removeListener(hostListener);
+ eventExecutor.shutdown();
+
+ log.info("Stopped");
+ }
+
+ abstract void hostDetected(Host host);
+
+ abstract void hostRemoved(Host host);
+
+ protected boolean isValidHost(Host host) {
+ return !host.ipAddresses().isEmpty() &&
+ host.annotations().value(VXLAN_ID) != null &&
+ host.annotations().value(NETWORK_ID) != null &&
+ host.annotations().value(TENANT_ID) != null &&
+ host.annotations().value(PORT_ID) != null;
+ }
+
+ protected Set<Host> getVmsInDifferentCnode(Host host) {
+ return Tools.stream(hostService.getHosts())
+ .filter(h -> !h.location().deviceId().equals(host.location().deviceId()))
+ .filter(this::isValidHost)
+ .filter(h -> Objects.equals(getVni(h), getVni(host)))
+ .collect(Collectors.toSet());
+ }
+
+ protected Optional<Host> getVmByPortId(String portId) {
+ return Tools.stream(hostService.getHosts())
+ .filter(this::isValidHost)
+ .filter(host -> host.annotations().value(PORT_ID).equals(portId))
+ .findFirst();
+ }
+
+ protected Ip4Address getIp(Host host) {
+ return host.ipAddresses().stream().findFirst().get().getIp4Address();
+ }
+
+ protected String getVni(Host host) {
+ return host.annotations().value(VXLAN_ID);
+ }
+
+ protected String getTenantId(Host host) {
+ return host.annotations().value(TENANT_ID);
+ }
+
+ private class InternalHostListener implements HostListener {
+
+ @Override
+ public void event(HostEvent event) {
+ Host host = event.subject();
+ if (!mastershipService.isLocalMaster(host.location().deviceId())) {
+ // do not allow to proceed without mastership
+ return;
+ }
+
+ if (!isValidHost(host)) {
+ log.debug("Invalid host event, ignore it {}", host);
+ return;
+ }
+
+ switch (event.type()) {
+ case HOST_UPDATED:
+ case HOST_ADDED:
+ eventExecutor.execute(() -> hostDetected(host));
+ break;
+ case HOST_REMOVED:
+ eventExecutor.execute(() -> hostRemoved(host));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/Constants.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/Constants.java
new file mode 100644
index 0000000..b173f29
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/Constants.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.switching;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Provides constants used in OpenStack node services.
+ */
+public final class Constants {
+
+ private Constants() {
+ }
+
+ public static final String APP_ID = "org.onosproject.openstackswitching";
+
+ public static final String PORTNAME_PREFIX_VM = "tap";
+ public static final String PORTNAME_PREFIX_ROUTER = "qr-";
+ public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
+
+ // TODO remove this
+ public static final String ROUTER_INTERFACE = "network:router_interface";
+ public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
+
+ public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8");
+ public static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");
+ public static final int DHCP_INFINITE_LEASE = -1;
+
+ public static final String NETWORK_ID = "networkId";
+ public static final String PORT_ID = "portId";
+ public static final String VXLAN_ID = "vxlanId";
+ public static final String TENANT_ID = "tenantId";
+ public static final String GATEWAY_IP = "gatewayIp";
+ public static final String CREATE_TIME = "createTime";
+
+ public static final int SWITCHING_RULE_PRIORITY = 30000;
+ public static final int TUNNELTAG_RULE_PRIORITY = 30000;
+ public static final int ACL_RULE_PRIORITY = 30000;
+}
\ No newline at end of file
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java
new file mode 100644
index 0000000..c855403
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackArpHandler.java
@@ -0,0 +1,221 @@
+/*
+* Copyright 2016-present Open Networking Laboratory
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.onosproject.openstacknetworking.switching;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.ARP;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.util.Tools;
+import org.onosproject.net.Host;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackNetwork;
+import org.onosproject.openstackinterface.OpenstackPort;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.nio.ByteBuffer;
+import java.util.Dictionary;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.openstacknetworking.switching.Constants.*;
+
+/**
+ * Handles ARP packet from VMs.
+ */
+@Component(immediate = true)
+public final class OpenstackArpHandler extends AbstractVmHandler {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final String GATEWAY_MAC = "gatewayMac";
+ private static final String DEFAULT_GATEWAY_MAC = "1f:1f:1f:1f:1f:1f";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackInterfaceService openstackService;
+
+ @Property(name = GATEWAY_MAC, value = DEFAULT_GATEWAY_MAC,
+ label = "Fake MAC address for virtual network subnet gateway")
+ private String gatewayMac = DEFAULT_GATEWAY_MAC;
+
+ private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
+ private final Set<Ip4Address> gateways = Sets.newConcurrentHashSet();
+
+ @Activate
+ protected void activate() {
+ packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
+ super.activate();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ packetService.removeProcessor(packetProcessor);
+ super.deactivate();
+ }
+
+ @Modified
+ protected void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ String updatedMac;
+
+ updatedMac = Tools.get(properties, GATEWAY_MAC);
+ if (!Strings.isNullOrEmpty(updatedMac) && !updatedMac.equals(gatewayMac)) {
+ gatewayMac = updatedMac;
+ }
+
+ log.info("Modified");
+ }
+
+ /**
+ * Processes ARP request packets.
+ * It checks if the target IP is owned by a known host first and then ask to
+ * OpenStack if it's not. This ARP proxy does not support overlapping IP.
+ *
+ * @param context packet context
+ * @param ethPacket ethernet packet
+ */
+ private void processPacketIn(PacketContext context, Ethernet ethPacket) {
+ ARP arpPacket = (ARP) ethPacket.getPayload();
+ if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
+ return;
+ }
+
+ Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
+ MacAddress replyMac = gateways.contains(targetIp) ? MacAddress.valueOf(gatewayMac) :
+ getMacFromHostService(targetIp);
+ if (replyMac.equals(MacAddress.NONE)) {
+ replyMac = getMacFromOpenstack(targetIp);
+ }
+
+ if (replyMac == MacAddress.NONE) {
+ log.debug("Failed to find MAC address for {}", targetIp.toString());
+ return;
+ }
+
+ Ethernet ethReply = ARP.buildArpReply(
+ targetIp.getIp4Address(),
+ replyMac,
+ ethPacket);
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(context.inPacket().receivedFrom().port())
+ .build();
+
+ packetService.emit(new DefaultOutboundPacket(
+ context.inPacket().receivedFrom().deviceId(),
+ treatment,
+ ByteBuffer.wrap(ethReply.serialize())));
+ }
+
+ /**
+ * Returns MAC address of a host with a given target IP address by asking to
+ * OpenStack. It does not support overlapping IP.
+ *
+ * @param targetIp target ip address
+ * @return mac address, or null if it fails to fetch the mac
+ */
+ private MacAddress getMacFromOpenstack(IpAddress targetIp) {
+ checkNotNull(targetIp);
+
+ OpenstackPort openstackPort = openstackService.ports()
+ .stream()
+ .filter(port -> port.fixedIps().containsValue(targetIp.getIp4Address()))
+ .findFirst()
+ .orElse(null);
+
+ if (openstackPort != null) {
+ log.debug("Found MAC from OpenStack for {}", targetIp.toString());
+ return openstackPort.macAddress();
+ } else {
+ return MacAddress.NONE;
+ }
+ }
+
+ /**
+ * Returns MAC address of a host with a given target IP address by asking to
+ * host service. It does not support overlapping IP.
+ *
+ * @param targetIp target ip
+ * @return mac address, or null if it fails to find the mac
+ */
+ private MacAddress getMacFromHostService(IpAddress targetIp) {
+ checkNotNull(targetIp);
+
+ Host host = hostService.getHostsByIp(targetIp)
+ .stream()
+ .findFirst()
+ .orElse(null);
+
+ if (host != null) {
+ log.debug("Found MAC from host service for {}", targetIp.toString());
+ return host.mac();
+ } else {
+ return MacAddress.NONE;
+ }
+ }
+
+ @Override
+ protected void hostDetected(Host host) {
+ OpenstackNetwork osNet = openstackService.network(host.annotations().value(NETWORK_ID));
+ if (osNet == null) {
+ log.warn("Failed to get OpenStack network for {}", host);
+ return;
+ }
+ osNet.subnets().stream()
+ .forEach(subnet -> gateways.add(Ip4Address.valueOf(subnet.gatewayIp())));
+ }
+
+ @Override
+ protected void hostRemoved(Host host) {
+ // TODO remove subnet gateway from gateways if no hosts exists on that subnet
+ }
+
+ private class InternalPacketProcessor implements PacketProcessor {
+
+ @Override
+ public void process(PacketContext context) {
+ if (context.isHandled()) {
+ return;
+ }
+
+ Ethernet ethPacket = context.inPacket().parsed();
+ if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
+ return;
+ }
+ processPacketIn(context, ethPacket);
+ }
+ }
+}
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
new file mode 100644
index 0000000..7477404
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSecurityGroupRulePopulator.java
@@ -0,0 +1,365 @@
+/*
+* Copyright 2016-present Open Networking Laboratory
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.openstacknetworking.switching;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.TpPort;
+import org.onlab.util.Tools;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackPort;
+import org.onosproject.openstackinterface.OpenstackSecurityGroup;
+import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.onosproject.openstacknetworking.switching.Constants.*;
+
+/**
+ * Populates flows rules for Security Groups of VMs.
+ *
+ */
+@Component(immediate = true)
+public class OpenstackSecurityGroupRulePopulator extends AbstractVmHandler {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackInterfaceService openstackService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ private static final String PROTO_ICMP = "ICMP";
+ private static final String PROTO_TCP = "TCP";
+ private static final String PROTO_UDP = "UDP";
+ private static final String ETHTYPE_IPV4 = "IPV4";
+
+ private final Map<Host, Set<SecurityGroupRule>> securityGroupRuleMap = Maps.newConcurrentMap();
+
+ @Activate
+ protected void activate() {
+ super.activate();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ super.deactivate();
+ }
+
+ // TODO call this when port is updated from OpenStack
+ public void updateSecurityGroup(OpenstackPort osPort) {
+ if (!osPort.status().equals(OpenstackPort.PortStatus.ACTIVE)) {
+ return;
+ }
+
+ Optional<Host> host = getVmByPortId(osPort.id());
+ if (!host.isPresent()) {
+ log.warn("No host found with {}", osPort);
+ return;
+ }
+ eventExecutor.execute(() -> updateSecurityGroupRules(host.get(), true));
+ }
+
+ /**
+ * Populates security group rules for all VMs in the supplied tenant ID.
+ * VMs in the same tenant tend to be engaged to each other by sharing the
+ * same security groups or setting the remote to another security group.
+ * To make the implementation simpler and robust, it tries to reinstall
+ * security group rules for all the VMs in the same tenant whenever a new
+ * VM is detected or port is updated.
+ *
+ * @param tenantId tenant id to update security group rules
+ */
+ private void populateSecurityGroupRules(String tenantId, boolean install) {
+ securityGroupRuleMap.entrySet().stream()
+ .filter(entry -> getTenantId(entry.getKey()).equals(tenantId))
+ .forEach(entry -> {
+ Host local = entry.getKey();
+ entry.getValue().stream().forEach(sgRule -> {
+ setSecurityGroupRule(local.location().deviceId(),
+ sgRule.rule(),
+ getIp(local),
+ sgRule.remoteIp(), install);
+ });
+ });
+ log.debug("Updated security group rules for {}", tenantId);
+ }
+
+ private void setSecurityGroupRule(DeviceId deviceId, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp,
+ boolean install) {
+ ForwardingObjective.Builder foBuilder = buildFlowObjective(sgRule, vmIp, remoteIp);
+ if (foBuilder == null) {
+ return;
+ }
+
+ if (install) {
+ flowObjectiveService.forward(deviceId, foBuilder.add());
+ } else {
+ flowObjectiveService.forward(deviceId, foBuilder.remove());
+ }
+ }
+
+ private ForwardingObjective.Builder buildFlowObjective(OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp,
+ IpPrefix remoteIp) {
+ if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
+ // do nothing if the remote IP is my IP
+ return null;
+ }
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
+
+ return DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(DefaultTrafficTreatment.builder().build())
+ .withPriority(ACL_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId);
+ }
+
+ private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
+ Ip4Address vmIp, IpPrefix remoteIp) {
+ buildMatchEthType(sBuilder, sgRule.ethertype());
+ buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
+ buildMatchProto(sBuilder, sgRule.protocol());
+ buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(),
+ sgRule.portRangeMax(), sgRule.portRangeMin());
+ buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
+ }
+
+ private void buildMatchDirection(TrafficSelector.Builder sBuilder,
+ OpenstackSecurityGroupRule.Direction direction,
+ Ip4Address vmIp) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
+ } else {
+ sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
+ }
+ }
+
+ private void buildMatchEthType(TrafficSelector.Builder sBuilder, String etherType) {
+ // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4);
+ if (etherType != null && !Objects.equals(etherType, "null") &&
+ !etherType.toUpperCase().equals(ETHTYPE_IPV4)) {
+ log.debug("EthType {} is not supported yet in Security Group", etherType);
+ }
+ }
+
+ private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
+ OpenstackSecurityGroupRule.Direction direction) {
+ if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchIPDst(remoteIpPrefix);
+ } else {
+ sBuilder.matchIPSrc(remoteIpPrefix);
+ }
+ }
+ }
+
+ private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
+ if (protocol != null) {
+ switch (protocol.toUpperCase()) {
+ case PROTO_ICMP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
+ break;
+ case PROTO_TCP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
+ break;
+ case PROTO_UDP:
+ sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
+ break;
+ default:
+ }
+ }
+ }
+
+ private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
+ OpenstackSecurityGroupRule.Direction direction,
+ int portMin, int portMax) {
+ if (portMin > 0 && portMax > 0 && portMin == portMax) {
+ if (protocol.toUpperCase().equals(PROTO_TCP)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchTcpDst(TpPort.tpPort(portMax));
+ } else {
+ sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
+ }
+ } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
+ if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
+ sBuilder.matchUdpDst(TpPort.tpPort(portMax));
+ } else {
+ sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
+ }
+ }
+ }
+ }
+
+ private void updateSecurityGroupRulesMap(Host host) {
+ OpenstackPort osPort = openstackService.port(host.annotations().value(PORT_ID));
+ if (osPort == null) {
+ log.debug("Failed to get OpenStack port information for {}", host);
+ return;
+ }
+
+ Set<SecurityGroupRule> rules = Sets.newHashSet();
+ osPort.securityGroups().stream().forEach(sgId -> {
+ OpenstackSecurityGroup osSecGroup = openstackService.securityGroup(sgId);
+ if (osSecGroup != null) {
+ osSecGroup.rules().stream().forEach(rule -> rules.addAll(getSgRules(rule)));
+ } else {
+ // TODO handle the case that the security group removed
+ log.warn("Failed to get security group {}", sgId);
+ }
+ });
+ securityGroupRuleMap.put(host, rules);
+ }
+
+ /**
+ * Returns set of security group rules with individual remote IP by
+ * converting remote group to actual IP address.
+ *
+ * @param sgRule security group rule
+ * @return set of security group rules
+ */
+ private Set<SecurityGroupRule> getSgRules(OpenstackSecurityGroupRule sgRule) {
+ Set<SecurityGroupRule> sgRules = Sets.newHashSet();
+ if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
+ sgRules = getRemoteIps(sgRule.tenantId(), sgRule.remoteGroupId())
+ .stream()
+ .map(remoteIp -> new SecurityGroupRule(sgRule, remoteIp))
+ .collect(Collectors.toSet());
+ } else {
+ sgRules.add(new SecurityGroupRule(sgRule, sgRule.remoteIpPrefix()));
+ }
+ return sgRules;
+ }
+
+ /**
+ * Returns a set of host IP addresses engaged with supplied security group ID.
+ * It only searches a VM in the same tenant boundary.
+ *
+ * @param tenantId tenant id
+ * @param sgId security group id
+ * @return set of ip addresses in ip prefix format
+ */
+ private Set<IpPrefix> getRemoteIps(String tenantId, String sgId) {
+ Set<IpPrefix> remoteIps = Sets.newHashSet();
+ securityGroupRuleMap.entrySet().stream()
+ .filter(entry -> Objects.equals(getTenantId(entry.getKey()), tenantId))
+ .forEach(entry -> {
+ if (entry.getValue().stream()
+ .anyMatch(rule -> rule.rule().secuityGroupId().equals(sgId))) {
+ remoteIps.add(IpPrefix.valueOf(getIp(entry.getKey()), 32));
+ }
+ });
+ return remoteIps;
+ }
+
+ private void updateSecurityGroupRules(Host host, boolean isHostAdded) {
+ String tenantId = getTenantId(host);
+ populateSecurityGroupRules(tenantId, false);
+
+ if (isHostAdded) {
+ updateSecurityGroupRulesMap(host);
+ } else {
+ securityGroupRuleMap.remove(host);
+ }
+
+ Tools.stream(hostService.getHosts())
+ .filter(h -> Objects.equals(getTenantId(h), getTenantId(host)))
+ .forEach(this::updateSecurityGroupRulesMap);
+
+ populateSecurityGroupRules(tenantId, true);
+ }
+
+ @Override
+ protected void hostDetected(Host host) {
+ updateSecurityGroupRules(host, true);
+ log.info("Applied security group rules for {}", host);
+ }
+
+ @Override
+ protected void hostRemoved(Host host) {
+ updateSecurityGroupRules(host, false);
+ log.info("Applied security group rules for {}", host);
+ }
+
+ private final class SecurityGroupRule {
+ private final OpenstackSecurityGroupRule rule;
+ private final IpPrefix remoteIp;
+
+ private SecurityGroupRule(OpenstackSecurityGroupRule rule, IpPrefix remoteIp) {
+ this.rule = rule;
+ this.remoteIp = remoteIp;
+ }
+
+ private OpenstackSecurityGroupRule rule() {
+ return rule;
+ }
+
+ private IpPrefix remoteIp() {
+ return remoteIp;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof SecurityGroupRule) {
+ SecurityGroupRule that = (SecurityGroupRule) obj;
+ if (Objects.equals(rule, that.rule) &&
+ Objects.equals(remoteIp, that.remoteIp)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rule, remoteIp);
+ }
+ }
+}
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
new file mode 100644
index 0000000..24ab533
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.switching;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Tools;
+import org.onosproject.core.CoreService;
+import org.onosproject.dhcp.DhcpService;
+import org.onosproject.dhcp.IpAssignment;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.DefaultHostDescription;
+import org.onosproject.net.host.HostDescription;
+import org.onosproject.net.host.HostProvider;
+import org.onosproject.net.host.HostProviderRegistry;
+import org.onosproject.net.host.HostProviderService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackNetwork;
+import org.onosproject.openstackinterface.OpenstackPort;
+import org.onosproject.openstackinterface.OpenstackSubnet;
+import org.onosproject.openstacknetworking.OpenstackPortInfo;
+import org.onosproject.openstacknetworking.OpenstackSwitchingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknetworking.switching.Constants.*;
+
+@Service
+@Component(immediate = true)
+/**
+ * Populates forwarding rules for VMs created by Openstack.
+ */
+public final class OpenstackSwitchingManager extends AbstractProvider
+ implements OpenstackSwitchingService, HostProvider {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostProviderRegistry hostProviderRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DhcpService dhcpService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MastershipService mastershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackInterfaceService openstackService;
+
+ private final ExecutorService deviceEventExecutor =
+ Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "device-event"));
+ private final ExecutorService configEventExecutor =
+ Executors.newSingleThreadExecutor(groupedThreads("onos/openstackswitching", "config-event"));
+ private final InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
+
+ private HostProviderService hostProvider;
+
+ /**
+ * Creates OpenStack switching host provider.
+ */
+ public OpenstackSwitchingManager() {
+ super(new ProviderId("host", APP_ID));
+ }
+
+ @Activate
+ protected void activate() {
+ coreService.registerApplication(APP_ID);
+ deviceService.addListener(internalDeviceListener);
+ hostProvider = hostProviderRegistry.register(this);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ hostProviderRegistry.unregister(this);
+ deviceService.removeListener(internalDeviceListener);
+
+ deviceEventExecutor.shutdown();
+ configEventExecutor.shutdown();
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public void triggerProbe(Host host) {
+ // no probe is required
+ }
+
+ @Override
+ // TODO remove this and openstackPortInfo
+ public Map<String, OpenstackPortInfo> openstackPortInfo() {
+ Map<String, OpenstackPortInfo> portInfoMap = Maps.newHashMap();
+
+ Tools.stream(hostService.getHosts()).filter(this::isValidHost).forEach(host -> {
+ Port port = deviceService.getPort(
+ host.location().deviceId(),
+ host.location().port());
+
+ OpenstackPortInfo portInfo = OpenstackPortInfo.builder()
+ .setDeviceId(host.location().deviceId())
+ .setHostMac(host.mac())
+ .setNetworkId(host.annotations().value(NETWORK_ID))
+ .setGatewayIP(Ip4Address.valueOf(host.annotations().value(GATEWAY_IP)))
+ .setVni(Long.valueOf(host.annotations().value(VXLAN_ID)))
+ .setHostIp(host.ipAddresses().stream().findFirst().get().getIp4Address())
+ .build();
+
+ portInfoMap.put(port.annotations().value(PORT_NAME), portInfo);
+ });
+
+ return portInfoMap;
+ }
+
+ // TODO remove this and openstackPortInfo
+ private boolean isValidHost(Host host) {
+ return !host.ipAddresses().isEmpty() &&
+ host.annotations().value(VXLAN_ID) != null &&
+ host.annotations().value(NETWORK_ID) != null &&
+ host.annotations().value(TENANT_ID) != null &&
+ host.annotations().value(GATEWAY_IP) != null &&
+ host.annotations().value(PORT_ID) != null;
+ }
+
+ private void processPortAdded(Port port) {
+ OpenstackPort osPort = openstackService.port(port);
+ if (osPort == null) {
+ log.warn("Failed to get OpenStack port for {}", port);
+ return;
+ }
+
+ OpenstackNetwork osNet = openstackService.network(osPort.networkId());
+ if (osNet == null) {
+ log.warn("Failed to get OpenStack network {}",
+ osPort.networkId());
+ return;
+ }
+
+ registerDhcpInfo(osPort);
+ ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
+ // TODO remove this and openstackPortInfo
+ String gatewayIp = osNet.subnets().stream().findFirst().get().gatewayIp();
+
+ // Added CREATE_TIME intentionally to trigger HOST_UPDATED event for the
+ // existing instances.
+ DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+ .set(NETWORK_ID, osPort.networkId())
+ .set(PORT_ID, osPort.id())
+ .set(VXLAN_ID, osNet.segmentId())
+ .set(TENANT_ID, osNet.tenantId())
+ // TODO remove this and openstackPortInfo
+ .set(GATEWAY_IP, gatewayIp)
+ .set(CREATE_TIME, String.valueOf(System.currentTimeMillis()));
+
+ HostDescription hostDesc = new DefaultHostDescription(
+ osPort.macAddress(),
+ VlanId.NONE,
+ new HostLocation(connectPoint, System.currentTimeMillis()),
+ Sets.newHashSet(osPort.fixedIps().values()),
+ annotations.build());
+
+ HostId hostId = HostId.hostId(osPort.macAddress());
+ hostProvider.hostDetected(hostId, hostDesc, false);
+ }
+
+ private void processPortRemoved(Port port) {
+ ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
+ hostService.getConnectedHosts(connectPoint).stream()
+ .forEach(host -> {
+ dhcpService.removeStaticMapping(host.mac());
+ hostProvider.hostVanished(host.id());
+ });
+ }
+
+ private void registerDhcpInfo(OpenstackPort openstackPort) {
+ checkNotNull(openstackPort);
+ checkArgument(!openstackPort.fixedIps().isEmpty());
+
+ OpenstackSubnet openstackSubnet = openstackService.subnets().stream()
+ .filter(n -> n.networkId().equals(openstackPort.networkId()))
+ .findFirst().orElse(null);
+ if (openstackSubnet == null) {
+ log.warn("Failed to find subnet for {}", openstackPort);
+ return;
+ }
+
+ Ip4Address ipAddress = openstackPort.fixedIps().values().stream().findFirst().get();
+ IpPrefix subnetPrefix = IpPrefix.valueOf(openstackSubnet.cidr());
+ Ip4Address broadcast = Ip4Address.makeMaskedAddress(
+ ipAddress,
+ subnetPrefix.prefixLength());
+
+ // TODO: supports multiple DNS servers
+ Ip4Address domainServer = openstackSubnet.dnsNameservers().isEmpty() ?
+ DNS_SERVER_IP : openstackSubnet.dnsNameservers().get(0);
+
+ IpAssignment ipAssignment = IpAssignment.builder()
+ .ipAddress(ipAddress)
+ .leasePeriod(DHCP_INFINITE_LEASE)
+ .timestamp(new Date())
+ .subnetMask(Ip4Address.makeMaskPrefix(subnetPrefix.prefixLength()))
+ .broadcast(broadcast)
+ .domainServer(domainServer)
+ .assignmentStatus(Option_RangeNotEnforced)
+ .routerAddress(Ip4Address.valueOf(openstackSubnet.gatewayIp()))
+ .build();
+
+ dhcpService.setStaticMapping(openstackPort.macAddress(), ipAssignment);
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ if (!mastershipService.isLocalMaster(device.id())) {
+ // do not allow to proceed without mastership
+ return;
+ }
+
+ Port port = event.port();
+ if (port == null) {
+ return;
+ }
+
+ String portName = port.annotations().value(PORT_NAME);
+ if (Strings.isNullOrEmpty(portName) ||
+ !portName.startsWith(PORTNAME_PREFIX_VM)) {
+ // handles VM connected port event only
+ return;
+ }
+
+ switch (event.type()) {
+ case PORT_UPDATED:
+ if (!event.port().isEnabled()) {
+ deviceEventExecutor.execute(() -> processPortRemoved(event.port()));
+ }
+ break;
+ case PORT_ADDED:
+ deviceEventExecutor.execute(() -> processPortAdded(event.port()));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
new file mode 100644
index 0000000..732be7d
--- /dev/null
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingRulePopulator.java
@@ -0,0 +1,293 @@
+/*
+* Copyright 2016-present Open Networking Laboratory
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.openstacknetworking.switching;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.openstacknode.OpenstackNodeService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.onosproject.openstacknetworking.switching.Constants.*;
+
+/**
+ * Populates switching flow rules.
+ */
+@Component(immediate = true)
+public final class OpenstackSwitchingRulePopulator extends AbstractVmHandler {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackNodeService nodeService;
+
+
+ private static final String TUNNEL_DST = "tunnelDst";
+
+ @Activate
+ protected void activate() {
+ super.activate();
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ super.deactivate();
+ }
+
+ private void populateSwitchingRules(Host host) {
+ populateFlowRulesForTunnelTag(host);
+ populateFlowRulesForTrafficToSameCnode(host);
+ populateFlowRulesForTrafficToDifferentCnode(host);
+
+ log.debug("Populated switching rule for {}", host);
+ }
+
+ private void populateFlowRulesForTunnelTag(Host host) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchInPort(host.location().port());
+
+ tBuilder.setTunnelId(Long.valueOf(getVni(host)));
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(TUNNELTAG_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId)
+ .add();
+
+ flowObjectiveService.forward(host.location().deviceId(), fo);
+ }
+
+ private void populateFlowRulesForTrafficToSameCnode(Host host) {
+ //For L2 Switching Case
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(getIp(host).toIpPrefix())
+ .matchTunnelId(Long.valueOf(getVni(host)));
+
+ tBuilder.setOutput(host.location().port());
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId)
+ .add();
+
+ flowObjectiveService.forward(host.location().deviceId(), fo);
+ }
+
+ private void populateFlowRulesForTrafficToDifferentCnode(Host host) {
+ Ip4Address localVmIp = getIp(host);
+ DeviceId localDeviceId = host.location().deviceId();
+ Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
+
+ if (!localDataIp.isPresent()) {
+ log.debug("Failed to get data IP for device {}",
+ host.location().deviceId());
+ return;
+ }
+
+ String vni = getVni(host);
+ getVmsInDifferentCnode(host).forEach(remoteVm -> {
+ Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
+ if (remoteDataIp.isPresent()) {
+ setVxLanFlowRule(vni,
+ localDeviceId,
+ remoteDataIp.get().getIp4Address(),
+ getIp(remoteVm));
+
+ setVxLanFlowRule(vni,
+ remoteVm.location().deviceId(),
+ localDataIp.get().getIp4Address(),
+ localVmIp);
+ }
+ });
+ }
+
+ private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
+ Ip4Address vmIp) {
+ Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
+ if (!tunnelPort.isPresent()) {
+ log.warn("Failed to get tunnel port from {}", deviceId);
+ return;
+ }
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchTunnelId(Long.parseLong(vni))
+ .matchIPDst(vmIp.toIpPrefix());
+ tBuilder.extension(buildNiciraExtenstion(deviceId, remoteIp), deviceId)
+ .setOutput(tunnelPort.get());
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId)
+ .add();
+
+ flowObjectiveService.forward(deviceId, fo);
+ }
+
+ private void removeSwitchingRules(Host host) {
+ removeFlowRuleForTunnelTag(host);
+ removeFlowRuleForVMsInSameCnode(host);
+ removeFlowRuleForVMsInDiffrentCnode(host);
+
+ log.debug("Removed switching rule for {}", host);
+ }
+
+ private void removeFlowRuleForTunnelTag(Host host) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchInPort(host.location().port());
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(TUNNELTAG_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .fromApp(appId)
+ .remove();
+
+ flowObjectiveService.forward(host.location().deviceId(), fo);
+ }
+
+ private void removeFlowRuleForVMsInSameCnode(Host host) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(getIp(host).toIpPrefix())
+ .matchTunnelId(Long.valueOf(getVni(host)));
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(DefaultTrafficTreatment.builder().build())
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .fromApp(appId)
+ .remove();
+
+ flowObjectiveService.forward(host.location().deviceId(), fo);
+ }
+
+ private void removeFlowRuleForVMsInDiffrentCnode(Host host) {
+ DeviceId deviceId = host.location().deviceId();
+ final boolean anyPortRemainedInSameCnode = hostService.getConnectedHosts(deviceId)
+ .stream()
+ .filter(this::isValidHost)
+ .anyMatch(h -> Objects.equals(getVni(h), getVni(host)));
+
+ getVmsInDifferentCnode(host).forEach(h -> {
+ removeVxLanFlowRule(h.location().deviceId(), getIp(host), getVni(host));
+ if (!anyPortRemainedInSameCnode) {
+ removeVxLanFlowRule(deviceId, getIp(h), getVni(host));
+ }
+ });
+ }
+
+ private void removeVxLanFlowRule(DeviceId deviceId, Ip4Address vmIp, String vni) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchTunnelId(Long.valueOf(vni))
+ .matchIPDst(vmIp.toIpPrefix());
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(DefaultTrafficTreatment.builder().build())
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .fromApp(appId)
+ .remove();
+
+ flowObjectiveService.forward(deviceId, fo);
+ }
+
+ private ExtensionTreatment buildNiciraExtenstion(DeviceId deviceId, Ip4Address remoteIp) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && !device.is(ExtensionTreatmentResolver.class)) {
+ log.error("The extension treatment is not supported");
+ return null;
+ }
+
+ ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
+ ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ try {
+ treatment.setPropertyValue(TUNNEL_DST, remoteIp);
+ return treatment;
+ } catch (ExtensionPropertyException e) {
+ log.warn("Failed to get tunnelDst extension treatment for {}", deviceId);
+ return null;
+ }
+ }
+
+ @Override
+ protected void hostDetected(Host host) {
+ populateSwitchingRules(host);
+ log.info("Added new virtual machine to switching service {}", host);
+ }
+
+ @Override
+ protected void hostRemoved(Host host) {
+ removeSwitchingRules(host);
+ log.info("Removed virtual machine from switching service {}", host);
+ }
+}
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/package-info.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/package-info.java
similarity index 100%
rename from apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/package-info.java
rename to apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/package-info.java
diff --git a/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java b/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
index af46e7b..e23a3ee 100644
--- a/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
+++ b/apps/openstacknetworking/web/src/main/java/org/onosproject/openstacknetworking/web/OpenstackPortWebResource.java
@@ -15,16 +15,7 @@
*/
package org.onosproject.openstacknetworking.web;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstackinterface.web.OpenstackPortCodec;
-import org.onosproject.openstacknetworking.OpenstackPortInfo;
-import org.onosproject.openstacknetworking.OpenstackRoutingService;
-import org.onosproject.openstacknetworking.OpenstackSwitchingService;
import org.onosproject.rest.AbstractWebResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -43,47 +34,16 @@
@Path("ports")
public class OpenstackPortWebResource extends AbstractWebResource {
- private final Logger log = LoggerFactory.getLogger(getClass());
- private static final String PORTNAME_PREFIX_VM = "tap";
- private static final OpenstackPortCodec PORT_CODEC = new OpenstackPortCodec();
-
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createPorts(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode portNode = (ObjectNode) mapper.readTree(input);
-
- OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
- OpenstackSwitchingService switchingService =
- getService(OpenstackSwitchingService.class);
- switchingService.createPorts(openstackPort);
-
- log.debug("REST API ports is called with {}", portNode.toString());
- return Response.status(Response.Status.OK).build();
-
- } catch (Exception e) {
- log.error("Creates Port failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ return Response.status(Response.Status.OK).build();
}
@Path("{portUUID}")
@DELETE
public Response deletePorts(@PathParam("portUUID") String id) {
- OpenstackSwitchingService switchingService =
- getService(OpenstackSwitchingService.class);
- OpenstackPortInfo portInfo = switchingService.openstackPortInfo()
- .get(PORTNAME_PREFIX_VM.concat(id.substring(0, 11)));
- OpenstackRoutingService routingService =
- getService(OpenstackRoutingService.class);
- routingService.checkDisassociatedFloatingIp(id, portInfo);
-
- switchingService.removePort(id);
-
return Response.noContent().build();
}
@@ -92,23 +52,7 @@
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updatePorts(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode portNode = (ObjectNode) mapper.readTree(input);
-
- OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
- OpenstackSwitchingService switchingService =
- getService(OpenstackSwitchingService.class);
- switchingService.updatePort(openstackPort);
-
- log.debug("REST API update port is called with {}", portNode.toString());
- return Response.status(Response.Status.OK).build();
-
- } catch (Exception e) {
- log.error("Update Port failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ // TODO call security group update here
+ return Response.status(Response.Status.OK).build();
}
}
diff --git a/apps/openstacknode/BUCK b/apps/openstacknode/BUCK
index e614257..c9ad7ac 100644
--- a/apps/openstacknode/BUCK
+++ b/apps/openstacknode/BUCK
@@ -16,5 +16,5 @@
category = 'Utility',
url = 'http://onosproject.org',
description = 'SONA Openstack Node Bootstrap Application.',
- required_app = [ 'org.onosproject.ovsdb-base' ],
+ required_apps = [ 'org.onosproject.ovsdb-base', 'org.onosproject.drivers.ovsdb' ]
)
diff --git a/apps/openstacknode/pom.xml b/apps/openstacknode/pom.xml
index 5524b22..71cb5b2 100644
--- a/apps/openstacknode/pom.xml
+++ b/apps/openstacknode/pom.xml
@@ -38,7 +38,8 @@
<onos.app.url>http://onosproject.org</onos.app.url>
<onos.app.readme>SONA Openstack Node Bootstrap Application</onos.app.readme>
<onos.app.requires>
- org.onosproject.ovsdb-base
+ org.onosproject.ovsdb-base,
+ org.onosproject.drivers.ovsdb
</onos.app.requires>
</properties>
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
index 1995111..039c3ed 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
@@ -242,7 +242,7 @@
deviceService.removeListener(deviceListener);
nodeStore.removeListener(nodeStoreListener);
- componentConfigService.unregisterProperties(getClass(), true);
+ componentConfigService.unregisterProperties(getClass(), false);
configRegistry.unregisterConfigFactory(configFactory);
leadershipService.withdraw(appId.name());