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
diff --git a/apps/openstackswitching/pom.xml b/apps/openstackswitching/pom.xml
index 245b9e8..52129b6 100644
--- a/apps/openstackswitching/pom.xml
+++ b/apps/openstackswitching/pom.xml
@@ -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>
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
index afaf7a2..0c139d8 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
@@ -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 @@
 
     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 @@
      * @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);
+        }
     }
 }
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java
deleted file mode 100644
index 9c3641c..0000000
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-* 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");
-    }
-}
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
index dc7c026..7bfdf29 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
@@ -26,8 +26,18 @@
     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 @@
     }
 
     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 @@
         return this.segmentId;
     }
 
-    public String networkType() {
+    public NetworkType networkType() {
         return this.networkType;
     }
 
@@ -72,7 +82,7 @@
         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 @@
             return this;
         }
 
-        public Builder networkType(String type) {
+        public Builder networkType(NetworkType type) {
             this.networkType = type;
 
             return this;
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java
new file mode 100644
index 0000000..39d783e
--- /dev/null
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java
@@ -0,0 +1,159 @@
+/*
+ * 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);
+        }
+    }
+}
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
index baae7f8..4be8a50 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
@@ -24,13 +24,12 @@
 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.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 @@
     @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 @@
     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 @@
 
         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 @@
 
     @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 @@
         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 @@
         // 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 @@
     }
 
     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 @@
         // 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 @@
                 .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 @@
                 .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 @@
 
             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);
-                    }
-                }
             }
         }
     }
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
index 9ead05f..661a873 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
@@ -87,7 +87,6 @@
      */
     public void populateDefaultRules(DeviceId id) {
 
-        //setFlowRuleForDHCP(id);
         setFlowRuleForArp(id);
 
         log.warn("Default rule has been set");
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
index d97b39c..3d40d51 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
@@ -46,4 +46,10 @@
      */
     void createNetwork(OpenstackNetwork openstackNetwork);
 
+    /**
+     * Store the subnet information created by openstack.
+     *
+     * @param openstackSubnet subnet information
+     */
+    void createSubnet(OpenstackSubnet openstackSubnet);
 }
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
index 43bd158..fc1509d 100644
--- a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
@@ -54,6 +54,8 @@
                 .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());
         }
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java
new file mode 100644
index 0000000..a643057
--- /dev/null
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+    }
+}
diff --git a/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java
new file mode 100644
index 0000000..af1ae9d
--- /dev/null
+++ b/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java
@@ -0,0 +1,64 @@
+/*
+ * 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();
+        }
+    }
+
+}
diff --git a/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml b/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
index 53b0e2e..4f50ef7 100644
--- a/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
+++ b/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
@@ -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>