BGP Route policy distribution and flow spec

Change-Id: I8903efd225a24db6ccc85a4a3148a4dd6076e042
diff --git a/apps/bgpflowspec/bgpweb/BUCK b/apps/bgpflowspec/bgpweb/BUCK
new file mode 100755
index 0000000..a5ef9e7
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/BUCK
@@ -0,0 +1,12 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:javax.ws.rs-api',
+    '//utils/rest:onlab-rest',
+    '//apps/bgpflowspec/flowapi:onos-apps-bgpflowspec-flowapi',
+    '//apps/bgpflowspec/flowmgr:onos-apps-bgpflowspec-flowmgr',
+]
+
+osgi_jar_with_tests (
+    name = 'onos-apps-bgpflowspec-web',
+    deps = COMPILE_DEPS,
+)
diff --git a/apps/bgpflowspec/bgpweb/pom.xml b/apps/bgpflowspec/bgpweb/pom.xml
new file mode 100755
index 0000000..036a7d1
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/pom.xml
@@ -0,0 +1,78 @@
+<?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
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+        xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-app-bgpflow</artifactId>
+        <version>1.6.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-app-bgp-web</artifactId>
+    <packaging>bundle</packaging>
+    <properties>
+        <web.context>/onos/bgp</web.context>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-bgp-flowmgr</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-rest</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava-testlib</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <_wab>src/main/webapp/</_wab>
+                        <Bundle-SymbolicName>
+                            ${project.groupId}.${project.artifactId}
+                        </Bundle-SymbolicName>
+                        <Import-Package>
+                            *,org.glassfish.jersey.servlet
+                        </Import-Package>
+                        <Web-ContextPath>${web.context}</Web-ContextPath>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpFlowWebResource.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpFlowWebResource.java
new file mode 100755
index 0000000..44ba4a4
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpFlowWebResource.java
@@ -0,0 +1,352 @@
+/*
+ * 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.bgpweb.resources;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.flow.manager.BgpFlowService;
+import org.onosproject.flowapi.DefaultExtWideCommunityInt;
+import org.onosproject.flowapi.ExtFlowContainer;
+import org.onosproject.flowapi.ExtFlowTypes;
+import org.onosproject.flowapi.ExtTrafficAction;
+import org.onosproject.flowapi.ExtWideCommunityInt;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+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.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.ListIterator;
+
+import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
+import static javax.ws.rs.core.Response.Status.OK;
+
+/**
+ * Bgp flow web resource.
+ */
+
+@Path("flow")
+public class BgpFlowWebResource extends AbstractWebResource {
+
+    private BgpFlowService flowService = get(BgpFlowService.class);
+    protected static final String BGPFLOW = "bgp_flow";
+    protected static final String DEVICEID = "deviceId";
+    protected static final int LOCAL_PERF = 20;
+    private final Logger log = LoggerFactory.getLogger(BgpFlowWebResource.class);
+
+    /**
+     * Get the Bgp flow.
+     *
+     * @return 200 OK
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getBgpFlow() {
+        Boolean result = true;
+        //TODO
+        return ok(result.toString()).build();
+    }
+
+    /**
+     * Push the the Bgp flow spec.
+     *
+     * @param stream bgp flow spec in JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response createBgpFlow(InputStream stream) {
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            JsonNode flow = jsonTree.get(BGPFLOW);
+            String devId = jsonTree.get(DEVICEID).asText();
+            boolean status;
+
+            List<ExtFlowTypes> list;
+            ExtFlowContainer container;
+
+            list = codec(ExtFlowTypes.class).decode((ArrayNode) flow, this);
+
+            if (!validateRpd(list)) {
+                return Response.status(NOT_ACCEPTABLE).entity(Boolean.FALSE.toString()).build();
+            }
+
+            container = new ExtFlowContainer(list);
+            container.setDeviceId(devId);
+
+
+            status = flowService.onBgpFlowCreated(container);
+            Boolean isSuccess = Boolean.valueOf(status);
+            if (!status) {
+                return Response.status(NOT_ACCEPTABLE).entity(isSuccess.toString()).build();
+            }
+
+            return Response.status(OK).entity(isSuccess.toString()).build();
+        } catch (IOException e) {
+            log.error("Exception while parsing bgp flow.", e.toString());
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Validates the rpd and flow spec classes.
+     *
+     * @param list list of types
+     * @return a true if the validation succeeds else false
+     */
+    boolean validateRpd(List<ExtFlowTypes> list) {
+        ListIterator<ExtFlowTypes> iterator = list.listIterator();
+        ExtFlowTypes flow;
+        boolean key = false;
+        boolean rpd = false;
+        boolean nonRpd = false;
+        ExtTrafficAction flowAction = null;
+        boolean dstPfx = false;
+        boolean wcFlg = false;
+        boolean wcHop = false;
+        boolean wcWc = false;
+        boolean wcCAs = false;
+        boolean wcLAs = false;
+        boolean wcTarget = false;
+        boolean wcETarget = false;
+        boolean wcParm = false;
+
+        while (iterator.hasNext()) {
+            flow = iterator.next();
+            switch (flow.type()) {
+                case EXT_FLOW_RULE_KEY:
+                    key = true;
+                    break;
+                case IPV4_DST_PFX:
+                    dstPfx = true;
+                    break;
+                case IPV4_SRC_PFX:
+                    nonRpd = true;
+                    break;
+                case IP_PROTO_LIST:
+                    nonRpd = true;
+                    break;
+                case IN_PORT_LIST:
+                    nonRpd = true;
+                    break;
+                case DST_PORT_LIST:
+                    nonRpd = true;
+                    break;
+                case SRC_PORT_LIST:
+                    nonRpd = true;
+                    break;
+                case ICMP_TYPE_LIST:
+                    nonRpd = true;
+                    break;
+                case ICMP_CODE_LIST:
+                    nonRpd = true;
+                    break;
+                case TCP_FLAG_LIST:
+                    nonRpd = true;
+                    break;
+                case PACKET_LENGTH_LIST:
+                    nonRpd = true;
+                    break;
+                case DSCP_VALUE_LIST:
+                    nonRpd = true;
+                    break;
+                case FRAGMENT_LIST:
+                    nonRpd = true;
+                    break;
+                case TRAFFIC_ACTION:
+                    flowAction = (ExtTrafficAction) flow;
+                    if (flowAction.rpd()) {
+                        rpd = true;
+                    }
+                    break;
+                case TRAFFIC_RATE:
+                    nonRpd = true;
+                    break;
+                case TRAFFIC_REDIRECT:
+                    nonRpd = true;
+                    break;
+                case TRAFFIC_MARKING:
+                    nonRpd = true;
+                    break;
+                case WIDE_COMM_FLAGS:
+                    wcFlg = true;
+                    break;
+                case WIDE_COMM_HOP_COUNT:
+                    wcHop = true;
+                    break;
+                case WIDE_COMM_COMMUNITY:
+                    wcWc = true;
+                    break;
+                case WIDE_COMM_CONTEXT_AS:
+                    wcCAs = true;
+                    break;
+                case WIDE_COMM_LOCAL_AS:
+                    wcLAs = true;
+                    break;
+                case WIDE_COMM_TARGET:
+                    wcTarget = true;
+                    break;
+                case WIDE_COMM_EXT_TARGET:
+                    wcETarget = true;
+                    break;
+                case WIDE_COMM_PARAMETER:
+                    wcParm = true;
+                    break;
+                default:
+                    log.error("error: this type is not supported");
+                    break;
+            }
+        }
+
+        if (!key) {
+            return false;
+        }
+
+        /** checking for non Rpd. */
+        if (!rpd) {
+            if (wcFlg || wcHop || wcWc
+                    || wcCAs || wcLAs || wcParm) {
+                return false;
+            }
+        }
+
+        /** checking for Rpd. */
+        if (nonRpd || !dstPfx || !wcFlg || !wcHop
+                || !wcWc || !wcCAs || !wcLAs || !wcParm) {
+            return false;
+        }
+
+        /** If it is rpd then either of these two or both should be present.*/
+        if (!wcTarget && !wcETarget) {
+            rpd = false;
+        }
+
+        if (!handleRpdLocalPerf(list)) {
+            return false;
+        }
+
+        return rpd;
+    }
+
+    /**
+     * Validate and format the rpd local perf.
+     *
+     * @param list list of types
+     * @return a true if the validation succeeds else false
+     */
+    boolean handleRpdLocalPerf(List<ExtFlowTypes> list) {
+        ListIterator<ExtFlowTypes> iterator = list.listIterator();
+        ExtFlowTypes flow;
+
+        ExtWideCommunityInt wcComm = null;
+        ExtWideCommunityInt wcParam = null;
+        ListIterator<Integer> wcInt = null;
+        int community = 0;
+        int param = 0;
+
+        while (iterator.hasNext()) {
+            flow = iterator.next();
+            switch (flow.type()) {
+                case WIDE_COMM_COMMUNITY:
+                    wcComm = (ExtWideCommunityInt) flow;
+                    wcInt = wcComm.communityInt().listIterator();
+                    community = wcInt.next().intValue();
+                    break;
+
+                case WIDE_COMM_PARAMETER:
+                    wcParam = (ExtWideCommunityInt) flow;
+                    wcInt = wcParam.communityInt().listIterator();
+                    param = wcInt.next().intValue();
+                    break;
+                default:
+                    log.error("error: this type is not supported");
+                    break;
+            }
+        }
+
+        if (community == LOCAL_PERF) {
+            if (param > 127 || param < -127) {
+                return false;
+            }
+
+            /** if -ve then make it 1 bye value and set it, if it is positive then no issue.*/
+            if (param < 0) {
+                param = ~param + 129;
+                list.remove(wcParam);
+                ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+                resultBuilder.setwCommInt(Integer.valueOf(param));
+                resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_PARAMETER);
+                list.add(resultBuilder.build());
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Delete the the Bgp flow spec.
+     *
+     * @param stream bgp flow spec in JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     */
+    @DELETE
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response deleteBgpFlow(InputStream stream) {
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            JsonNode flow = jsonTree.get(BGPFLOW);
+            String devId = jsonTree.get(DEVICEID).asText();
+            boolean status;
+
+            List<ExtFlowTypes> list;
+            ExtFlowContainer container;
+
+            list = codec(ExtFlowTypes.class).decode((ArrayNode) flow, this);
+
+            if (!validateRpd(list)) {
+                return Response.status(NOT_ACCEPTABLE).entity(Boolean.FALSE.toString()).build();
+            }
+
+            container = new ExtFlowContainer(list);
+            container.setDeviceId(devId);
+
+
+            status = flowService.onBgpFlowDeleted(container);
+            Boolean isSuccess = Boolean.valueOf(status);
+            if (!status) {
+                return Response.status(NOT_ACCEPTABLE).entity(isSuccess.toString()).build();
+            }
+            return Response.status(OK).entity(isSuccess.toString()).build();
+        } catch (IOException e) {
+            log.error("Exception while parsing bgp flow.", e.toString());
+            throw new IllegalArgumentException(e);
+        }
+    }
+}
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpWebApplication.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpWebApplication.java
new file mode 100755
index 0000000..4ab7777
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/BgpWebApplication.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bgpweb.resources;
+
+import org.onlab.rest.AbstractWebApplication;
+import java.util.Set;
+
+/**
+ * BGP REST API web application.
+ */
+public class BgpWebApplication extends AbstractWebApplication {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return getClasses(BgpFlowWebResource.class);
+    }
+}
+
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/package-info.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/package-info.java
new file mode 100755
index 0000000..09c5210
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/resources/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * BGP web that used rest to create BGP resources.
+ */
+package org.onosproject.bgpweb.resources;
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpCodecRegistrator.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpCodecRegistrator.java
new file mode 100755
index 0000000..1140fda
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpCodecRegistrator.java
@@ -0,0 +1,50 @@
+/*
+ * 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.bgpweb.web;
+
+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.onosproject.codec.CodecService;
+import org.onosproject.flowapi.ExtFlowTypes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the JSON codec brokering service for BGP app.
+ */
+@Component(immediate = true)
+public class BgpCodecRegistrator {
+
+    private static Logger log = LoggerFactory.getLogger(BgpCodecRegistrator.class);
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CodecService codecService;
+
+    @Activate
+    public void activate() {
+        codecService.registerCodec(ExtFlowTypes.class, new BgpFlowExtensionCodec());
+        System.out.print("BgpCodecRegistrator started");
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        log.info("Stopped");
+    }
+}
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpFlowExtensionCodec.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpFlowExtensionCodec.java
new file mode 100755
index 0000000..5c6f250
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpFlowExtensionCodec.java
@@ -0,0 +1,77 @@
+/*
+ * 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.bgpweb.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.flowapi.ExtFlowTypes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BgpFlowExtensionCodec extends JsonCodec<ExtFlowTypes> {
+
+    protected static final Logger log =
+            LoggerFactory.getLogger(BgpFlowExtensionCodec.class);
+
+    protected static final String TYPE = "type";
+    protected static final String NAME = "name";
+    protected static final String PREFIX = "prefix";
+    protected static final String PROTOCOLS = "protocols";
+    protected static final String PORT = "port";
+    protected static final String DST_PORT = "destinationPort";
+    protected static final String SRC_PORT = "sourcePort";
+    protected static final String ICMP_TYPE = "icmpType";
+    protected static final String ICMP_CODE = "icmpCode";
+    protected static final String TCP_FLAG = "tcpFlag";
+    protected static final String PACKET_LENGTH = "packetLength";
+    protected static final String DSCP_VALUE = "dscpValue";
+    protected static final String FRAGMENT = "fragment";
+
+    protected static final String TRAFFIC_RATE = "trafficRate";
+    protected static final String TRAFFIC_ACTION = "trafficAction";
+    protected static final String TRAFFIC_REDIRECTION = "trafficRedirection";
+    protected static final String TRAFFIC_MARKING = "trafficMarking";
+
+    protected static final String TRAFFIC_RATE_ASN = "asn";
+    protected static final String TRAFFIC_RATE_RATE = "rate";
+    protected static final String TRAFFIC_ACTION_TERMINAL = "terminal";
+    protected static final String TRAFFIC_ACTION_SAMPLE = "sample";
+    protected static final String TRAFFIC_ACTION_RPD = "rpd";
+
+    protected static final String WIDE_COMM_FLAGS = "widecommunityFlags";
+    protected static final String WIDE_COMM_HOP_COUNT = "widecommunityHopCount";
+    protected static final String WIDE_COMM_COMMUNITY = "widecommunityCommunity";
+    protected static final String WIDE_COMM_CONTEXT_AS = "widecommunityContextAs";
+    protected static final String WIDE_COMM_LOCAL_AS = "widecommunityLocalAs";
+    protected static final String WIDE_COMM_TARGET = "widecommunityTarget";
+    protected static final String WIDE_COMM_EXT_TARGET = "widecommunityExtTarget";
+    protected static final String WIDE_COMM_PARAMETER = "widecommunityParameter";
+
+    protected static final String WIDE_COMM_TGT_LOCAL_SP = "localSpeaker";
+    protected static final String WIDE_COMM_TGT_REMOTE_SP = "remoteSpeaker";
+
+    @Override
+    public ObjectNode encode(ExtFlowTypes flowTypes, CodecContext context) {
+        return null;
+    }
+
+    @Override
+    public ExtFlowTypes decode(ObjectNode json, CodecContext context) {
+        DecodeBgpFlowExtnCodecHelper decoder = new DecodeBgpFlowExtnCodecHelper(json);
+        return decoder.decode();
+    }
+}
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpParseAttributes.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpParseAttributes.java
new file mode 100755
index 0000000..464b388
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/BgpParseAttributes.java
@@ -0,0 +1,402 @@
+/*
+ * 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.bgpweb.web;
+
+import org.onosproject.flowapi.ExtOperatorValue;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class BgpParseAttributes {
+
+    private final Logger log = getLogger(getClass());
+
+    /** Bits as per flow spec rfc 5575.*/
+    final byte endBit = (byte) 0x80;
+    final byte andBit = 0x40;
+    final byte twoByteLen = (byte) (0x01 << 4);
+    final byte fourByteLen = (byte) (0x02 << 4);
+    final byte lessThan = 0x04;
+    final byte greaterThan = 0x02;
+    final byte equal = 0x01;
+
+    /** Protocol types.*/
+    protected static final byte ICMP = 1;
+    protected static final byte IGMP = 2;
+    protected static final byte TCP = 6;
+    protected static final byte UDP = 17;
+    protected static final byte IPV4 = 4;
+    protected static final byte IPV6 = 41;
+
+    /** TCP Flags.*/
+    static final byte FIN = (1 << 0);
+    static final byte SYN = (1 << 1);
+    static final byte RST = (1 << 2);
+    static final byte PSH = (1 << 3);
+    static final byte ACK = (1 << 4);
+    static final byte URG = (1 << 5);
+
+    final byte notBit = 0x02;
+    final byte matchBit = 0x01;
+
+    /** Fragment Flags.*/
+    static final byte DF = (1 << 0);
+    static final byte IF = (1 << 1);
+    static final byte FF = (1 << 2);
+    static final byte LF = (1 << 3);
+
+    List<ExtOperatorValue> parsePort(String string) {
+        List<ExtOperatorValue> operatorValue = null;
+
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parseIpProtocol(String string) {
+        List<ExtOperatorValue> operatorValue  = null;
+
+        string = string.replaceAll("ICMP", Byte.valueOf(ICMP).toString());
+        string = string.replaceAll("icmp", Byte.valueOf(ICMP).toString());
+        string = string.replaceAll("IPv4", Byte.valueOf(IPV4).toString());
+        string = string.replaceAll("ipv4", Byte.valueOf(IPV4).toString());
+        string = string.replaceAll("TCP", Byte.valueOf(TCP).toString());
+        string = string.replaceAll("tcp", Byte.valueOf(TCP).toString());
+        string = string.replaceAll("UDP", Byte.valueOf(UDP).toString());
+        string = string.replaceAll("udp", Byte.valueOf(UDP).toString());
+        string = string.replaceAll("IPv6", Byte.valueOf(IPV6).toString());
+        string = string.replaceAll("ipv6", Byte.valueOf(IPV6).toString());
+        string = string.replaceAll("igmp", Byte.valueOf(IGMP).toString());
+        string = string.replaceAll("IGMP", Byte.valueOf(IGMP).toString());
+
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parseIcmpType(String string) {
+        List<ExtOperatorValue> operatorValue  = null;
+
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parseIcmpCode(String string) {
+        List<ExtOperatorValue> operatorValue  = null;
+
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+
+    List<ExtOperatorValue> parseTcpFlags(String string) {
+        List<ExtOperatorValue> operatorValue  = new ArrayList<>();
+        Token token;
+        int index = 0;
+
+        string = string.replaceAll("FIN", Byte.valueOf(FIN).toString());
+        string = string.replaceAll("fin", Byte.valueOf(FIN).toString());
+        string = string.replaceAll("SYN", Byte.valueOf(SYN).toString());
+        string = string.replaceAll("syn", Byte.valueOf(SYN).toString());
+        string = string.replaceAll("RST", Byte.valueOf(RST).toString());
+        string = string.replaceAll("rst", Byte.valueOf(RST).toString());
+        string = string.replaceAll("PSH", Byte.valueOf(PSH).toString());
+        string = string.replaceAll("psh", Byte.valueOf(PSH).toString());
+        string = string.replaceAll("ACK", Byte.valueOf(ACK).toString());
+        string = string.replaceAll("ack", Byte.valueOf(ACK).toString());
+        string = string.replaceAll("URG", Byte.valueOf(URG).toString());
+        string = string.replaceAll("urg", Byte.valueOf(URG).toString());
+
+        do {
+            token = parseTcpTokenValue(string, index);
+            if (token.error) {
+                log.error("Error in parsing the TCP value list");
+                return null;
+            }
+            operatorValue.add(new ExtOperatorValue(token.operator, token.value));
+            index = token.index;
+        } while ((token.operator & endBit) != endBit);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parsePacketLength(String string) {
+        List<ExtOperatorValue> operatorValue  = null;
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parseDscp(String string) {
+        List<ExtOperatorValue> operatorValue  = null;
+
+        operatorValue = createOperatorValue(string);
+
+        return operatorValue;
+    }
+
+    List<ExtOperatorValue> parseFragment(String string) {
+
+        List<ExtOperatorValue> operatorValue  = null;
+
+        string = string.replaceAll("DF", Byte.valueOf(DF).toString());
+        string = string.replaceAll("df", Byte.valueOf(DF).toString());
+        string = string.replaceAll("IF", Byte.valueOf(IF).toString());
+        string = string.replaceAll("if", Byte.valueOf(IF).toString());
+        string = string.replaceAll("FF", Byte.valueOf(FF).toString());
+        string = string.replaceAll("ff", Byte.valueOf(FF).toString());
+        string = string.replaceAll("LF", Byte.valueOf(LF).toString());
+        string = string.replaceAll("lf", Byte.valueOf(LF).toString());
+
+        operatorValue = createOperatorValue(string);
+        return operatorValue;
+    }
+
+    private class Token {
+        byte operator;
+        byte[] value;
+        int index;
+        boolean error;
+    }
+
+    List<ExtOperatorValue> createOperatorValue(String string) {
+        List<ExtOperatorValue> operatorValue  = new ArrayList<>();
+        Token token;
+        int index = 0;
+
+        do {
+            token = parseMultiTokenValue(string, index);
+            if (token.error) {
+                log.error("Error in parsing the operator value list");
+                return null;
+            }
+            operatorValue.add(new ExtOperatorValue(token.operator, token.value));
+            index = token.index;
+        } while ((token.operator & endBit) != endBit);
+
+        return operatorValue;
+    }
+
+
+    Token parseMultiTokenValue(String str, int index) {
+        Token token = new Token();
+        token.error = true;
+        int number = 0;
+        int cur = 0;
+        byte operator = 0;
+        boolean prevNumber = false;
+        boolean bLess = false;
+        boolean bGreater = false;
+        boolean bAnd = false;
+        boolean bEqual = false;
+
+        while (str.length() > index) {
+
+            switch (str.charAt(index)) {
+                case '=':
+                    if (bEqual) {
+                        return token;
+                    }
+                    bEqual = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | equal);
+                    break;
+                case '>':
+                    if (bGreater) {
+                        return token;
+                    }
+                    bGreater = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | greaterThan);
+                    break;
+                case '<':
+                    if (bLess) {
+                        return token;
+                    }
+                    bLess = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | lessThan);
+                    break;
+                case '&':
+                    if (bAnd) {
+                        return token;
+                    }
+                    bAnd = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | andBit);
+                    break;
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    prevNumber = true;
+                    bLess = false;
+                    bGreater = false;
+                    bAnd = false;
+                    bEqual = false;
+                    cur =  str.charAt(index);
+                    number = (number * 10) + cur - '0';
+                    break;
+
+                default:
+                    log.error("Error in parsing the token character" + str.charAt(index));
+                    return token;
+            }
+            index++;
+        }
+
+        if (prevNumber) {
+            return windUp(str, index, number, operator);
+        }
+
+        return token;
+    }
+
+    Token windUp(String str, int index, int number, byte operator) {
+        Token token = new Token();
+        byte[] array = new byte[1];
+
+        if (str.length() == index) {
+            operator = (byte) (operator | endBit);
+        }
+
+        if (number <= 255) {
+            array[0] = (byte) number;
+        } else if (number > 255 && number <= Short.MAX_VALUE) {
+            operator = (byte) (operator | twoByteLen);
+            array = shortToByteStream((short) number);
+        } else if (number > Short.MAX_VALUE) {
+            operator = (byte) (operator | fourByteLen);
+            array = intToByteStream(number);
+        }
+
+        token.value = array;
+        token.operator = operator;
+        token.index = index;
+        token.error = false;
+        return token;
+    }
+
+    byte[] intToByteStream(int val) {
+        return new byte[] {
+                (byte) (val >>> 24),
+                (byte) (val >>> 16),
+                (byte) (val >>> 8),
+                (byte) val};
+    }
+
+    byte[] shortToByteStream(short val) {
+        return new byte[] {
+                (byte) (val >>> 8),
+                (byte) val};
+    }
+
+    Token parseTcpTokenValue(String str, int index) {
+        Token token = new Token();
+        token.error = true;
+        int number = 0;
+        int cur = 0;
+        byte operator = 0;
+        boolean prevNumber = false;
+
+        boolean bNotBit = false;
+        boolean bAnd = false;
+        boolean bMatchBit = false;
+
+        while (str.length() > index) {
+
+            switch (str.charAt(index)) {
+                case '=':
+                    if (bMatchBit) {
+                        return token;
+                    }
+                    bMatchBit = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | matchBit);
+                    break;
+                case '!':
+                    if (bNotBit) {
+                        return token;
+                    }
+                    bNotBit = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | notBit);
+                    break;
+                case '&':
+                    if (bAnd) {
+                        return token;
+                    }
+                    bAnd = true;
+                    if (prevNumber) {
+                        return windUp(str, index, number, operator);
+                    }
+                    operator = (byte) (operator | andBit);
+                    break;
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    prevNumber = true;
+                    bNotBit = false;
+                    bAnd = false;
+                    bMatchBit = false;
+                    cur =  str.charAt(index);
+                    number = (number * 10) + cur - '0';
+                    break;
+
+                default:
+                    log.error("Error in parsing the TCP token character" + str.charAt(index));
+                    return token;
+            }
+            index++;
+        }
+
+        if (prevNumber) {
+            return windUp(str, index, number, operator);
+        }
+
+        return token;
+    }
+}
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/DecodeBgpFlowExtnCodecHelper.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/DecodeBgpFlowExtnCodecHelper.java
new file mode 100755
index 0000000..3aafde1
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/DecodeBgpFlowExtnCodecHelper.java
@@ -0,0 +1,721 @@
+/*
+ * 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.bgpweb.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.flowapi.DefaultExtDscpValue;
+import org.onosproject.flowapi.DefaultExtFragment;
+import org.onosproject.flowapi.DefaultExtIcmpCode;
+import org.onosproject.flowapi.DefaultExtIcmpType;
+import org.onosproject.flowapi.DefaultExtIpProtocol;
+import org.onosproject.flowapi.DefaultExtKeyName;
+import org.onosproject.flowapi.DefaultExtPacketLength;
+import org.onosproject.flowapi.DefaultExtPort;
+import org.onosproject.flowapi.DefaultExtPrefix;
+import org.onosproject.flowapi.DefaultExtTarget;
+import org.onosproject.flowapi.DefaultExtTcpFlag;
+import org.onosproject.flowapi.DefaultExtTrafficAction;
+import org.onosproject.flowapi.DefaultExtTrafficMarking;
+import org.onosproject.flowapi.DefaultExtTrafficRate;
+import org.onosproject.flowapi.DefaultExtTrafficRedirect;
+import org.onosproject.flowapi.DefaultExtWideCommunityInt;
+import org.onosproject.flowapi.ExtDscpValue;
+import org.onosproject.flowapi.ExtFlowTypes;
+import org.onosproject.flowapi.ExtFragment;
+import org.onosproject.flowapi.ExtIcmpCode;
+import org.onosproject.flowapi.ExtIcmpType;
+import org.onosproject.flowapi.ExtIpProtocol;
+import org.onosproject.flowapi.ExtKeyName;
+import org.onosproject.flowapi.ExtPacketLength;
+import org.onosproject.flowapi.ExtPort;
+import org.onosproject.flowapi.ExtPrefix;
+import org.onosproject.flowapi.ExtTarget;
+import org.onosproject.flowapi.ExtTcpFlag;
+import org.onosproject.flowapi.ExtTrafficAction;
+import org.onosproject.flowapi.ExtTrafficMarking;
+import org.onosproject.flowapi.ExtTrafficRate;
+import org.onosproject.flowapi.ExtTrafficRedirect;
+import org.onosproject.flowapi.ExtWideCommunityInt;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * Decode the Ext extension codec.
+ */
+public final class DecodeBgpFlowExtnCodecHelper {
+
+    private final ObjectNode json;
+
+    protected static final String MISSING_MEMBER_MESSAGE =
+            " member is required in ExtTypes";
+
+    protected static final String MALFORMED_MEMBER_MESSAGE =
+            " member is malformed";
+
+    private interface ExtensionDecoder {
+        ExtFlowTypes decodeExtension(ObjectNode json);
+    }
+
+    private final Map<String, ExtensionDecoder> decoderMap;
+
+    BgpParseAttributes parse = new BgpParseAttributes();
+
+    /**
+     * Creates a decode extension codec object.
+     * Initializes the lookup map for Bgp extension types.
+     *
+     * @param json JSON object to decode
+     */
+    public DecodeBgpFlowExtnCodecHelper(ObjectNode json) {
+        this.json = json;
+        decoderMap = new HashMap<>();
+
+        decoderMap.put(ExtFlowTypes.ExtType.IPV4_SRC_PFX.name(), new BgpSourcePrefixDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.IPV4_DST_PFX.name(), new BgpDestinationPrefixDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.EXT_FLOW_RULE_KEY.name(), new BgpFlowRuleKeyDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.IP_PROTO_LIST.name(), new BgpIpProtocolDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.IN_PORT_LIST.name(), new BgpInPortDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.DST_PORT_LIST.name(), new BgpDestinationPortDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.SRC_PORT_LIST.name(), new BgpSourcePortDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.ICMP_TYPE_LIST.name(), new BgpIcmpTypeDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.ICMP_CODE_LIST.name(), new BgpIcmpCodeDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.TCP_FLAG_LIST.name(), new BgpTcpFlagDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.PACKET_LENGTH_LIST.name(), new BgpPacketLengthDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.DSCP_VALUE_LIST.name(), new BgpDscpValueDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.FRAGMENT_LIST.name(), new BgpFragmentDecode());
+
+        decoderMap.put(ExtFlowTypes.ExtType.TRAFFIC_RATE.name(), new BgpTrafficRateDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.TRAFFIC_ACTION.name(), new BgpTrafficActionDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.TRAFFIC_REDIRECT.name(), new BgpTrafficRedirectDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.TRAFFIC_MARKING.name(), new BgpTrafficMarkingDecode());
+
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_FLAGS.name(), new BgpWcommFlagsDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_HOP_COUNT.name(), new BgpWcommHopCountDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_COMMUNITY.name(), new BgpWcommCommunityDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_CONTEXT_AS.name(), new BgpWcommContextAsDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_LOCAL_AS.name(), new BgpWcommLocalAsDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_TARGET.name(), new BgpWcommTargetDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_EXT_TARGET.name(), new BgpWcommExtTargetDecode());
+        decoderMap.put(ExtFlowTypes.ExtType.WIDE_COMM_PARAMETER.name(), new BgpWcommParameterDecode());
+    }
+
+    /** Source prefix decoder.*/
+    private class BgpSourcePrefixDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPrefix.Builder resultBuilder = new DefaultExtPrefix.Builder();
+
+            String ip = nullIsIllegal(json.get(BgpFlowExtensionCodec.PREFIX),
+                    BgpFlowExtensionCodec.PREFIX + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPrefix(IpPrefix.valueOf(ip));
+            resultBuilder.setType(ExtFlowTypes.ExtType.IPV4_SRC_PFX);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Destination prefix decoder.*/
+    private class BgpDestinationPrefixDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPrefix.Builder resultBuilder = new DefaultExtPrefix.Builder();
+
+            String ip = nullIsIllegal(json.get(BgpFlowExtensionCodec.PREFIX),
+                    BgpFlowExtensionCodec.PREFIX + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPrefix(IpPrefix.valueOf(ip));
+            resultBuilder.setType(ExtFlowTypes.ExtType.IPV4_DST_PFX);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Flow rule key decoder.*/
+    private class BgpFlowRuleKeyDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtKeyName.Builder resultBuilder = new DefaultExtKeyName.Builder();
+
+            String name = nullIsIllegal(json.get(BgpFlowExtensionCodec.NAME),
+                    BgpFlowExtensionCodec.NAME + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setKeyName(name);
+            resultBuilder.setType(ExtFlowTypes.ExtType.EXT_FLOW_RULE_KEY);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Ip protocol decoder.*/
+    private class BgpIpProtocolDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtIpProtocol.Builder resultBuilder = new DefaultExtIpProtocol.Builder();
+
+            String protocols = nullIsIllegal(json.get(BgpFlowExtensionCodec.PROTOCOLS),
+                    BgpFlowExtensionCodec.PROTOCOLS + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setIpProtocol(parse.parseIpProtocol(protocols));
+            resultBuilder.setType(ExtFlowTypes.ExtType.IP_PROTO_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** In port decoder.*/
+    private class BgpInPortDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPort.Builder resultBuilder = new DefaultExtPort.Builder();
+
+            String portList = nullIsIllegal(json.get(BgpFlowExtensionCodec.PORT),
+                    BgpFlowExtensionCodec.PORT + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPort(parse.parsePort(portList));
+            resultBuilder.setType(ExtFlowTypes.ExtType.IN_PORT_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Destination decoder.*/
+    private class BgpDestinationPortDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPort.Builder resultBuilder = new DefaultExtPort.Builder();
+
+            String portList = nullIsIllegal(json.get(BgpFlowExtensionCodec.DST_PORT),
+                    BgpFlowExtensionCodec.DST_PORT + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPort(parse.parsePort(portList));
+            resultBuilder.setType(ExtFlowTypes.ExtType.DST_PORT_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Source decoder.*/
+    private class BgpSourcePortDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPort.Builder resultBuilder = new DefaultExtPort.Builder();
+
+            String portList = nullIsIllegal(json.get(BgpFlowExtensionCodec.SRC_PORT),
+                    BgpFlowExtensionCodec.SRC_PORT + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPort(parse.parsePort(portList));
+            resultBuilder.setType(ExtFlowTypes.ExtType.SRC_PORT_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Icmp type decoder.*/
+    private class BgpIcmpTypeDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtIcmpType.Builder resultBuilder = new DefaultExtIcmpType.Builder();
+
+            String icmpType = nullIsIllegal(json.get(BgpFlowExtensionCodec.ICMP_TYPE),
+                    BgpFlowExtensionCodec.ICMP_TYPE + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setIcmpType(parse.parseIcmpType(icmpType));
+            resultBuilder.setType(ExtFlowTypes.ExtType.ICMP_TYPE_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Icmp code decoder.*/
+    private class BgpIcmpCodeDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtIcmpCode.Builder resultBuilder = new DefaultExtIcmpCode.Builder();
+
+            String icmpCode = nullIsIllegal(json.get(BgpFlowExtensionCodec.ICMP_CODE),
+                    BgpFlowExtensionCodec.ICMP_CODE + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setIcmpCode(parse.parseIcmpCode(icmpCode));
+            resultBuilder.setType(ExtFlowTypes.ExtType.ICMP_CODE_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Tcp flag decoder.*/
+    private class BgpTcpFlagDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTcpFlag.Builder resultBuilder = new DefaultExtTcpFlag.Builder();
+
+            String tcpFlag = nullIsIllegal(json.get(BgpFlowExtensionCodec.TCP_FLAG),
+                    BgpFlowExtensionCodec.TCP_FLAG + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setTcpFlag(parse.parseTcpFlags(tcpFlag));
+            resultBuilder.setType(ExtFlowTypes.ExtType.TCP_FLAG_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Packet length decoder.*/
+    private class BgpPacketLengthDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtPacketLength.Builder resultBuilder = new DefaultExtPacketLength.Builder();
+
+            String packetLength = nullIsIllegal(json.get(BgpFlowExtensionCodec.PACKET_LENGTH),
+                    BgpFlowExtensionCodec.PACKET_LENGTH + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setPacketLength(parse.parsePacketLength(packetLength));
+            resultBuilder.setType(ExtFlowTypes.ExtType.PACKET_LENGTH_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Dscp value decoder.*/
+    private class BgpDscpValueDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtDscpValue.Builder resultBuilder = new DefaultExtDscpValue.Builder();
+
+            String dscpValue = nullIsIllegal(json.get(BgpFlowExtensionCodec.DSCP_VALUE),
+                    BgpFlowExtensionCodec.DSCP_VALUE + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setDscpValue(parse.parseDscp(dscpValue));
+            resultBuilder.setType(ExtFlowTypes.ExtType.DSCP_VALUE_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Fragment decoder.*/
+    private class BgpFragmentDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtFragment.Builder resultBuilder = new DefaultExtFragment.Builder();
+
+            String fragment = nullIsIllegal(json.get(BgpFlowExtensionCodec.FRAGMENT),
+                    BgpFlowExtensionCodec.FRAGMENT + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setFragment(parse.parseFragment(fragment));
+            resultBuilder.setType(ExtFlowTypes.ExtType.FRAGMENT_LIST);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Traffic rate decoder.*/
+    private class BgpTrafficRateDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTrafficRate.Builder resultBuilder = new DefaultExtTrafficRate.Builder();
+
+            String rate = nullIsIllegal(json.get(BgpFlowExtensionCodec.TRAFFIC_RATE),
+                    BgpFlowExtensionCodec.TRAFFIC_RATE + MISSING_MEMBER_MESSAGE).asText();
+
+            String[] commaPart = rate.split(",");
+            String[] valuePart = commaPart[0].split("=");
+
+            if (valuePart[0].matches(BgpFlowExtensionCodec.TRAFFIC_RATE_ASN)) {
+                short s = Short.decode(valuePart[1].trim()).shortValue();
+                resultBuilder.setAsn(s);
+            } else {
+                nullIsIllegal(valuePart[0], BgpFlowExtensionCodec.TRAFFIC_RATE + MALFORMED_MEMBER_MESSAGE);
+            }
+
+            valuePart = commaPart[1].split("=");
+            if (valuePart[0].matches(BgpFlowExtensionCodec.TRAFFIC_RATE_RATE)) {
+                float f = Float.parseFloat(valuePart[1].trim());
+                resultBuilder.setRate(f);
+            } else {
+                nullIsIllegal(valuePart[0], BgpFlowExtensionCodec.TRAFFIC_RATE + MALFORMED_MEMBER_MESSAGE);
+            }
+
+            resultBuilder.setType(ExtFlowTypes.ExtType.TRAFFIC_RATE);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Traffic action decoder.*/
+    private class BgpTrafficActionDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTrafficAction.Builder resultBuilder = new DefaultExtTrafficAction.Builder();
+
+            String rate = nullIsIllegal(json.get(BgpFlowExtensionCodec.TRAFFIC_ACTION),
+                    BgpFlowExtensionCodec.TRAFFIC_ACTION + MISSING_MEMBER_MESSAGE).asText();
+
+            String[] commaPart = rate.split(",");
+            String[] valuePart = commaPart[0].split("=");
+
+            if (valuePart[0].matches(BgpFlowExtensionCodec.TRAFFIC_ACTION_TERMINAL)) {
+                boolean terminal = Boolean.parseBoolean(valuePart[1].trim());
+                resultBuilder.setTerminal(terminal);
+            } else {
+                nullIsIllegal(valuePart[0], BgpFlowExtensionCodec.TRAFFIC_ACTION_TERMINAL + MISSING_MEMBER_MESSAGE);
+            }
+
+            valuePart = commaPart[1].split("=");
+            if (valuePart[0].matches(BgpFlowExtensionCodec.TRAFFIC_ACTION_SAMPLE)) {
+                boolean sample = Boolean.parseBoolean(valuePart[1].trim());
+                resultBuilder.setSample(sample);
+            } else {
+                nullIsIllegal(valuePart[0], BgpFlowExtensionCodec.TRAFFIC_ACTION_SAMPLE + MISSING_MEMBER_MESSAGE);
+            }
+
+            valuePart = commaPart[2].split("=");
+            if (valuePart[0].matches(BgpFlowExtensionCodec.TRAFFIC_ACTION_RPD)) {
+                boolean rpd = Boolean.parseBoolean(valuePart[1].trim());
+                resultBuilder.setRpd(rpd);
+            } else {
+                nullIsIllegal(valuePart[0], BgpFlowExtensionCodec.TRAFFIC_ACTION_RPD + MISSING_MEMBER_MESSAGE);
+            }
+
+            resultBuilder.setType(ExtFlowTypes.ExtType.TRAFFIC_ACTION);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Traffic redirect decoder.*/
+    private class BgpTrafficRedirectDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTrafficRedirect.Builder resultBuilder = new DefaultExtTrafficRedirect.Builder();
+
+            String action = nullIsIllegal(json.get(BgpFlowExtensionCodec.TRAFFIC_REDIRECTION),
+                    BgpFlowExtensionCodec.TRAFFIC_REDIRECTION + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setRedirect(action);
+            resultBuilder.setType(ExtFlowTypes.ExtType.TRAFFIC_REDIRECT);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Traffic marking decoder.*/
+    private class BgpTrafficMarkingDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTrafficMarking.Builder resultBuilder = new DefaultExtTrafficMarking.Builder();
+
+            String action = nullIsIllegal(json.get(BgpFlowExtensionCodec.TRAFFIC_MARKING),
+                    BgpFlowExtensionCodec.TRAFFIC_MARKING + MISSING_MEMBER_MESSAGE).asText();
+
+            if ((action.length() != 1) || action.isEmpty()) {
+                nullIsIllegal(action, BgpFlowExtensionCodec.TRAFFIC_MARKING + MALFORMED_MEMBER_MESSAGE);
+            }
+
+            resultBuilder.setMarking((byte) action.charAt(0));
+            resultBuilder.setType(ExtFlowTypes.ExtType.TRAFFIC_MARKING);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community flag decoder.*/
+    private class BgpWcommFlagsDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_FLAGS),
+                    BgpFlowExtensionCodec.WIDE_COMM_FLAGS + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_FLAGS);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community hop count decoder.*/
+    private class BgpWcommHopCountDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_HOP_COUNT),
+                    BgpFlowExtensionCodec.WIDE_COMM_HOP_COUNT + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_HOP_COUNT);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community decoder.*/
+    private class BgpWcommCommunityDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_COMMUNITY),
+                    BgpFlowExtensionCodec.WIDE_COMM_COMMUNITY + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_COMMUNITY);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community context AS decoder.*/
+    private class BgpWcommContextAsDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_CONTEXT_AS),
+                    BgpFlowExtensionCodec.WIDE_COMM_CONTEXT_AS + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_CONTEXT_AS);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community local AS decoder.*/
+    private class BgpWcommLocalAsDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_LOCAL_AS),
+                    BgpFlowExtensionCodec.WIDE_COMM_LOCAL_AS + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_LOCAL_AS);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community parameter decoder.*/
+    private class BgpWcommParameterDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtWideCommunityInt.Builder resultBuilder = new DefaultExtWideCommunityInt.Builder();
+
+            String wideComm = nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_PARAMETER),
+                    BgpFlowExtensionCodec.WIDE_COMM_PARAMETER + MISSING_MEMBER_MESSAGE).asText();
+            resultBuilder.setwCommInt(Integer.valueOf(wideComm));
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_PARAMETER);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community target decoder.*/
+    private class BgpWcommTargetDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTarget.Builder resultBuilder = new DefaultExtTarget.Builder();
+
+            JsonNode jsonNodes = json.get(BgpFlowExtensionCodec.WIDE_COMM_TARGET);
+            if (jsonNodes == null) {
+                nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_TARGET),
+                        BgpFlowExtensionCodec.WIDE_COMM_TARGET + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            JsonNode array = jsonNodes.path(BgpFlowExtensionCodec.WIDE_COMM_TGT_LOCAL_SP);
+            if (array == null) {
+                nullIsIllegal(array, BgpFlowExtensionCodec.WIDE_COMM_TGT_LOCAL_SP + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            ExtPrefix.Builder resultBuilderPfx = parseIpArrayToPrefix(array);
+            resultBuilderPfx.setType(ExtFlowTypes.ExtType.IPV4_SRC_PFX);
+            resultBuilder.setLocalSpeaker(resultBuilderPfx.build());
+
+            array = jsonNodes.path(BgpFlowExtensionCodec.WIDE_COMM_TGT_REMOTE_SP);
+            if (array == null) {
+                nullIsIllegal(array, BgpFlowExtensionCodec.WIDE_COMM_TGT_REMOTE_SP + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            resultBuilderPfx = parseIpArrayToPrefix(array);
+            resultBuilderPfx.setType(ExtFlowTypes.ExtType.IPV4_DST_PFX);
+            resultBuilder.setRemoteSpeaker(resultBuilderPfx.build());
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_TARGET);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Wide community extended target decoder.*/
+    private class BgpWcommExtTargetDecode implements ExtensionDecoder {
+        @Override
+        public ExtFlowTypes decodeExtension(ObjectNode json) {
+            if (json == null || !json.isObject()) {
+                return null;
+            }
+
+            ExtTarget.Builder resultBuilder = new DefaultExtTarget.Builder();
+
+            JsonNode jsonNodes = json.get(BgpFlowExtensionCodec.WIDE_COMM_EXT_TARGET);
+            if (jsonNodes == null) {
+                nullIsIllegal(json.get(BgpFlowExtensionCodec.WIDE_COMM_EXT_TARGET),
+                        BgpFlowExtensionCodec.WIDE_COMM_EXT_TARGET + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            JsonNode array = jsonNodes.path(BgpFlowExtensionCodec.WIDE_COMM_TGT_LOCAL_SP);
+            if (array == null) {
+                nullIsIllegal(array, BgpFlowExtensionCodec.WIDE_COMM_TGT_LOCAL_SP + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            ExtPrefix.Builder resultBuilderPfx = parseIpArrayToPrefix(array);
+            resultBuilderPfx.setType(ExtFlowTypes.ExtType.IPV4_SRC_PFX);
+            resultBuilder.setLocalSpeaker(resultBuilderPfx.build());
+
+            array = jsonNodes.path(BgpFlowExtensionCodec.WIDE_COMM_TGT_REMOTE_SP);
+            if (array == null) {
+                nullIsIllegal(array, BgpFlowExtensionCodec.WIDE_COMM_TGT_REMOTE_SP + MISSING_MEMBER_MESSAGE).asText();
+            }
+
+            resultBuilderPfx = parseIpArrayToPrefix(array);
+            resultBuilderPfx.setType(ExtFlowTypes.ExtType.IPV4_DST_PFX);
+            resultBuilder.setRemoteSpeaker(resultBuilderPfx.build());
+            resultBuilder.setType(ExtFlowTypes.ExtType.WIDE_COMM_EXT_TARGET);
+
+            return resultBuilder.build();
+        }
+    }
+
+    /** Ip address parser decoder.*/
+    public ExtPrefix.Builder parseIpArrayToPrefix(JsonNode array) {
+
+        ExtPrefix.Builder resultBuilder = new DefaultExtPrefix.Builder();
+        String ip;
+        IpPrefix prefix;
+        IpAddress ipAddr;
+
+        Iterator<JsonNode> itr =  array.iterator();
+        while (itr.hasNext()) {
+            ip = itr.next().asText();
+            ipAddr = IpAddress.valueOf(ip);
+            prefix = IpPrefix.valueOf(ipAddr, 32);
+            resultBuilder.setPrefix(prefix);
+        }
+
+        return resultBuilder;
+    }
+
+    /**
+     * Decodes the JSON into a BgpFlowType extension object.
+     *
+     * @return ExtFlowTypes object
+     * @throws IllegalArgumentException if the JSON is invalid
+     */
+    public ExtFlowTypes decode() {
+        String type = json.get(BgpFlowExtensionCodec.TYPE).asText();
+
+        ExtensionDecoder decoder = decoderMap.get(type);
+        if (decoder != null) {
+            return decoder.decodeExtension(json);
+        }
+
+        throw new IllegalArgumentException("Type " + type + " is unknown");
+    }
+}
diff --git a/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/package-info.java b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/package-info.java
new file mode 100755
index 0000000..2f6d844
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/java/org/onosproject/bgpweb/web/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-prensent 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.
+ */
+
+/**
+ * Codec for bgp flow.
+ */
+package org.onosproject.bgpweb.web;
diff --git a/apps/bgpflowspec/bgpweb/src/main/webapp/WEB-INF/web.xml b/apps/bgpflowspec/bgpweb/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..2a13327
--- /dev/null
+++ b/apps/bgpflowspec/bgpweb/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?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.
+  -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         id="ONOS" version="2.5">
+    <display-name>BGP REST API v1.0</display-name>
+
+
+    <servlet>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.onosproject.bgpweb.resources.BgpWebApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>