daniel
Committed by Gerrit Code Review

SONA: openstackSwitching

-Added ARP handler
-Added OpenstackSubnet to encode and decode subnet-related message from Openstack
-Rebased with 5896 (Modified DhcpService for OpenStack)

Change-Id: Ic63e5c82d0301fa5c45d1a41548d8dc3a8b1ec57
......@@ -80,6 +80,11 @@
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-dhcp-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
......
......@@ -15,11 +15,20 @@
*/
package org.onosproject.openstackswitching;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.nio.ByteBuffer;
import java.util.Map;
/**
* It handles ARP packet from VMs.
......@@ -28,16 +37,18 @@ public class OpenstackArpHandler {
private static Logger log = LoggerFactory
.getLogger(OpenstackArpHandler.class);
HashMap<String, OpenstackPort> openstackPortHashMap;
private PacketService packetService;
private Map<String, OpenstackPort> openstackPortMap;
/**
* Constructs an OpenstackArpHandler.
* Returns OpenstackArpHandler reference.
*
* @param openstackPortMap port map
* @param openstackPortMap
* @param packetService
*/
public OpenstackArpHandler(HashMap<String, OpenstackPort> openstackPortMap) {
this.openstackPortHashMap = openstackPortMap;
public OpenstackArpHandler(Map<String, OpenstackPort> openstackPortMap, PacketService packetService) {
this.openstackPortMap = openstackPortMap;
this.packetService = packetService;
}
/**
......@@ -46,6 +57,50 @@ public class OpenstackArpHandler {
* @param pkt ARP request packet
*/
public void processPacketIn(InboundPacket pkt) {
log.warn("Received an ARP packet");
Ethernet ethernet = pkt.parsed();
ARP arp = (ARP) ethernet.getPayload();
if (arp.getOpCode() == ARP.OP_REQUEST) {
byte[] srcMacAddress = arp.getSenderHardwareAddress();
byte[] srcIPAddress = arp.getSenderProtocolAddress();
byte[] dstIPAddress = arp.getTargetProtocolAddress();
//Searches the Dst MAC Address based on openstackPortMap
MacAddress macAddress = null;
OpenstackPort openstackPort = openstackPortMap.values().stream().filter(e -> e.fixedIps().
containsValue(Ip4Address.valueOf(dstIPAddress))).findAny().orElse(null);
if (openstackPort != null) {
macAddress = openstackPort.macAddress();
log.debug("Found MACAddress: {}", macAddress.toString());
} else {
return;
}
//Creates a response packet
ARP arpReply = new ARP();
arpReply.setOpCode(ARP.OP_REPLY)
.setHardwareAddressLength(arp.getHardwareAddressLength())
.setHardwareType(arp.getHardwareType())
.setProtocolAddressLength(arp.getProtocolAddressLength())
.setProtocolType(arp.getProtocolType())
.setSenderHardwareAddress(macAddress.toBytes())
.setSenderProtocolAddress(dstIPAddress)
.setTargetHardwareAddress(srcMacAddress)
.setTargetProtocolAddress(srcIPAddress);
//Sends a response packet
ethernet.setDestinationMACAddress(srcMacAddress)
.setSourceMACAddress(macAddress)
.setEtherType(Ethernet.TYPE_ARP)
.setPayload(arpReply);
TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
builder.setOutput(pkt.receivedFrom().port());
OutboundPacket packet = new DefaultOutboundPacket(pkt.receivedFrom().deviceId(),
builder.build(), ByteBuffer.wrap(ethernet.serialize()));
packetService.emit(packet);
}
}
}
......
/*
* Copyright 2015 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.openstackswitching;
import org.onosproject.net.packet.InboundPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* It handles DHCP request packets.
*/
public class OpenstackDhcpHandler {
private static Logger log = LoggerFactory
.getLogger(OpenstackDhcpHandler.class);
/**
* Returns OpenstackDhcpHandler reference.
*/
public OpenstackDhcpHandler() {
}
/**
* Processes DHCP request packets.
*
* @param pkt DHCP request packet
*/
public void processPacketIn(InboundPacket pkt) {
log.warn("Received a DHCP packet");
}
}
......@@ -26,8 +26,18 @@ public final class OpenstackNetwork {
private String name;
private String tenantId;
private String segmentId;
private String networkType;
private String id;
private NetworkType networkType;
public enum NetworkType {
/**
* Currently only VXLAN moded is supported.
*/
VXLAN,
VLAN,
STT,
LOCAL
}
/**
* Returns the builder object of the OpenstackNetwork class.
......@@ -39,12 +49,12 @@ public final class OpenstackNetwork {
}
private OpenstackNetwork(String name, String tenantId, String id, String sid,
String type) {
NetworkType type) {
this.name = checkNotNull(name);
this.tenantId = checkNotNull(tenantId);
this.segmentId = checkNotNull(sid);
this.id = checkNotNull(id);
this.networkType = checkNotNull(type);
this.networkType = type;
}
public String name() {
......@@ -63,7 +73,7 @@ public final class OpenstackNetwork {
return this.segmentId;
}
public String networkType() {
public NetworkType networkType() {
return this.networkType;
}
......@@ -72,7 +82,7 @@ public final class OpenstackNetwork {
private String tenantId;
private String id;
private String sid;
private String networkType;
private NetworkType networkType;
public Builder name(String name) {
this.name = name;
......@@ -98,7 +108,7 @@ public final class OpenstackNetwork {
return this;
}
public Builder networkType(String type) {
public Builder networkType(NetworkType type) {
this.networkType = type;
return this;
......
/*
* Copyright 2015 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.openstackswitching;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents the subnet information given by Neutron.
*
*/
public final class OpenstackSubnet {
private String name;
private boolean enableHhcp;
private String networkId;
private String tenantId;
private String dnsNameservers;
private String gatewayIp;
private String cidr;
private String id;
private OpenstackSubnet(String name, boolean enableHhcp, String networkId,
String tenantId, String dnsNameservers, String gatewayIp,
String cidr, String id) {
this.name = name;
this.enableHhcp = enableHhcp;
this.networkId = checkNotNull(networkId);
this.tenantId = checkNotNull(tenantId);
this.dnsNameservers = dnsNameservers;
this.gatewayIp = gatewayIp;
this.cidr = checkNotNull(cidr);
this.id = checkNotNull(id);
}
/**
* Returns OpenstackSubnet builder object.
*
* @return OpenstackSubnet builder
*/
public static OpenstackSubnet.Builder builder() {
return new Builder();
}
public String name() {
return name;
}
public boolean enableHhcp() {
return enableHhcp;
}
public String networkId() {
return networkId;
}
public String tenantId() {
return tenantId;
}
public String dnsNameservers() {
return dnsNameservers;
}
public String gatewayIp() {
return gatewayIp;
}
public String cidr() {
return cidr;
}
public String id() {
return id;
}
// TODO : Implement the following functions when necessary
/**
* OpenstackSubnet Builder class.
*
*/
public static final class Builder {
private String name;
private boolean enableDhcp;
private String networkId;
private String tenantId;
private String dnsNameservers;
private String gatewayIp;
private String cidr;
private String id;
Builder() {}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setEnableDhcp(boolean enableDhcp) {
this.enableDhcp = enableDhcp;
return this;
}
public Builder setNetworkId(String networkId) {
this.networkId = networkId;
return this;
}
public Builder setTenantId(String tenantId) {
this.tenantId = tenantId;
return this;
}
public Builder setDnsNameservers(String dnsNameservers) {
this.dnsNameservers = dnsNameservers;
return this;
}
public Builder setGatewayIp(String gatewayIp) {
this.gatewayIp = gatewayIp;
return this;
}
public Builder setCidr(String cidr) {
this.cidr = cidr;
return this;
}
public Builder setId(String id) {
this.id = id;
return this;
}
public OpenstackSubnet build() {
return new OpenstackSubnet(name, enableDhcp, networkId, tenantId,
dnsNameservers, gatewayIp, cidr, id);
}
}
}
......@@ -24,13 +24,12 @@ 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.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.dhcp.DhcpService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
......@@ -45,8 +44,8 @@ import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
......@@ -73,12 +72,14 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DhcpService dhcpService;
public static final int DHCP_PORT = 67;
private ApplicationId appId;
private OpenstackArpHandler arpHandler;
private OpenstackDhcpHandler dhcpHandler = new OpenstackDhcpHandler();
private OpenstackSwitchingRulePopulator rulePopulator;
private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);
......@@ -86,12 +87,14 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
// Map <port_id, OpenstackPort>
private HashMap<String, OpenstackPort> openstackPortMap;
private Map<String, OpenstackPort> openstackPortMap;
// Map <network_id, OpenstackNetwork>
private HashMap<String, OpenstackNetwork> openstackNetworkMap;
private Map<String, OpenstackNetwork> openstackNetworkMap;
// Map <subnet_id, OpenstackSubner>
private Map<String, OpenstackSubnet> openstackSubnetMap;
// Map <vni, List <Entry <portName, host ip>>
private HashMap<String, List<PortInfo>> vniPortMap;
private HashMap<Ip4Address, Port> tunnelPortMap;
private Map<String, List<PortInfo>> vniPortMap;
private Map<Ip4Address, Port> tunnelPortMap;
@Activate
......@@ -104,11 +107,11 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
openstackPortMap = Maps.newHashMap();
openstackNetworkMap = Maps.newHashMap();
openstackSubnetMap = Maps.newHashMap();
vniPortMap = Maps.newHashMap();
tunnelPortMap = Maps.newHashMap();
arpHandler = new OpenstackArpHandler(openstackPortMap);
arpHandler = new OpenstackArpHandler(openstackPortMap, packetService);
log.info("Started");
}
......@@ -124,9 +127,43 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
@Override
public void createPorts(OpenstackPort openstackPort) {
//For DHCP purpose
//registerDhcpInfo(openstackPort);
openstackPortMap.put(openstackPort.id(), openstackPort);
}
/*
private void registerDhcpInfo(OpenstackPort openstackPort) {
Ip4Address ip4Address;
Ip4Address subnetMask;
Ip4Address dhcpServer;
Ip4Address gatewayIPAddress;
Ip4Address domainServer;
OpenstackSubnet openstackSubnet;
ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
openstackSubnet = openstackSubnetMap.values().stream()
.filter(n -> n.networkId().equals(openstackPort.networkId()))
.findFirst().get();
int prefix;
String[] parts = openstackSubnet.cidr().split("/");
prefix = Integer.parseInt(parts[1]);
int mask = 0xffffffff << (32 - prefix);
byte[] bytes = new byte[]{(byte) (mask >>> 24),
(byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
subnetMask = Ip4Address.valueOf(bytes);
gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
dhcpServer = gatewayIPAddress;
domainServer = Ip4Address.valueOf("8.8.8.8");
dhcpService.setStaticMappingOpenstack(openstackPort.macAddress(),
ip4Address, subnetMask, dhcpServer, gatewayIPAddress, domainServer);
}
*/
@Override
public void deletePorts() {
......@@ -142,8 +179,15 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
}
@Override
public void createSubnet(OpenstackSubnet openstackSubnet) {
openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet);
log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id()));
}
private void processDeviceAdded(Device device) {
log.warn("device {} is added", device.id());
log.debug("device {} is added", device.id());
rulePopulator.populateDefaultRules(device.id());
}
......@@ -152,7 +196,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
// TODO: Make it stateless
// TODO: All the logics need to be processed inside of the rulePopulator class
synchronized (vniPortMap) {
log.warn("port {} is updated", port.toString());
log.debug("port {} is updated", port.toString());
updatePortMaps(device, port);
if (!port.annotations().value("portName").equals("vxlan")) {
......@@ -163,7 +207,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
}
private void processPortRemoved(Device device, Port port) {
log.warn("port {} is removed", port.toString());
log.debug("port {} is removed", port.toString());
// TODO: need to update the vniPortMap
}
......@@ -182,7 +226,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
// TODO: Avoid duplicate flow rule set up for VMs in other Cnode
// (possibly avoided by flowrule subsystem?)
if (tunnelPortMap.get(hostIpAddress) == null) {
log.warn("There is no tunnel port information");
log.debug("There is no tunnel port information");
return;
}
String vni = getVniForPort(portName);
......@@ -251,20 +295,19 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
.filter(p -> p.id().startsWith(uuid))
.findFirst().get();
if (port == null) {
log.warn("No port information for port {}", portName);
log.debug("No port information for port {}", portName);
return null;
}
//OpenstackSubnet subnet = openstackSubnetMap.values().stream()
// .filter(s -> s.networkId().equals(port.networkId()))
// .findFirst().get();
//if (subnet == null) {
// log.warn("No subnet information for network {}", subnet.id());
// return null;
//}
OpenstackSubnet subnet = openstackSubnetMap.values().stream()
.filter(s -> s.networkId().equals(port.networkId()))
.findFirst().get();
if (subnet == null) {
log.debug("No subnet information for network {}", subnet.id());
return null;
}
//return Ip4Prefix.valueOf(subnet.cidr());
return null;
return Ip4Prefix.valueOf(subnet.cidr());
}
/**
......@@ -280,14 +323,14 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
.filter(p -> p.id().startsWith(uuid))
.findFirst().get();
if (port == null) {
log.warn("No port information for port {}", portName);
log.debug("No port information for port {}", portName);
return null;
}
OpenstackNetwork network = openstackNetworkMap.values().stream()
.filter(n -> n.id().equals(port.networkId()))
.findFirst().get();
if (network == null) {
log.warn("No VNI information for network {}", network.id());
log.debug("No VNI information for network {}", network.id());
return null;
}
......@@ -357,15 +400,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
arpHandler.processPacketIn(pkt);
} else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
IPv4 ipPacket = (IPv4) ethernet.getPayload();
if (ipPacket.getProtocol() == IPv4.PROTOCOL_UDP) {
UDP udpPacket = (UDP) ipPacket.getPayload();
if (udpPacket.getDestinationPort() == DHCP_PORT) {
dhcpHandler.processPacketIn(pkt);
}
}
}
}
}
......
......@@ -87,7 +87,6 @@ public class OpenstackSwitchingRulePopulator {
*/
public void populateDefaultRules(DeviceId id) {
//setFlowRuleForDHCP(id);
setFlowRuleForArp(id);
log.warn("Default rule has been set");
......
......@@ -46,4 +46,10 @@ public interface OpenstackSwitchingService {
*/
void createNetwork(OpenstackNetwork openstackNetwork);
/**
* Store the subnet information created by openstack.
*
* @param openstackSubnet subnet information
*/
void createSubnet(OpenstackSubnet openstackSubnet);
}
......
......@@ -54,6 +54,8 @@ public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> {
.id(id);
if (!networkInfo.path(NETWORK_TYPE).isMissingNode()) {
onb.networkType(OpenstackNetwork.NetworkType.valueOf(networkInfo.path(NETWORK_TYPE).
asText().toUpperCase()));
onb.name(networkInfo.path(NETWORK_TYPE).asText());
onb.segmentId(networkInfo.path(SEGMENTATION_ID).asText());
}
......
/*
* Copyright 2015 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.openstackswitching.web;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* It encodes and decodes the OpenstackSubnet.
*/
public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
private static Logger log = LoggerFactory
.getLogger(OpenstackSubnetCodec.class);
// JSON Field names
private static final String SUBNET = "subnet";
private static final String NAME = "name";
private static final String ENABLE_DHCP = "enable_dhcp";
private static final String NETWORK_ID = "network_id";
private static final String TENANT_ID = "tenant_id";
private static final String DNS_NAMESERVERS = "dns_nameservers";
private static final String GATEWAY_IP = "gateway_ip";
private static final String CIDR = "cidr";
private static final String ID = "id";
@Override
public OpenstackSubnet decode(ObjectNode json, CodecContext context) {
JsonNode subnetInfo = json.get(SUBNET);
String name = subnetInfo.path(NAME).asText();
boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean();
String networkId = subnetInfo.path(NETWORK_ID).asText();
String tenantId = subnetInfo.path(TENANT_ID).asText();
String dnsNameservsers = subnetInfo.path(DNS_NAMESERVERS).asText();
String gatewayIp = subnetInfo.path(GATEWAY_IP).asText();
String cidr = subnetInfo.path(CIDR).asText();
String id = subnetInfo.path(ID).asText();
OpenstackSubnet openstackSubnet = OpenstackSubnet.builder()
.setName(name)
.setEnableDhcp(enableDhcp)
.setNetworkId(networkId)
.setTenantId(tenantId)
.setDnsNameservers(dnsNameservsers)
.setGatewayIp(gatewayIp)
.setCidr(cidr)
.setId(id)
.build();
return openstackSubnet;
}
}
/*
* Copyright 2015 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.openstackswitching.web;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.onosproject.openstackswitching.OpenstackSwitchingService;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
@Path("subnets")
public class OpenstackSubnetWebResource extends AbstractWebResource {
protected static final Logger log = LoggerFactory
.getLogger(OpenstackSubnetWebResource.class);
private static final OpenstackSubnetCodec SUBNET_CODEC = new OpenstackSubnetCodec();
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createSubnet(InputStream input) {
try {
ObjectMapper mapper = new ObjectMapper();
ObjectNode subnetNode = (ObjectNode) mapper.readTree(input);
OpenstackSubnet openstackSubnet = SUBNET_CODEC.decode(subnetNode, this);
OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
switchingService.createSubnet(openstackSubnet);
log.info("REST API subnets is called with {}", subnetNode.toString());
return Response.status(Response.Status.OK).build();
} catch (Exception e) {
log.error("Creates VirtualSubnet failed because of exception {}",
e.toString());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
.build();
}
}
}
......@@ -31,7 +31,8 @@
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>
org.onosproject.openstackswitching.web.OpenstackPortWebResource,
org.onosproject.openstackswitching.web.OpenstackNetworkWebResource
org.onosproject.openstackswitching.web.OpenstackNetworkWebResource,
org.onosproject.openstackswitching.web.OpenstackSubnetWebResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
......